diff --git a/pki/templates.go b/pki/templates.go index 44d4a7b0..6c3e888a 100644 --- a/pki/templates.go +++ b/pki/templates.go @@ -11,77 +11,13 @@ import ( "github.com/smallstep/cli/utils" ) -// SSHTemplates contains the configuration of default templates used on ssh. -// Relative paths are relative to the StepPath. -var SSHTemplates = &templates.SSHTemplates{ - User: []templates.Template{ - {Name: "include.tpl", Type: templates.Snippet, TemplatePath: "templates/ssh/include.tpl", Path: "~/.ssh/config", Comment: "#"}, - {Name: "config.tpl", Type: templates.File, TemplatePath: "templates/ssh/config.tpl", Path: "ssh/config", Comment: "#"}, - {Name: "known_hosts.tpl", Type: templates.File, TemplatePath: "templates/ssh/known_hosts.tpl", Path: "ssh/known_hosts", Comment: "#"}, - }, - Host: []templates.Template{ - {Name: "sshd_config.tpl", Type: templates.Snippet, TemplatePath: "templates/ssh/sshd_config.tpl", Path: "/etc/ssh/sshd_config", Comment: "#"}, - {Name: "ca.tpl", Type: templates.Snippet, TemplatePath: "templates/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. - // - // Note: on windows `Include C:\...` is treated as a relative path. - "include.tpl": `Host * -{{- if or .User.GOOS "none" | eq "windows" }} - Include "{{ .User.StepPath | replace "\\" "/" | trimPrefix "C:" }}/ssh/config" -{{- else }} - Include "{{.User.StepPath}}/ssh/config" -{{- end }}`, - - // config.tpl is the step ssh config file, it includes the Match rule and - // references the step known_hosts file. - // - // Note: on windows ProxyCommand requires the full path - "config.tpl": `Match exec "step ssh check-host %h" -{{- if .User.User }} - User {{.User.User}} -{{- end }} -{{- if or .User.GOOS "none" | eq "windows" }} - UserKnownHostsFile "{{.User.StepPath}}\ssh\known_hosts" - ProxyCommand C:\Windows\System32\cmd.exe /c step ssh proxycommand %r %h %p -{{- else }} - UserKnownHostsFile "{{.User.StepPath}}/ssh/known_hosts" - ProxyCommand step ssh proxycommand %r %h %p -{{- end }} -`, - - // known_hosts.tpl authorizes the ssh hosts key - "known_hosts.tpl": `@cert-authority * {{.Step.SSH.HostKey.Type}} {{.Step.SSH.HostKey.Marshal | toString | b64enc}} -{{- range .Step.SSH.HostFederatedKeys}} -@cert-authority * {{.Type}} {{.Marshal | toString | b64enc}} -{{- end }} -`, - - // 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}} -{{- range .Step.SSH.UserFederatedKeys}} -{{.Type}} {{.Marshal | toString | b64enc}} -{{- end }} -`, -} - // getTemplates returns all the templates enabled func (p *PKI) getTemplates() *templates.Templates { if !p.enableSSH { return nil } - return &templates.Templates{ - SSH: SSHTemplates, + SSH: &templates.DefaultSSHTemplates, Data: map[string]interface{}{}, } } @@ -104,7 +40,7 @@ func generateTemplates(t *templates.Templates) error { } // Create all templates for _, t := range t.SSH.User { - data, ok := SSHTemplateData[t.Name] + data, ok := templates.DefaultSSHTemplateData[t.Name] if !ok { return errors.Errorf("template %s does not exists", t.Name) } @@ -113,7 +49,7 @@ func generateTemplates(t *templates.Templates) error { } } for _, t := range t.SSH.Host { - data, ok := SSHTemplateData[t.Name] + data, ok := templates.DefaultSSHTemplateData[t.Name] if !ok { return errors.Errorf("template %s does not exists", t.Name) } diff --git a/templates/values.go b/templates/values.go index ba03267b..1ecd7ea3 100644 --- a/templates/values.go +++ b/templates/values.go @@ -16,3 +16,112 @@ type StepSSH struct { HostFederatedKeys []ssh.PublicKey UserFederatedKeys []ssh.PublicKey } + +// DefaultSSHTemplates contains the configuration of default templates used on ssh. +// Relative paths are relative to the StepPath. +var DefaultSSHTemplates = SSHTemplates{ + User: []Template{ + { + Name: "include.tpl", + Type: Snippet, + TemplatePath: "templates/ssh/include.tpl", + Path: "~/.ssh/config", + Comment: "#", + }, + { + Name: "config.tpl", + Type: File, + TemplatePath: "templates/ssh/config.tpl", + Path: "ssh/config", + Comment: "#", + }, + { + Name: "known_hosts.tpl", + Type: File, + TemplatePath: "templates/ssh/known_hosts.tpl", + Path: "ssh/known_hosts", + Comment: "#", + }, + }, + Host: []Template{ + { + Name: "sshd_config.tpl", + Type: Snippet, + TemplatePath: "templates/ssh/sshd_config.tpl", + Path: "/etc/ssh/sshd_config", + Comment: "#", + RequiredData: []string{"Certificate", "Key"}, + }, + { + Name: "ca.tpl", + Type: Snippet, + TemplatePath: "templates/ssh/ca.tpl", + Path: "/etc/ssh/ca.pub", + Comment: "#", + }, + }, +} + +// DefaultSSHTemplateData contains the data of the default templates used on ssh. +var DefaultSSHTemplateData = map[string]string{ + // include.tpl adds the step ssh config file. + // + // Note: on windows `Include C:\...` is treated as a relative path. + "include.tpl": `Host * +{{- if or .User.GOOS "none" | eq "windows" }} + Include "{{ .User.StepPath | replace "\\" "/" | trimPrefix "C:" }}/ssh/config" +{{- else }} + Include "{{.User.StepPath}}/ssh/config" +{{- end }}`, + + // config.tpl is the step ssh config file, it includes the Match rule and + // references the step known_hosts file. + // + // Note: on windows ProxyCommand requires the full path + "config.tpl": `Match exec "step ssh check-host %h" +{{- if .User.User }} + User {{.User.User}} +{{- end }} +{{- if or .User.GOOS "none" | eq "windows" }} + UserKnownHostsFile "{{.User.StepPath}}\ssh\known_hosts" + ProxyCommand C:\Windows\System32\cmd.exe /c step ssh proxycommand %r %h %p +{{- else }} + UserKnownHostsFile "{{.User.StepPath}}/ssh/known_hosts" + ProxyCommand step ssh proxycommand %r %h %p +{{- end }} +`, + + // known_hosts.tpl authorizes the ssh hosts key + "known_hosts.tpl": `@cert-authority * {{.Step.SSH.HostKey.Type}} {{.Step.SSH.HostKey.Marshal | toString | b64enc}} +{{- range .Step.SSH.HostFederatedKeys}} +@cert-authority * {{.Type}} {{.Marshal | toString | b64enc}} +{{- end }} +`, + + // 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}} +{{- range .Step.SSH.UserFederatedKeys}} +{{.Type}} {{.Marshal | toString | b64enc}} +{{- end }} +`, +} + +// DefaultTemplates returns the default templates. +func DefaultTemplates() *Templates { + sshTemplates := DefaultSSHTemplates + for i, t := range sshTemplates.User { + sshTemplates.User[i].Content = []byte(DefaultSSHTemplateData[t.Name]) + } + for i, t := range sshTemplates.Host { + sshTemplates.Host[i].Content = []byte(DefaultSSHTemplateData[t.Name]) + } + return &Templates{ + SSH: &sshTemplates, + Data: map[string]interface{}{}, + } +}