Add first version of ssh templates.
This commit is contained in:
parent
505da52279
commit
0b5abcf3b0
2 changed files with 116 additions and 3 deletions
18
pki/pki.go
18
pki/pki.go
|
@ -434,6 +434,7 @@ func (p *PKI) GenerateConfig(opt ...Option) (*authority.Config, error) {
|
||||||
Renegotiation: x509util.DefaultTLSRenegotiation,
|
Renegotiation: x509util.DefaultTLSRenegotiation,
|
||||||
CipherSuites: x509util.DefaultTLSCipherSuites,
|
CipherSuites: x509util.DefaultTLSCipherSuites,
|
||||||
},
|
},
|
||||||
|
Templates: p.getTemplates(),
|
||||||
}
|
}
|
||||||
if p.enableSSH {
|
if p.enableSSH {
|
||||||
enableSSHCA := true
|
enableSSHCA := true
|
||||||
|
@ -461,6 +462,7 @@ func (p *PKI) GenerateConfig(opt ...Option) (*authority.Config, error) {
|
||||||
func (p *PKI) Save(opt ...Option) error {
|
func (p *PKI) Save(opt ...Option) error {
|
||||||
p.tellPKI()
|
p.tellPKI()
|
||||||
|
|
||||||
|
// Generate and write ca.json
|
||||||
config, err := p.GenerateConfig(opt...)
|
config, err := p.GenerateConfig(opt...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -489,6 +491,7 @@ func (p *PKI) Save(opt ...Option) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate and write defaults.json
|
||||||
defaults := &caDefaults{
|
defaults := &caDefaults{
|
||||||
Root: p.root,
|
Root: p.root,
|
||||||
CAConfig: p.config,
|
CAConfig: p.config,
|
||||||
|
@ -503,11 +506,20 @@ func (p *PKI) Save(opt ...Option) error {
|
||||||
return errs.FileError(err, p.defaults)
|
return errs.FileError(err, p.defaults)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate and write templates
|
||||||
|
if err := generateTemplates(config.Templates); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.DB != nil {
|
||||||
|
ui.PrintSelected("Database folder", config.DB.DataSource)
|
||||||
|
}
|
||||||
|
if config.Templates != nil {
|
||||||
|
ui.PrintSelected("Templates folder", GetTemplatesPath())
|
||||||
|
}
|
||||||
|
|
||||||
ui.PrintSelected("Default configuration", p.defaults)
|
ui.PrintSelected("Default configuration", p.defaults)
|
||||||
ui.PrintSelected("Certificate Authority configuration", p.config)
|
ui.PrintSelected("Certificate Authority configuration", p.config)
|
||||||
if config.DB != nil {
|
|
||||||
ui.PrintSelected("Database", config.DB.DataSource)
|
|
||||||
}
|
|
||||||
ui.Println()
|
ui.Println()
|
||||||
ui.Println("Your PKI is ready to go. To generate certificates for individual services see 'step help ca'.")
|
ui.Println("Your PKI is ready to go. To generate certificates for individual services see 'step help ca'.")
|
||||||
|
|
||||||
|
|
101
pki/templates.go
Normal file
101
pki/templates.go
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
package pki
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/smallstep/cli/utils"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/smallstep/certificates/templates"
|
||||||
|
"github.com/smallstep/cli/errs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// sshTemplates contains the configuration of default templates used on ssh.
|
||||||
|
var sshTemplates = &templates.SSHTemplates{
|
||||||
|
User: []templates.Template{
|
||||||
|
{Name: "include.tpl", Type: templates.Snippet, TemplatePath: "ssh/include.tpl", Path: "~/.ssh/config", Comment: "#"},
|
||||||
|
{Name: "config.tpl", Type: templates.File, TemplatePath: "ssh/config.tpl", Path: "ssh/config", Comment: "#"},
|
||||||
|
{Name: "known_hosts.tpl", Type: templates.File, TemplatePath: "ssh/known_hosts.tpl", Path: "ssh/known_hosts", Comment: "#"},
|
||||||
|
},
|
||||||
|
Host: []templates.Template{
|
||||||
|
{Name: "sshd_config.tpl", Type: templates.Snippet, TemplatePath: "ssh/sshd_config.tpl", Path: "/etc/ssh/sshd_config", Comment: "#"},
|
||||||
|
{Name: "ca.tpl", Type: templates.Snippet, TemplatePath: "ssh/ca.tpl", Path: "/etc/ssh/ca.pub", Comment: "#"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// sshTemplateData contains the data of the default templates used on ssh.
|
||||||
|
var sshTemplateData = map[string]string{
|
||||||
|
// include.tpl adds the step ssh config file
|
||||||
|
"include.tpl": `Host *
|
||||||
|
Include {{.User.StepPath}}/ssh/config`,
|
||||||
|
|
||||||
|
// config.tpl is the step ssh config file, it includes the Match rule
|
||||||
|
// and references the step known_hosts file
|
||||||
|
"config.tpl": `Match exec "step ssh check-host %h"
|
||||||
|
ForwardAgent yes
|
||||||
|
UserKnownHostsFile {{.User.StepPath}}/config/ssh/known_hosts`,
|
||||||
|
|
||||||
|
// known_hosts.tpl authorizes the ssh hosst key
|
||||||
|
"known_hosts.tpl": "@cert-authority * {{.Step.SSH.HostKey.Type}} {{.Step.SSH.HostKey.Marshal | toString | b64enc}}",
|
||||||
|
|
||||||
|
// sshd_config.tpl adds the configuration to support certificates
|
||||||
|
"sshd_config.tpl": `TrustedUserCAKeys /etc/ssh/ca.pub
|
||||||
|
HostCertificate /etc/ssh/{{.User.Certificate}}
|
||||||
|
HostKey /etc/ssh/{{.User.Key}}`,
|
||||||
|
|
||||||
|
// ca.tpl contains the public key used to authorized clients
|
||||||
|
"ca.tpl": "{{.Step.SSH.UserKey.Type}} {{.Step.SSH.UserKey.Marshal | toString | b64enc}}",
|
||||||
|
}
|
||||||
|
|
||||||
|
// getTemplates returns all the templates enabled
|
||||||
|
func (p *PKI) getTemplates() *templates.Templates {
|
||||||
|
if !p.enableSSH {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &templates.Templates{
|
||||||
|
SSH: sshTemplates,
|
||||||
|
Data: map[string]interface{}{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateTemplates generates given templates.
|
||||||
|
func generateTemplates(t *templates.Templates) error {
|
||||||
|
if t == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
base := GetTemplatesPath()
|
||||||
|
// Generate SSH templates
|
||||||
|
if t.SSH != nil {
|
||||||
|
// all ssh templates are under ssh:
|
||||||
|
sshDir := filepath.Join(base, "ssh")
|
||||||
|
if _, err := os.Stat(sshDir); os.IsNotExist(err) {
|
||||||
|
if err = os.MkdirAll(sshDir, 0700); err != nil {
|
||||||
|
return errs.FileError(err, sshDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Create all templates
|
||||||
|
for _, t := range t.SSH.User {
|
||||||
|
data, ok := sshTemplateData[t.Name]
|
||||||
|
if !ok {
|
||||||
|
return errors.Errorf("template %s does not exists", t.Name)
|
||||||
|
}
|
||||||
|
if err := utils.WriteFile(filepath.Join(base, t.TemplatePath), []byte(data), 0644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, t := range t.SSH.Host {
|
||||||
|
data, ok := sshTemplateData[t.Name]
|
||||||
|
if !ok {
|
||||||
|
return errors.Errorf("template %s does not exists", t.Name)
|
||||||
|
}
|
||||||
|
if err := utils.WriteFile(filepath.Join(base, t.TemplatePath), []byte(data), 0644); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in a new issue