From 741ac64c6128e5b6941b91e22f9ad9f8203467f2 Mon Sep 17 00:00:00 2001 From: max furman Date: Thu, 5 Aug 2021 14:00:58 -0700 Subject: [PATCH 01/24] change name of package cli-utils/config to cli-utils/step --- ca/identity/identity.go | 10 +++++----- go.mod | 11 +++++++---- templates/templates.go | 8 ++++---- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/ca/identity/identity.go b/ca/identity/identity.go index 0f022dd7..14a22eb9 100644 --- a/ca/identity/identity.go +++ b/ca/identity/identity.go @@ -16,7 +16,7 @@ import ( "github.com/pkg/errors" "github.com/smallstep/certificates/api" - "go.step.sm/cli-utils/config" + "go.step.sm/cli-utils/step" "go.step.sm/crypto/pemutil" ) @@ -40,10 +40,10 @@ const TunnelTLS Type = "tTLS" const DefaultLeeway = 1 * time.Minute // IdentityFile contains the location of the identity file. -var IdentityFile = filepath.Join(config.StepPath(), "config", "identity.json") +var IdentityFile = filepath.Join(step.Path(), "config", "identity.json") // DefaultsFile contains the location of the defaults file. -var DefaultsFile = filepath.Join(config.StepPath(), "config", "defaults.json") +var DefaultsFile = filepath.Join(step.Path(), "config", "defaults.json") // Identity represents the identity file that can be used to authenticate with // the CA. @@ -80,8 +80,8 @@ func LoadDefaultIdentity() (*Identity, error) { // configDir and identityDir are used in WriteDefaultIdentity for testing // purposes. var ( - configDir = filepath.Join(config.StepPath(), "config") - identityDir = filepath.Join(config.StepPath(), "identity") + configDir = filepath.Join(step.Path(), "config") + identityDir = filepath.Join(step.Path(), "identity") ) // WriteDefaultIdentity writes the given certificates and key and the diff --git a/go.mod b/go.mod index 5f234b7a..3b7c0f3a 100644 --- a/go.mod +++ b/go.mod @@ -44,7 +44,10 @@ require ( gopkg.in/square/go-jose.v2 v2.6.0 ) -// replace github.com/smallstep/nosql => ../nosql -// replace go.step.sm/crypto => ../crypto -// replace go.step.sm/cli-utils => ../cli-utils -// replace go.step.sm/linkedca => ../linkedca +//replace github.com/smallstep/nosql => ../nosql + +//replace go.step.sm/crypto => ../crypto + +replace go.step.sm/cli-utils => ../cli-utils + +replace go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 => github.com/omorsi/pkcs7 v0.0.0-20210217142924-a7b80a2a8568 diff --git a/templates/templates.go b/templates/templates.go index 09416b68..4fb831d4 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -10,8 +10,8 @@ import ( "github.com/Masterminds/sprig/v3" "github.com/pkg/errors" - "go.step.sm/cli-utils/config" "go.step.sm/cli-utils/fileutil" + "go.step.sm/cli-utils/step" ) // TemplateType defines how a template will be written in disk. @@ -132,7 +132,7 @@ func (t *Template) Validate() error { if t.TemplatePath != "" { // Check for file - st, err := os.Stat(config.StepAbs(t.TemplatePath)) + st, err := os.Stat(step.Abs(t.TemplatePath)) if err != nil { return errors.Wrapf(err, "error reading %s", t.TemplatePath) } @@ -166,7 +166,7 @@ func (t *Template) Load() error { if t.Template == nil && t.Type != Directory { switch { case t.TemplatePath != "": - filename := config.StepAbs(t.TemplatePath) + filename := step.Abs(t.TemplatePath) b, err := ioutil.ReadFile(filename) if err != nil { return errors.Wrapf(err, "error reading %s", filename) @@ -247,7 +247,7 @@ type Output struct { // Write writes the Output to the filesystem as a directory, file or snippet. func (o *Output) Write() error { - path := config.StepAbs(o.Path) + path := step.Abs(o.Path) if o.Type == Directory { return mkdir(path, 0700) } From 10db335f13899857ae546f91ae0080af21f86124 Mon Sep 17 00:00:00 2001 From: max furman Date: Tue, 10 Aug 2021 00:38:30 -0700 Subject: [PATCH 02/24] mv pkg config -> step --- ca/client.go | 4 ++-- cmd/step-ca/main.go | 6 +++--- pki/pki.go | 16 ++++++++-------- pki/templates.go | 6 +++--- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ca/client.go b/ca/client.go index cfeddba0..aa1e38dd 100644 --- a/ca/client.go +++ b/ca/client.go @@ -29,7 +29,7 @@ import ( "github.com/smallstep/certificates/authority/provisioner" "github.com/smallstep/certificates/ca/identity" "github.com/smallstep/certificates/errs" - "go.step.sm/cli-utils/config" + "go.step.sm/cli-utils/step" "go.step.sm/crypto/jose" "go.step.sm/crypto/keyutil" "go.step.sm/crypto/pemutil" @@ -1295,7 +1295,7 @@ func createCertificateRequest(commonName string, sans []string, key crypto.Priva // getRootCAPath returns the path where the root CA is stored based on the // STEPPATH environment variable. func getRootCAPath() string { - return filepath.Join(config.StepPath(), "certs", "root_ca.crt") + return filepath.Join(step.Path(), "certs", "root_ca.crt") } func readJSON(r io.ReadCloser, v interface{}) error { diff --git a/cmd/step-ca/main.go b/cmd/step-ca/main.go index 01d800d8..f40ddf5f 100644 --- a/cmd/step-ca/main.go +++ b/cmd/step-ca/main.go @@ -21,7 +21,7 @@ import ( "github.com/urfave/cli" "go.step.sm/cli-utils/command" "go.step.sm/cli-utils/command/version" - "go.step.sm/cli-utils/config" + "go.step.sm/cli-utils/step" "go.step.sm/cli-utils/ui" "go.step.sm/cli-utils/usage" @@ -49,7 +49,7 @@ var ( ) func init() { - config.Set("Smallstep CA", Version, BuildTime) + step.Set("Smallstep CA", Version, BuildTime) authority.GlobalVersion.Version = Version rand.Seed(time.Now().UnixNano()) } @@ -115,7 +115,7 @@ func main() { app := cli.NewApp() app.Name = "step-ca" app.HelpName = "step-ca" - app.Version = config.Version() + app.Version = step.Version() app.Usage = "an online certificate authority for secure automated certificate management" app.UsageText = `**step-ca** [**--password-file**=] [**--ssh-host-password-file**=] [**--ssh-user-password-file**=] diff --git a/pki/pki.go b/pki/pki.go index 61e20b6b..5f2afedd 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -29,9 +29,9 @@ import ( "github.com/smallstep/certificates/kms" kmsapi "github.com/smallstep/certificates/kms/apiv1" "github.com/smallstep/nosql" - "go.step.sm/cli-utils/config" "go.step.sm/cli-utils/errs" "go.step.sm/cli-utils/fileutil" + "go.step.sm/cli-utils/step" "go.step.sm/cli-utils/ui" "go.step.sm/crypto/jose" "go.step.sm/crypto/pemutil" @@ -89,42 +89,42 @@ const ( // GetDBPath returns the path where the file-system persistence is stored // based on the STEPPATH environment variable. func GetDBPath() string { - return filepath.Join(config.StepPath(), dbPath) + return filepath.Join(step.Path(), dbPath) } // GetConfigPath returns the directory where the configuration files are stored // based on the STEPPATH environment variable. func GetConfigPath() string { - return filepath.Join(config.StepPath(), configPath) + return filepath.Join(step.Path(), configPath) } // GetPublicPath returns the directory where the public keys are stored based on // the STEPPATH environment variable. func GetPublicPath() string { - return filepath.Join(config.StepPath(), publicPath) + return filepath.Join(step.Path(), publicPath) } // GetSecretsPath returns the directory where the private keys are stored based // on the STEPPATH environment variable. func GetSecretsPath() string { - return filepath.Join(config.StepPath(), privatePath) + return filepath.Join(step.Path(), privatePath) } // GetRootCAPath returns the path where the root CA is stored based on the // STEPPATH environment variable. func GetRootCAPath() string { - return filepath.Join(config.StepPath(), publicPath, "root_ca.crt") + return filepath.Join(step.Path(), publicPath, "root_ca.crt") } // GetOTTKeyPath returns the path where the one-time token key is stored based // on the STEPPATH environment variable. func GetOTTKeyPath() string { - return filepath.Join(config.StepPath(), privatePath, "ott_key") + return filepath.Join(step.Path(), privatePath, "ott_key") } // GetTemplatesPath returns the path where the templates are stored. func GetTemplatesPath() string { - return filepath.Join(config.StepPath(), templatesPath) + return filepath.Join(step.Path(), templatesPath) } // GetProvisioners returns the map of provisioners on the given CA. diff --git a/pki/templates.go b/pki/templates.go index 3506a96d..0ccbed8b 100644 --- a/pki/templates.go +++ b/pki/templates.go @@ -6,9 +6,9 @@ import ( "github.com/pkg/errors" "github.com/smallstep/certificates/templates" - "go.step.sm/cli-utils/config" "go.step.sm/cli-utils/errs" "go.step.sm/cli-utils/fileutil" + "go.step.sm/cli-utils/step" ) // getTemplates returns all the templates enabled @@ -44,7 +44,7 @@ func generateTemplates(t *templates.Templates) error { if !ok { return errors.Errorf("template %s does not exists", t.Name) } - if err := fileutil.WriteFile(config.StepAbs(t.TemplatePath), []byte(data), 0644); err != nil { + if err := fileutil.WriteFile(step.Abs(t.TemplatePath), []byte(data), 0644); err != nil { return err } } @@ -53,7 +53,7 @@ func generateTemplates(t *templates.Templates) error { if !ok { return errors.Errorf("template %s does not exists", t.Name) } - if err := fileutil.WriteFile(config.StepAbs(t.TemplatePath), []byte(data), 0644); err != nil { + if err := fileutil.WriteFile(step.Abs(t.TemplatePath), []byte(data), 0644); err != nil { return err } } From 7eeebca529cfdf914101a89c23e762b72816651f Mon Sep 17 00:00:00 2001 From: max furman Date: Fri, 13 Aug 2021 00:16:41 -0700 Subject: [PATCH 03/24] Enable step path contexts in identity and pki paths --- ca/identity/identity.go | 8 ++++---- pki/pki.go | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/ca/identity/identity.go b/ca/identity/identity.go index 14a22eb9..7d80ef70 100644 --- a/ca/identity/identity.go +++ b/ca/identity/identity.go @@ -40,10 +40,10 @@ const TunnelTLS Type = "tTLS" const DefaultLeeway = 1 * time.Minute // IdentityFile contains the location of the identity file. -var IdentityFile = filepath.Join(step.Path(), "config", "identity.json") +var IdentityFile = filepath.Join(step.ProfilePath(), "config", "identity.json") // DefaultsFile contains the location of the defaults file. -var DefaultsFile = filepath.Join(step.Path(), "config", "defaults.json") +var DefaultsFile = filepath.Join(step.ProfilePath(), "config", "defaults.json") // Identity represents the identity file that can be used to authenticate with // the CA. @@ -80,8 +80,8 @@ func LoadDefaultIdentity() (*Identity, error) { // configDir and identityDir are used in WriteDefaultIdentity for testing // purposes. var ( - configDir = filepath.Join(step.Path(), "config") - identityDir = filepath.Join(step.Path(), "identity") + configDir = filepath.Join(step.ProfilePath(), "config") + identityDir = filepath.Join(step.ProfilePath(), "identity") ) // WriteDefaultIdentity writes the given certificates and key and the diff --git a/pki/pki.go b/pki/pki.go index 5f2afedd..b0f2c886 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -10,6 +10,7 @@ import ( "encoding/json" "encoding/pem" "fmt" + "io/ioutil" "net" "os" "path/filepath" @@ -98,6 +99,12 @@ func GetConfigPath() string { return filepath.Join(step.Path(), configPath) } +// GetProfileConfigPath returns the directory where the profile configuration +// files are stored based on the STEPPATH environment variable. +func GetProfileConfigPath() string { + return filepath.Join(step.ProfilePath(), configPath) +} + // GetPublicPath returns the directory where the public keys are stored based on // the STEPPATH environment variable. func GetPublicPath() string { @@ -367,6 +374,21 @@ func New(o apiv1.Options, opts ...Option) (*PKI, error) { } } + // Create profile directory and stub for default profile configuration. + if currentCtx := step.GetCurrentContext(); currentCtx != nil { + profile := GetProfileConfigPath() + if err := os.MkdirAll(profile, 0700); err != nil { + return nil, errs.FileError(err, profile) + } + if p.profileDefaults, err = getPath(profile, "defaults.json"); err != nil { + return nil, err + } + if err := ioutil.WriteFile(p.profileDefaults, + []byte("{}"), 0600); err != nil { + return nil, err + } + } + if p.Defaults.CaUrl == "" { p.Defaults.CaUrl = p.DnsNames[0] _, port, err := net.SplitHostPort(p.Address) @@ -958,6 +980,9 @@ func (p *PKI) Save(opt ...ConfigOption) error { } ui.PrintSelected("Default configuration", p.defaults) + if p.profileDefaults != "" { + ui.PrintSelected("Profile default configuration", p.profileDefaults) + } ui.PrintSelected("Certificate Authority configuration", p.config) if p.options.deploymentType != LinkedDeployment { ui.Println() From ed4b56732e00cf1ed34e377641a98a959a4e3bc3 Mon Sep 17 00:00:00 2001 From: max furman Date: Mon, 18 Oct 2021 13:56:24 -0700 Subject: [PATCH 04/24] updates after rebase to keep up with master --- authority/export.go | 6 +++--- authority/provisioners.go | 6 +++--- pki/pki.go | 21 +++++++++++---------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/authority/export.go b/authority/export.go index 8a5a257f..dce52292 100644 --- a/authority/export.go +++ b/authority/export.go @@ -9,7 +9,7 @@ import ( "github.com/pkg/errors" "github.com/smallstep/certificates/authority/provisioner" - "go.step.sm/cli-utils/config" + "go.step.sm/cli-utils/step" "go.step.sm/linkedca" "google.golang.org/protobuf/types/known/structpb" ) @@ -245,7 +245,7 @@ func mustReadFileOrURI(fn string, m map[string][]byte) string { return "" } - stepPath := filepath.ToSlash(config.StepPath()) + stepPath := filepath.ToSlash(step.Path()) if !strings.HasSuffix(stepPath, "/") { stepPath += "/" } @@ -257,7 +257,7 @@ func mustReadFileOrURI(fn string, m map[string][]byte) string { panic(err) } if ok { - b, err := ioutil.ReadFile(config.StepAbs(fn)) + b, err := ioutil.ReadFile(step.Abs(fn)) if err != nil { panic(errors.Wrapf(err, "error reading %s", fn)) } diff --git a/authority/provisioners.go b/authority/provisioners.go index 7e02126f..8aebcc3e 100644 --- a/authority/provisioners.go +++ b/authority/provisioners.go @@ -13,7 +13,7 @@ import ( "github.com/smallstep/certificates/authority/config" "github.com/smallstep/certificates/authority/provisioner" "github.com/smallstep/certificates/errs" - step "go.step.sm/cli-utils/config" + "go.step.sm/cli-utils/step" "go.step.sm/cli-utils/ui" "go.step.sm/crypto/jose" "go.step.sm/linkedca" @@ -523,7 +523,7 @@ func provisionerOptionsToLinkedca(p *provisioner.Options) (*linkedca.Template, * if p.X509.Template != "" { x509Template.Template = []byte(p.SSH.Template) } else if p.X509.TemplateFile != "" { - filename := step.StepAbs(p.X509.TemplateFile) + filename := step.Abs(p.X509.TemplateFile) if x509Template.Template, err = ioutil.ReadFile(filename); err != nil { return nil, nil, errors.Wrap(err, "error reading x509 template") } @@ -539,7 +539,7 @@ func provisionerOptionsToLinkedca(p *provisioner.Options) (*linkedca.Template, * if p.SSH.Template != "" { sshTemplate.Template = []byte(p.SSH.Template) } else if p.SSH.TemplateFile != "" { - filename := step.StepAbs(p.SSH.TemplateFile) + filename := step.Abs(p.SSH.TemplateFile) if sshTemplate.Template, err = ioutil.ReadFile(filename); err != nil { return nil, nil, errors.Wrap(err, "error reading ssh template") } diff --git a/pki/pki.go b/pki/pki.go index b0f2c886..8bc07dae 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -293,16 +293,17 @@ func WithKeyURIs(rootKey, intermediateKey, hostKey, userKey string) Option { // PKI represents the Public Key Infrastructure used by a certificate authority. type PKI struct { linkedca.Configuration - Defaults linkedca.Defaults - casOptions apiv1.Options - caService apiv1.CertificateAuthorityService - caCreator apiv1.CertificateAuthorityCreator - keyManager kmsapi.KeyManager - config string - defaults string - ottPublicKey *jose.JSONWebKey - ottPrivateKey *jose.JSONWebEncryption - options *options + Defaults linkedca.Defaults + casOptions apiv1.Options + caService apiv1.CertificateAuthorityService + caCreator apiv1.CertificateAuthorityCreator + keyManager kmsapi.KeyManager + config string + defaults string + profileDefaults string + ottPublicKey *jose.JSONWebKey + ottPrivateKey *jose.JSONWebEncryption + options *options } // New creates a new PKI configuration. From e5951fd84c0a043965e9533f4a12b89070dfa37f Mon Sep 17 00:00:00 2001 From: max furman Date: Wed, 20 Oct 2021 12:41:24 -0700 Subject: [PATCH 05/24] Use methods in the step package * rather than variables set at execution time, which may not match the actual current context --- ca/identity/client.go | 14 ++++++++------ ca/identity/identity.go | 30 +++++++++++++----------------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/ca/identity/client.go b/ca/identity/client.go index 4377638f..6f862115 100644 --- a/ca/identity/client.go +++ b/ca/identity/client.go @@ -10,6 +10,7 @@ import ( "net/url" "github.com/pkg/errors" + "go.step.sm/cli-utils/step" ) // Client wraps http.Client with a transport using the step root and identity. @@ -27,21 +28,22 @@ func (c *Client) ResolveReference(ref *url.URL) *url.URL { // $STEPPATH/config/defaults.json and the identity defined in // $STEPPATH/config/identity.json func LoadClient() (*Client, error) { - b, err := ioutil.ReadFile(DefaultsFile) + defaultsFile := step.DefaultsFile() + b, err := ioutil.ReadFile(defaultsFile) if err != nil { - return nil, errors.Wrapf(err, "error reading %s", DefaultsFile) + return nil, errors.Wrapf(err, "error reading %s", defaultsFile) } var defaults defaultsConfig if err := json.Unmarshal(b, &defaults); err != nil { - return nil, errors.Wrapf(err, "error unmarshaling %s", DefaultsFile) + return nil, errors.Wrapf(err, "error unmarshaling %s", defaultsFile) } if err := defaults.Validate(); err != nil { - return nil, errors.Wrapf(err, "error validating %s", DefaultsFile) + return nil, errors.Wrapf(err, "error validating %s", defaultsFile) } caURL, err := url.Parse(defaults.CaURL) if err != nil { - return nil, errors.Wrapf(err, "error validating %s", DefaultsFile) + return nil, errors.Wrapf(err, "error validating %s", defaultsFile) } if caURL.Scheme == "" { caURL.Scheme = "https" @@ -52,7 +54,7 @@ func LoadClient() (*Client, error) { return nil, err } if err := identity.Validate(); err != nil { - return nil, errors.Wrapf(err, "error validating %s", IdentityFile) + return nil, errors.Wrapf(err, "error validating %s", step.IdentityFile()) } if kind := identity.Kind(); kind != MutualTLS { return nil, errors.Errorf("unsupported identity %s: only mTLS is currently supported", kind) diff --git a/ca/identity/identity.go b/ca/identity/identity.go index 7d80ef70..e8760c50 100644 --- a/ca/identity/identity.go +++ b/ca/identity/identity.go @@ -39,12 +39,6 @@ const TunnelTLS Type = "tTLS" // DefaultLeeway is the duration for matching not before claims. const DefaultLeeway = 1 * time.Minute -// IdentityFile contains the location of the identity file. -var IdentityFile = filepath.Join(step.ProfilePath(), "config", "identity.json") - -// DefaultsFile contains the location of the defaults file. -var DefaultsFile = filepath.Join(step.ProfilePath(), "config", "defaults.json") - // Identity represents the identity file that can be used to authenticate with // the CA. type Identity struct { @@ -74,23 +68,25 @@ func LoadIdentity(filename string) (*Identity, error) { // LoadDefaultIdentity loads the default identity. func LoadDefaultIdentity() (*Identity, error) { - return LoadIdentity(IdentityFile) + return LoadIdentity(step.IdentityFile()) } -// configDir and identityDir are used in WriteDefaultIdentity for testing -// purposes. -var ( - configDir = filepath.Join(step.ProfilePath(), "config") - identityDir = filepath.Join(step.ProfilePath(), "identity") -) +func profileConfigDir() string { + return filepath.Join(step.ProfilePath(), "config") +} + +func profileIdentityDir() string { + return filepath.Join(step.ProfilePath(), "identity") +} // WriteDefaultIdentity writes the given certificates and key and the // identity.json pointing to the new files. func WriteDefaultIdentity(certChain []api.Certificate, key crypto.PrivateKey) error { - if err := os.MkdirAll(configDir, 0700); err != nil { + if err := os.MkdirAll(profileConfigDir(), 0700); err != nil { return errors.Wrap(err, "error creating config directory") } + identityDir := profileIdentityDir() if err := os.MkdirAll(identityDir, 0700); err != nil { return errors.Wrap(err, "error creating identity directory") } @@ -127,7 +123,7 @@ func WriteDefaultIdentity(certChain []api.Certificate, key crypto.PrivateKey) er }); err != nil { return errors.Wrap(err, "error writing identity json") } - if err := ioutil.WriteFile(IdentityFile, buf.Bytes(), 0600); err != nil { + if err := ioutil.WriteFile(step.IdentityFile(), buf.Bytes(), 0600); err != nil { return errors.Wrap(err, "error writing identity certificate") } @@ -136,7 +132,7 @@ func WriteDefaultIdentity(certChain []api.Certificate, key crypto.PrivateKey) er // WriteIdentityCertificate writes the identity certificate to disk. func WriteIdentityCertificate(certChain []api.Certificate) error { - filename := filepath.Join(identityDir, "identity.crt") + filename := filepath.Join(profileIdentityDir(), "identity.crt") return writeCertificate(filename, certChain) } @@ -319,7 +315,7 @@ func (i *Identity) Renew(client Renewer) error { return errors.Wrap(err, "error encoding identity certificate") } } - certFilename := filepath.Join(identityDir, "identity.crt") + certFilename := filepath.Join(profileIdentityDir(), "identity.crt") if err := ioutil.WriteFile(certFilename, buf.Bytes(), 0600); err != nil { return errors.Wrap(err, "error writing identity certificate") } From d777fc23c26ab9d3347bdfe060e036a8ea1dab38 Mon Sep 17 00:00:00 2001 From: max furman Date: Thu, 28 Oct 2021 23:58:18 -0700 Subject: [PATCH 06/24] Add ca.WithInsecure and use methods for file names --- ca/client.go | 13 ++++++++++++- ca/identity/identity.go | 4 ++-- pki/pki.go | 7 ++----- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/ca/client.go b/ca/client.go index aa1e38dd..9bcf1eb4 100644 --- a/ca/client.go +++ b/ca/client.go @@ -226,7 +226,7 @@ func (o *clientOptions) getTransport(endpoint string) (tr http.RoundTripper, err return tr, nil } -// WithTransport adds a custom transport to the Client. It will fail if a +// WithTransport adds a custom transport to the Client. It will fail if a // previous option to create the transport has been configured. func WithTransport(tr http.RoundTripper) ClientOption { return func(o *clientOptions) error { @@ -238,6 +238,17 @@ func WithTransport(tr http.RoundTripper) ClientOption { } } +// WithInsecure adds a insecure transport that bypasses TLS verification. +func WithInsecure() ClientOption { + return func(o *clientOptions) error { + o.transport = &http.Transport{ + Proxy: http.ProxyFromEnvironment, + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + return nil + } +} + // WithRootFile will create the transport using the given root certificate. It // will fail if a previous option to create the transport has been configured. func WithRootFile(filename string) ClientOption { diff --git a/ca/identity/identity.go b/ca/identity/identity.go index e8760c50..c294d982 100644 --- a/ca/identity/identity.go +++ b/ca/identity/identity.go @@ -72,11 +72,11 @@ func LoadDefaultIdentity() (*Identity, error) { } func profileConfigDir() string { - return filepath.Join(step.ProfilePath(), "config") + return filepath.Join(step.Path(), "config") } func profileIdentityDir() string { - return filepath.Join(step.ProfilePath(), "identity") + return filepath.Join(step.Path(), "identity") } // WriteDefaultIdentity writes the given certificates and key and the diff --git a/pki/pki.go b/pki/pki.go index 8bc07dae..ae6b712c 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -376,15 +376,12 @@ func New(o apiv1.Options, opts ...Option) (*PKI, error) { } // Create profile directory and stub for default profile configuration. - if currentCtx := step.GetCurrentContext(); currentCtx != nil { + if currentCtx := step.Contexts().GetCurrent(); currentCtx != nil { profile := GetProfileConfigPath() if err := os.MkdirAll(profile, 0700); err != nil { return nil, errs.FileError(err, profile) } - if p.profileDefaults, err = getPath(profile, "defaults.json"); err != nil { - return nil, err - } - if err := ioutil.WriteFile(p.profileDefaults, + if err := ioutil.WriteFile(step.ProfileDefaultsFile(), []byte("{}"), 0600); err != nil { return nil, err } From b080b7582bbceee5d9ab5ad3fb0dd784dc276a51 Mon Sep 17 00:00:00 2001 From: max furman Date: Tue, 9 Nov 2021 15:26:34 -0800 Subject: [PATCH 07/24] Template updates to support multiple SSH include snippets --- templates/templates.go | 20 ++++++++++++++------ templates/values.go | 11 +++++++---- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/templates/templates.go b/templates/templates.go index 4fb831d4..aa77a2ff 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -20,6 +20,8 @@ type TemplateType string const ( // Snippet will mark a template as a part of a file. Snippet TemplateType = "snippet" + // FullSnippet will mark a template that includes header and footer as a part of a file. + FullSnippet TemplateType = "fullSnippet" // File will mark a templates as a full file. File TemplateType = "file" // Directory will mark a template as a directory. @@ -99,7 +101,7 @@ func (t *SSHTemplates) Validate() (err error) { return } -// Template represents on template file. +// Template represents a template file. type Template struct { *template.Template Name string `json:"name"` @@ -118,8 +120,8 @@ func (t *Template) Validate() error { return nil case t.Name == "": return errors.New("template name cannot be empty") - case t.Type != Snippet && t.Type != File && t.Type != Directory: - return errors.Errorf("invalid template type %s, it must be %s, %s, or %s", t.Type, Snippet, File, Directory) + case t.Type != Snippet && t.Type != File && t.Type != Directory && t.Type != FullSnippet: + return errors.Errorf("invalid template type %s, it must be %s, %s, %s, or %s", t.Type, Snippet, FullSnippet, File, Directory) case t.TemplatePath == "" && t.Type != Directory && len(t.Content) == 0: return errors.New("template template cannot be empty") case t.TemplatePath != "" && t.Type == Directory: @@ -257,11 +259,17 @@ func (o *Output) Write() error { return err } - if o.Type == File { + switch o.Type { + case File: return fileutil.WriteFile(path, o.Content, 0600) + case Snippet: + return fileutil.WriteSnippet(path, o.Content, 0600) + case FullSnippet: + lines := strings.Split(string(o.Content), "\n") + return fileutil.WriteFullSnippet(path, o.Content, lines[0], lines[len(lines)-1], 0600) + default: + return errors.Errorf("unexpected output template type %s", string(o.Type)) } - - return fileutil.WriteSnippet(path, o.Content, 0600) } func mkdir(path string, perm os.FileMode) error { diff --git a/templates/values.go b/templates/values.go index 972b1d55..0117cf52 100644 --- a/templates/values.go +++ b/templates/values.go @@ -23,7 +23,7 @@ var DefaultSSHTemplates = SSHTemplates{ User: []Template{ { Name: "include.tpl", - Type: Snippet, + Type: FullSnippet, TemplatePath: "templates/ssh/include.tpl", Path: "~/.ssh/config", Comment: "#", @@ -67,18 +67,21 @@ 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 * + "include.tpl": `{{- if .User.Authority }}# {{ .User.Authority }} +{{ end }}# autogenerated by step +# @ {{ now }} +Host * {{- if or .User.GOOS "none" | eq "windows" }} Include "{{ .User.StepPath | replace "\\" "/" | trimPrefix "C:" }}/ssh/config" {{- else }} Include "{{.User.StepPath}}/ssh/config" -{{- end }}`, +{{ end }}# 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" + "config.tpl": `Match exec "step ssh{{- if .User.Context }} --context {{ .User.Context }}{{- end }} check-host %h" {{- if .User.User }} User {{.User.User}} {{- end }} From da74fa2eb9c3d03917012265664772062c360349 Mon Sep 17 00:00:00 2001 From: max furman Date: Tue, 9 Nov 2021 17:25:03 -0800 Subject: [PATCH 08/24] Rename FullSnippet to Fragment and remove unused replace in go.mod --- go.mod | 2 -- templates/templates.go | 12 ++++++------ templates/values.go | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 3b7c0f3a..346e0102 100644 --- a/go.mod +++ b/go.mod @@ -49,5 +49,3 @@ require ( //replace go.step.sm/crypto => ../crypto replace go.step.sm/cli-utils => ../cli-utils - -replace go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 => github.com/omorsi/pkcs7 v0.0.0-20210217142924-a7b80a2a8568 diff --git a/templates/templates.go b/templates/templates.go index aa77a2ff..bfc5b596 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -20,8 +20,8 @@ type TemplateType string const ( // Snippet will mark a template as a part of a file. Snippet TemplateType = "snippet" - // FullSnippet will mark a template that includes header and footer as a part of a file. - FullSnippet TemplateType = "fullSnippet" + // Fragment will mark a template that includes header and footer as a part of a file. + Fragment TemplateType = "fragment" // File will mark a templates as a full file. File TemplateType = "file" // Directory will mark a template as a directory. @@ -120,8 +120,8 @@ func (t *Template) Validate() error { return nil case t.Name == "": return errors.New("template name cannot be empty") - case t.Type != Snippet && t.Type != File && t.Type != Directory && t.Type != FullSnippet: - return errors.Errorf("invalid template type %s, it must be %s, %s, %s, or %s", t.Type, Snippet, FullSnippet, File, Directory) + case t.Type != Snippet && t.Type != File && t.Type != Directory && t.Type != Fragment: + return errors.Errorf("invalid template type %s, it must be %s, %s, %s, or %s", t.Type, Snippet, Fragment, File, Directory) case t.TemplatePath == "" && t.Type != Directory && len(t.Content) == 0: return errors.New("template template cannot be empty") case t.TemplatePath != "" && t.Type == Directory: @@ -264,9 +264,9 @@ func (o *Output) Write() error { return fileutil.WriteFile(path, o.Content, 0600) case Snippet: return fileutil.WriteSnippet(path, o.Content, 0600) - case FullSnippet: + case Fragment: lines := strings.Split(string(o.Content), "\n") - return fileutil.WriteFullSnippet(path, o.Content, lines[0], lines[len(lines)-1], 0600) + return fileutil.WriteFragment(path, o.Content, lines[0], lines[len(lines)-1], 0600) default: return errors.Errorf("unexpected output template type %s", string(o.Type)) } diff --git a/templates/values.go b/templates/values.go index 0117cf52..3749f9f0 100644 --- a/templates/values.go +++ b/templates/values.go @@ -23,7 +23,7 @@ var DefaultSSHTemplates = SSHTemplates{ User: []Template{ { Name: "include.tpl", - Type: FullSnippet, + Type: Fragment, TemplatePath: "templates/ssh/include.tpl", Path: "~/.ssh/config", Comment: "#", From 74eea883434a78f89544804336e8e0f9aa78a7a4 Mon Sep 17 00:00:00 2001 From: max furman Date: Wed, 10 Nov 2021 00:42:57 -0800 Subject: [PATCH 09/24] Replace Fragment template with Line --- templates/templates.go | 13 ++++++------ templates/values.go | 45 +++++++++++++++++++++++++++++------------- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/templates/templates.go b/templates/templates.go index bfc5b596..ab0f1040 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -20,8 +20,8 @@ type TemplateType string const ( // Snippet will mark a template as a part of a file. Snippet TemplateType = "snippet" - // Fragment will mark a template that includes header and footer as a part of a file. - Fragment TemplateType = "fragment" + // Line is a template for a single line in a file. + Line TemplateType = "line" // File will mark a templates as a full file. File TemplateType = "file" // Directory will mark a template as a directory. @@ -120,8 +120,8 @@ func (t *Template) Validate() error { return nil case t.Name == "": return errors.New("template name cannot be empty") - case t.Type != Snippet && t.Type != File && t.Type != Directory && t.Type != Fragment: - return errors.Errorf("invalid template type %s, it must be %s, %s, %s, or %s", t.Type, Snippet, Fragment, File, Directory) + case t.Type != Snippet && t.Type != File && t.Type != Directory && t.Type != Line: + return errors.Errorf("invalid template type %s, it must be %s, %s, %s, or %s", t.Type, Snippet, Line, File, Directory) case t.TemplatePath == "" && t.Type != Directory && len(t.Content) == 0: return errors.New("template template cannot be empty") case t.TemplatePath != "" && t.Type == Directory: @@ -264,9 +264,8 @@ func (o *Output) Write() error { return fileutil.WriteFile(path, o.Content, 0600) case Snippet: return fileutil.WriteSnippet(path, o.Content, 0600) - case Fragment: - lines := strings.Split(string(o.Content), "\n") - return fileutil.WriteFragment(path, o.Content, lines[0], lines[len(lines)-1], 0600) + case Line: + return fileutil.WriteLine(path, o.Content, 0600) default: return errors.Errorf("unexpected output template type %s", string(o.Type)) } diff --git a/templates/values.go b/templates/values.go index 3749f9f0..60c0ad8f 100644 --- a/templates/values.go +++ b/templates/values.go @@ -22,12 +22,19 @@ type StepSSH struct { var DefaultSSHTemplates = SSHTemplates{ User: []Template{ { - Name: "include.tpl", - Type: Fragment, - TemplatePath: "templates/ssh/include.tpl", + Name: "base_config.tpl", + Type: Snippet, + TemplatePath: "templates/ssh/base_config.tpl", Path: "~/.ssh/config", Comment: "#", }, + { + Name: "include.tpl", + Type: Line, + TemplatePath: "templates/ssh/include.tpl", + Path: "~/.ssh/include", + Comment: "#", + }, { Name: "config.tpl", Type: File, @@ -64,18 +71,28 @@ var DefaultSSHTemplates = SSHTemplates{ // DefaultSSHTemplateData contains the data of the default templates used on ssh. var DefaultSSHTemplateData = map[string]string{ + // base_config.tpl adds the step ssh config file. + // + // Note: on windows `Include C:\...` is treated as a relative path. + "base_config.tpl": `Host * +{{- if or .User.GOOS "none" | eq "windows" }} +{{- if .User.Authority }} + Include "{{ .User.Home | replace "\\" "/" | trimPrefix "C:" }}/.ssh/include" +{{- else }} + Include "{{ .User.StepPath | replace "\\" "/" | trimPrefix "C:" }}/ssh/config" +{{- end }} +{{- else }} +{{- if .User.Authority }} + Include "{{.User.Home}}/.ssh/include" +{{- else }} + Include "{{.User.StepPath}}/ssh/config" +{{- end }} +{{- end }}`, + // include.tpl adds the step ssh config file. // // Note: on windows `Include C:\...` is treated as a relative path. - "include.tpl": `{{- if .User.Authority }}# {{ .User.Authority }} -{{ end }}# autogenerated by step -# @ {{ now }} -Host * -{{- if or .User.GOOS "none" | eq "windows" }} - Include "{{ .User.StepPath | replace "\\" "/" | trimPrefix "C:" }}/ssh/config" -{{- else }} - Include "{{.User.StepPath}}/ssh/config" -{{ end }}# end`, + "include.tpl": `{{- 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. @@ -87,10 +104,10 @@ Host * {{- 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 + ProxyCommand C:\Windows\System32\cmd.exe /c step ssh proxycommand{{- if .User.Context }} --context {{ .User.Context }}{{- end }} %r %h %p {{- else }} UserKnownHostsFile "{{.User.StepPath}}/ssh/known_hosts" - ProxyCommand step ssh proxycommand %r %h %p + ProxyCommand step ssh proxycommand{{- if .User.Context }} --context {{ .User.Context }}{{- end }} %r %h %p {{- end }} `, From 9d4a7cf9fcd4dc155f373dfed3ac7b3db406746d Mon Sep 17 00:00:00 2001 From: max furman Date: Wed, 10 Nov 2021 14:53:44 -0800 Subject: [PATCH 10/24] Update includes template to use STEPPATH as the replace var --- templates/templates.go | 3 +++ templates/values.go | 14 +++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/templates/templates.go b/templates/templates.go index ab0f1040..3a708731 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -249,6 +249,9 @@ type Output struct { // Write writes the Output to the filesystem as a directory, file or snippet. func (o *Output) Write() error { + // Replace ${STEPPATH} with the base step path. + o.Path = strings.Replace(o.Path, "${STEPPATH}", step.BasePath(), -1) + path := step.Abs(o.Path) if o.Type == Directory { return mkdir(path, 0700) diff --git a/templates/values.go b/templates/values.go index 60c0ad8f..c59843af 100644 --- a/templates/values.go +++ b/templates/values.go @@ -29,10 +29,10 @@ var DefaultSSHTemplates = SSHTemplates{ Comment: "#", }, { - Name: "include.tpl", + Name: "includes.tpl", Type: Line, - TemplatePath: "templates/ssh/include.tpl", - Path: "~/.ssh/include", + TemplatePath: "templates/ssh/includes.tpl", + Path: "${STEPPATH}/ssh/includes", Comment: "#", }, { @@ -77,22 +77,22 @@ var DefaultSSHTemplateData = map[string]string{ "base_config.tpl": `Host * {{- if or .User.GOOS "none" | eq "windows" }} {{- if .User.Authority }} - Include "{{ .User.Home | replace "\\" "/" | trimPrefix "C:" }}/.ssh/include" + Include "{{ .User.StepBasePath | replace "\\" "/" | trimPrefix "C:" }}/ssh/includes" {{- else }} Include "{{ .User.StepPath | replace "\\" "/" | trimPrefix "C:" }}/ssh/config" {{- end }} {{- else }} {{- if .User.Authority }} - Include "{{.User.Home}}/.ssh/include" + Include "{{.User.StepBasePath}}/ssh/includes" {{- else }} Include "{{.User.StepPath}}/ssh/config" {{- end }} {{- end }}`, - // include.tpl adds the step ssh config file. + // includes.tpl adds the step ssh config file. // // Note: on windows `Include C:\...` is treated as a relative path. - "include.tpl": `{{- if or .User.GOOS "none" | eq "windows" }}Include "{{ .User.StepPath | replace "\\" "/" | trimPrefix "C:" }}/ssh/config"{{- else }}Include "{{.User.StepPath}}/ssh/config"{{- end }}`, + "includes.tpl": `{{- 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. From c8560b4854766f920ff10f5668b9f4dfa322425d Mon Sep 17 00:00:00 2001 From: max furman Date: Wed, 10 Nov 2021 23:23:10 -0800 Subject: [PATCH 11/24] updated method name in cli-utils --- templates/templates.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/templates.go b/templates/templates.go index 3a708731..e760f0a4 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -268,7 +268,7 @@ func (o *Output) Write() error { case Snippet: return fileutil.WriteSnippet(path, o.Content, 0600) case Line: - return fileutil.WriteLine(path, o.Content, 0600) + return fileutil.PrependLine(path, o.Content, 0600) default: return errors.Errorf("unexpected output template type %s", string(o.Type)) } From 3e9830e36322e5387ae4fe48b2c6f129384188d4 Mon Sep 17 00:00:00 2001 From: max furman Date: Thu, 11 Nov 2021 13:49:32 -0800 Subject: [PATCH 12/24] Use profileDefaults in PKI - write profile defaults at the same time as authority defaults --- pki/pki.go | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/pki/pki.go b/pki/pki.go index ae6b712c..58f256b1 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -10,7 +10,6 @@ import ( "encoding/json" "encoding/pem" "fmt" - "io/ioutil" "net" "os" "path/filepath" @@ -99,12 +98,6 @@ func GetConfigPath() string { return filepath.Join(step.Path(), configPath) } -// GetProfileConfigPath returns the directory where the profile configuration -// files are stored based on the STEPPATH environment variable. -func GetProfileConfigPath() string { - return filepath.Join(step.ProfilePath(), configPath) -} - // GetPublicPath returns the directory where the public keys are stored based on // the STEPPATH environment variable. func GetPublicPath() string { @@ -375,18 +368,6 @@ func New(o apiv1.Options, opts ...Option) (*PKI, error) { } } - // Create profile directory and stub for default profile configuration. - if currentCtx := step.Contexts().GetCurrent(); currentCtx != nil { - profile := GetProfileConfigPath() - if err := os.MkdirAll(profile, 0700); err != nil { - return nil, errs.FileError(err, profile) - } - if err := ioutil.WriteFile(step.ProfileDefaultsFile(), - []byte("{}"), 0600); err != nil { - return nil, err - } - } - if p.Defaults.CaUrl == "" { p.Defaults.CaUrl = p.DnsNames[0] _, port, err := net.SplitHostPort(p.Address) @@ -435,6 +416,10 @@ func New(o apiv1.Options, opts ...Option) (*PKI, error) { if p.defaults, err = getPath(cfg, "defaults.json"); err != nil { return nil, err } + if c := step.Contexts().GetCurrent(); c != nil { + p.profileDefaults = c.ProfileDefaultsFile() + } + if p.config, err = getPath(cfg, "ca.json"); err != nil { return nil, err } @@ -964,6 +949,11 @@ func (p *PKI) Save(opt ...ConfigOption) error { if err = fileutil.WriteFile(p.defaults, b, 0644); err != nil { return errs.FileError(err, p.defaults) } + if p.profileDefaults != "" { + if err = fileutil.WriteFile(p.profileDefaults, []byte("{}"), 0644); err != nil { + return errs.FileError(err, p.profileDefaults) + } + } // Generate and write templates if err := generateTemplates(cfg.Templates); err != nil { @@ -979,7 +969,7 @@ func (p *PKI) Save(opt ...ConfigOption) error { ui.PrintSelected("Default configuration", p.defaults) if p.profileDefaults != "" { - ui.PrintSelected("Profile default configuration", p.profileDefaults) + ui.PrintSelected("Default profile configuration", p.profileDefaults) } ui.PrintSelected("Certificate Authority configuration", p.config) if p.options.deploymentType != LinkedDeployment { From 43cba993bbe3abc68275a2fac1a2353b2091f255 Mon Sep 17 00:00:00 2001 From: max furman Date: Thu, 11 Nov 2021 22:05:47 -0800 Subject: [PATCH 13/24] PR fixes - Line -> PrependLine - dont' overwrite profileDefaults - update ssh/config.tpl to always include includes file --- pki/pki.go | 6 +++++- templates/templates.go | 11 ++++++----- templates/values.go | 22 +++++++++++----------- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/pki/pki.go b/pki/pki.go index 58f256b1..ea2da61e 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -950,7 +950,11 @@ func (p *PKI) Save(opt ...ConfigOption) error { return errs.FileError(err, p.defaults) } if p.profileDefaults != "" { - if err = fileutil.WriteFile(p.profileDefaults, []byte("{}"), 0644); err != nil { + if _, err := os.Stat(p.profileDefaults); os.IsNotExist(err) { + if err = fileutil.WriteFile(p.profileDefaults, []byte("{}"), 0644); err != nil { + return errs.FileError(err, p.profileDefaults) + } + } else if err != nil { return errs.FileError(err, p.profileDefaults) } } diff --git a/templates/templates.go b/templates/templates.go index e760f0a4..dee7aa5f 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -20,8 +20,9 @@ type TemplateType string const ( // Snippet will mark a template as a part of a file. Snippet TemplateType = "snippet" - // Line is a template for a single line in a file. - Line TemplateType = "line" + // PrependLine is a template for prepending a single line to a file. If the + // line already exists in the file it will be removed first. + PrependLine TemplateType = "prepend-line" // File will mark a templates as a full file. File TemplateType = "file" // Directory will mark a template as a directory. @@ -120,8 +121,8 @@ func (t *Template) Validate() error { return nil case t.Name == "": return errors.New("template name cannot be empty") - case t.Type != Snippet && t.Type != File && t.Type != Directory && t.Type != Line: - return errors.Errorf("invalid template type %s, it must be %s, %s, %s, or %s", t.Type, Snippet, Line, File, Directory) + case t.Type != Snippet && t.Type != File && t.Type != Directory && t.Type != PrependLine: + return errors.Errorf("invalid template type %s, it must be %s, %s, %s, or %s", t.Type, Snippet, PrependLine, File, Directory) case t.TemplatePath == "" && t.Type != Directory && len(t.Content) == 0: return errors.New("template template cannot be empty") case t.TemplatePath != "" && t.Type == Directory: @@ -267,7 +268,7 @@ func (o *Output) Write() error { return fileutil.WriteFile(path, o.Content, 0600) case Snippet: return fileutil.WriteSnippet(path, o.Content, 0600) - case Line: + case PrependLine: return fileutil.PrependLine(path, o.Content, 0600) default: return errors.Errorf("unexpected output template type %s", string(o.Type)) diff --git a/templates/values.go b/templates/values.go index c59843af..c5e3f291 100644 --- a/templates/values.go +++ b/templates/values.go @@ -22,23 +22,23 @@ type StepSSH struct { var DefaultSSHTemplates = SSHTemplates{ User: []Template{ { - Name: "base_config.tpl", + Name: "config.tpl", Type: Snippet, - TemplatePath: "templates/ssh/base_config.tpl", + TemplatePath: "templates/ssh/config.tpl", Path: "~/.ssh/config", Comment: "#", }, { - Name: "includes.tpl", - Type: Line, - TemplatePath: "templates/ssh/includes.tpl", + Name: "step_includes.tpl", + Type: PrependLine, + TemplatePath: "templates/ssh/step_includes.tpl", Path: "${STEPPATH}/ssh/includes", Comment: "#", }, { - Name: "config.tpl", + Name: "step_config.tpl", Type: File, - TemplatePath: "templates/ssh/config.tpl", + TemplatePath: "templates/ssh/step_config.tpl", Path: "ssh/config", Comment: "#", }, @@ -76,16 +76,16 @@ var DefaultSSHTemplateData = map[string]string{ // Note: on windows `Include C:\...` is treated as a relative path. "base_config.tpl": `Host * {{- if or .User.GOOS "none" | eq "windows" }} -{{- if .User.Authority }} +{{- if .User.StepBasePath }} Include "{{ .User.StepBasePath | replace "\\" "/" | trimPrefix "C:" }}/ssh/includes" {{- else }} - Include "{{ .User.StepPath | replace "\\" "/" | trimPrefix "C:" }}/ssh/config" + Include "{{ .User.StepPath | replace "\\" "/" | trimPrefix "C:" }}/ssh/includes" {{- end }} {{- else }} -{{- if .User.Authority }} +{{- if .User.StepBasePath }} Include "{{.User.StepBasePath}}/ssh/includes" {{- else }} - Include "{{.User.StepPath}}/ssh/config" + Include "{{.User.StepPath}}/ssh/includes" {{- end }} {{- end }}`, From fcc15174ea7062736e6040cd97a83e9c261c6d40 Mon Sep 17 00:00:00 2001 From: max furman Date: Thu, 11 Nov 2021 22:28:25 -0800 Subject: [PATCH 14/24] Rename templates and create profileConfig dir ahead of time. --- pki/pki.go | 26 ++++++++++++++++++-------- templates/values.go | 6 +++--- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/pki/pki.go b/pki/pki.go index ea2da61e..0c9d91e8 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -87,37 +87,43 @@ const ( ) // GetDBPath returns the path where the file-system persistence is stored -// based on the STEPPATH environment variable. +// based on the $(step path). func GetDBPath() string { return filepath.Join(step.Path(), dbPath) } // GetConfigPath returns the directory where the configuration files are stored -// based on the STEPPATH environment variable. +// based on the $(step path). func GetConfigPath() string { return filepath.Join(step.Path(), configPath) } +// GetProfileConfigPath returns the directory where the profile configuration +// files are stored based on the $(step path). +func GetProfileConfigPath() string { + return filepath.Join(step.ProfilePath(), configPath) +} + // GetPublicPath returns the directory where the public keys are stored based on -// the STEPPATH environment variable. +// the $(step path). func GetPublicPath() string { return filepath.Join(step.Path(), publicPath) } // GetSecretsPath returns the directory where the private keys are stored based -// on the STEPPATH environment variable. +// on the $(step path). func GetSecretsPath() string { return filepath.Join(step.Path(), privatePath) } // GetRootCAPath returns the path where the root CA is stored based on the -// STEPPATH environment variable. +// $(step path). func GetRootCAPath() string { return filepath.Join(step.Path(), publicPath, "root_ca.crt") } // GetOTTKeyPath returns the path where the one-time token key is stored based -// on the STEPPATH environment variable. +// on the $(step path). func GetOTTKeyPath() string { return filepath.Join(step.Path(), privatePath, "ott_key") } @@ -301,6 +307,7 @@ type PKI struct { // New creates a new PKI configuration. func New(o apiv1.Options, opts ...Option) (*PKI, error) { + currentCtx := step.Contexts().GetCurrent() caService, err := cas.New(context.Background(), o) if err != nil { return nil, err @@ -359,6 +366,9 @@ func New(o apiv1.Options, opts ...Option) (*PKI, error) { cfg = GetConfigPath() // Create directories dirs := []string{public, private, cfg, GetTemplatesPath()} + if currentCtx != nil { + dirs = append(dirs, GetProfileConfigPath()) + } for _, name := range dirs { if _, err := os.Stat(name); os.IsNotExist(err) { if err = os.MkdirAll(name, 0700); err != nil { @@ -416,8 +426,8 @@ func New(o apiv1.Options, opts ...Option) (*PKI, error) { if p.defaults, err = getPath(cfg, "defaults.json"); err != nil { return nil, err } - if c := step.Contexts().GetCurrent(); c != nil { - p.profileDefaults = c.ProfileDefaultsFile() + if currentCtx != nil { + p.profileDefaults = currentCtx.ProfileDefaultsFile() } if p.config, err = getPath(cfg, "ca.json"); err != nil { diff --git a/templates/values.go b/templates/values.go index c5e3f291..7a8e1765 100644 --- a/templates/values.go +++ b/templates/values.go @@ -74,7 +74,7 @@ var DefaultSSHTemplateData = map[string]string{ // base_config.tpl adds the step ssh config file. // // Note: on windows `Include C:\...` is treated as a relative path. - "base_config.tpl": `Host * + "config.tpl": `Host * {{- if or .User.GOOS "none" | eq "windows" }} {{- if .User.StepBasePath }} Include "{{ .User.StepBasePath | replace "\\" "/" | trimPrefix "C:" }}/ssh/includes" @@ -92,13 +92,13 @@ var DefaultSSHTemplateData = map[string]string{ // includes.tpl adds the step ssh config file. // // Note: on windows `Include C:\...` is treated as a relative path. - "includes.tpl": `{{- if or .User.GOOS "none" | eq "windows" }}Include "{{ .User.StepPath | replace "\\" "/" | trimPrefix "C:" }}/ssh/config"{{- else }}Include "{{.User.StepPath}}/ssh/config"{{- end }}`, + "step_includes.tpl": `{{- 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{{- if .User.Context }} --context {{ .User.Context }}{{- end }} check-host %h" + "step_config.tpl": `Match exec "step ssh{{- if .User.Context }} --context {{ .User.Context }}{{- end }} check-host %h" {{- if .User.User }} User {{.User.User}} {{- end }} From c80a64d0e6673d32161fb5d11944ccfd29c7b9bf Mon Sep 17 00:00:00 2001 From: max furman Date: Thu, 11 Nov 2021 22:51:46 -0800 Subject: [PATCH 15/24] ssh/step_config.tpl context flag in wrong spot --- templates/values.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/values.go b/templates/values.go index 7a8e1765..3cace69d 100644 --- a/templates/values.go +++ b/templates/values.go @@ -98,7 +98,7 @@ var DefaultSSHTemplateData = map[string]string{ // references the step known_hosts file. // // Note: on windows ProxyCommand requires the full path - "step_config.tpl": `Match exec "step ssh{{- if .User.Context }} --context {{ .User.Context }}{{- end }} check-host %h" + "step_config.tpl": `Match exec "step ssh check-host{{- if .User.Context }} --context {{ .User.Context }}{{- end }} %h" {{- if .User.User }} User {{.User.User}} {{- end }} From f426c152a935dd9d3e8624785fc6591c80720765 Mon Sep 17 00:00:00 2001 From: max furman Date: Fri, 12 Nov 2021 13:12:11 -0800 Subject: [PATCH 16/24] backwards compatibility for version of cli older than v0.18.0 --- authority/ssh.go | 7 +++++++ templates/templates.go | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/authority/ssh.go b/authority/ssh.go index 762319ae..da93acaf 100644 --- a/authority/ssh.go +++ b/authority/ssh.go @@ -101,6 +101,13 @@ func (a *Authority) GetSSHConfig(ctx context.Context, typ string, data map[strin if err != nil { return nil, err } + + // Backwards compatibility for version of the cli older than v0.18.0 + if o.Name == "step_includes.tpl" && (data == nil || data["Version"] != "v2") { + o.Type = templates.File + o.Path = strings.TrimPrefix(o.Path, "${STEPPATH}/") + } + output = append(output, o) } return output, nil diff --git a/templates/templates.go b/templates/templates.go index dee7aa5f..b18c176c 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -271,7 +271,8 @@ func (o *Output) Write() error { case PrependLine: return fileutil.PrependLine(path, o.Content, 0600) default: - return errors.Errorf("unexpected output template type %s", string(o.Type)) + // Default to using a Snippet type if the type is not known. + return fileutil.WriteSnippet(path, o.Content, 0600) } } From 507be61e8ca1971231ee7df059f500cf6c41c9b3 Mon Sep 17 00:00:00 2001 From: max furman Date: Sat, 13 Nov 2021 14:22:23 -0800 Subject: [PATCH 17/24] Use a more distint map key to indicate template version - make the key a variable that can be reused on the CLI side. --- authority/ssh.go | 2 +- templates/values.go | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/authority/ssh.go b/authority/ssh.go index da93acaf..d5d6ce45 100644 --- a/authority/ssh.go +++ b/authority/ssh.go @@ -103,7 +103,7 @@ func (a *Authority) GetSSHConfig(ctx context.Context, typ string, data map[strin } // Backwards compatibility for version of the cli older than v0.18.0 - if o.Name == "step_includes.tpl" && (data == nil || data["Version"] != "v2") { + if o.Name == "step_includes.tpl" && (data == nil || data[templates.SSHTemplateVersionKey] != "v2") { o.Type = templates.File o.Path = strings.TrimPrefix(o.Path, "${STEPPATH}/") } diff --git a/templates/values.go b/templates/values.go index 3cace69d..c3362527 100644 --- a/templates/values.go +++ b/templates/values.go @@ -4,6 +4,10 @@ import ( "golang.org/x/crypto/ssh" ) +// SSHTemplateVersionKey is a key that can be submitted by a client to select +// the template version that will be returned by the server. +var SSHTemplateVersionKey = "StepSSHTemplateVersion" + // Step represents the default variables available in the CA. type Step struct { SSH StepSSH From d37313bef4cbfdcb40380b481d71bc9b10936539 Mon Sep 17 00:00:00 2001 From: max furman Date: Mon, 15 Nov 2021 10:20:10 -0800 Subject: [PATCH 18/24] Use 0600 for profile defaults file. --- pki/pki.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pki/pki.go b/pki/pki.go index 0c9d91e8..effc1f22 100644 --- a/pki/pki.go +++ b/pki/pki.go @@ -959,9 +959,12 @@ func (p *PKI) Save(opt ...ConfigOption) error { if err = fileutil.WriteFile(p.defaults, b, 0644); err != nil { return errs.FileError(err, p.defaults) } + // If we're using contexts then write a blank object to the defualt profile + // configuration location. if p.profileDefaults != "" { if _, err := os.Stat(p.profileDefaults); os.IsNotExist(err) { - if err = fileutil.WriteFile(p.profileDefaults, []byte("{}"), 0644); err != nil { + // Write with 0600 to be consistent with directories structure. + if err = fileutil.WriteFile(p.profileDefaults, []byte("{}"), 0600); err != nil { return errs.FileError(err, p.profileDefaults) } } else if err != nil { From a7d144996f3a1f832419358021cbcfaad79a35fe Mon Sep 17 00:00:00 2001 From: max furman Date: Mon, 15 Nov 2021 15:32:07 -0800 Subject: [PATCH 19/24] SSH backwards compat updates - use existence of new value in data map as boolean - add tests for backwards and forwards compatibility - fix old tests that used static dir locations --- authority/ssh.go | 12 +++-- authority/ssh_test.go | 29 ++++++++++++ .../testdata/templates/step_includes.tpl | 1 + ca/identity/client.go | 5 +-- ca/identity/client_test.go | 42 ++++++++++-------- ca/identity/identity.go | 33 ++++++++------ ca/identity/identity_test.go | 44 +++++++++---------- 7 files changed, 105 insertions(+), 61 deletions(-) create mode 100644 authority/testdata/templates/step_includes.tpl diff --git a/authority/ssh.go b/authority/ssh.go index d5d6ce45..1b1645e4 100644 --- a/authority/ssh.go +++ b/authority/ssh.go @@ -102,10 +102,14 @@ func (a *Authority) GetSSHConfig(ctx context.Context, typ string, data map[strin return nil, err } - // Backwards compatibility for version of the cli older than v0.18.0 - if o.Name == "step_includes.tpl" && (data == nil || data[templates.SSHTemplateVersionKey] != "v2") { - o.Type = templates.File - o.Path = strings.TrimPrefix(o.Path, "${STEPPATH}/") + // Backwards compatibility for version of the cli older than v0.18.0. + // Before v0.18.0 we were not passing any value for SSHTemplateVersionKey + // from the cli. + if o.Name == "step_includes.tpl" { + if val, ok := data[templates.SSHTemplateVersionKey]; !ok || val == "" { + o.Type = templates.File + o.Path = strings.TrimPrefix(o.Path, "${STEPPATH}/") + } } output = append(output, o) diff --git a/authority/ssh_test.go b/authority/ssh_test.go index 41df8576..994d015f 100644 --- a/authority/ssh_test.go +++ b/authority/ssh_test.go @@ -501,6 +501,32 @@ func TestAuthority_GetSSHConfig(t *testing.T) { {Name: "sshd_config.tpl", Type: templates.File, Comment: "#", Path: "/etc/ssh/sshd_config", Content: []byte("Match all\n\tTrustedUserCAKeys /etc/ssh/ca.pub\n\tHostCertificate /etc/ssh/ssh_host_ecdsa_key-cert.pub\n\tHostKey /etc/ssh/ssh_host_ecdsa_key")}, } + tmplConfigUserIncludes := &templates.Templates{ + SSH: &templates.SSHTemplates{ + User: []templates.Template{ + {Name: "step_includes.tpl", Type: templates.PrependLine, TemplatePath: "./testdata/templates/step_includes.tpl", Path: "${STEPPATH}/ssh/includes", Comment: "#"}, + }, + }, + Data: map[string]interface{}{ + "Step": &templates.Step{ + SSH: templates.StepSSH{ + UserKey: user, + HostKey: host, + }, + }, + }, + } + + userOutputEmptyData := []templates.Output{ + {Name: "step_includes.tpl", Type: templates.File, Comment: "#", Path: "ssh/includes", Content: []byte("Include \"/ssh/config\"\n")}, + } + userOutputWithoutTemplateVersion := []templates.Output{ + {Name: "step_includes.tpl", Type: templates.File, Comment: "#", Path: "ssh/includes", Content: []byte("Include \"/home/user/.step/ssh/config\"\n")}, + } + userOutputWithTemplateVersion := []templates.Output{ + {Name: "step_includes.tpl", Type: templates.PrependLine, Comment: "#", Path: "${STEPPATH}/ssh/includes", Content: []byte("Include \"/home/user/.step/ssh/config\"\n")}, + } + tmplConfigErr := &templates.Templates{ SSH: &templates.SSHTemplates{ User: []templates.Template{ @@ -542,6 +568,9 @@ func TestAuthority_GetSSHConfig(t *testing.T) { {"host", fields{tmplConfig, nil, hostSigner}, args{"host", nil}, hostOutput, false}, {"userWithData", fields{tmplConfigWithUserData, userSigner, hostSigner}, args{"user", map[string]string{"StepPath": "/home/user/.step"}}, userOutputWithUserData, false}, {"hostWithData", fields{tmplConfigWithUserData, userSigner, hostSigner}, args{"host", map[string]string{"Certificate": "ssh_host_ecdsa_key-cert.pub", "Key": "ssh_host_ecdsa_key"}}, hostOutputWithUserData, false}, + {"userIncludesEmptyData", fields{tmplConfigUserIncludes, userSigner, hostSigner}, args{"user", nil}, userOutputEmptyData, false}, + {"userIncludesWithoutTemplateVersion", fields{tmplConfigUserIncludes, userSigner, hostSigner}, args{"user", map[string]string{"StepPath": "/home/user/.step"}}, userOutputWithoutTemplateVersion, false}, + {"userIncludesWithTemplateVersion", fields{tmplConfigUserIncludes, userSigner, hostSigner}, args{"user", map[string]string{"StepPath": "/home/user/.step", "StepSSHTemplateVersion": "v2"}}, userOutputWithTemplateVersion, false}, {"disabled", fields{tmplConfig, nil, nil}, args{"host", nil}, nil, true}, {"badType", fields{tmplConfig, userSigner, hostSigner}, args{"bad", nil}, nil, true}, {"userError", fields{tmplConfigErr, userSigner, hostSigner}, args{"user", nil}, nil, true}, diff --git a/authority/testdata/templates/step_includes.tpl b/authority/testdata/templates/step_includes.tpl new file mode 100644 index 00000000..8c481bd8 --- /dev/null +++ b/authority/testdata/templates/step_includes.tpl @@ -0,0 +1 @@ +{{- if or .User.GOOS "none" | eq "windows" }}Include "{{ .User.StepPath | replace "\\" "/" | trimPrefix "C:" }}/ssh/config"{{- else }}Include "{{.User.StepPath}}/ssh/config"{{- end }} diff --git a/ca/identity/client.go b/ca/identity/client.go index 6f862115..97389b2d 100644 --- a/ca/identity/client.go +++ b/ca/identity/client.go @@ -10,7 +10,6 @@ import ( "net/url" "github.com/pkg/errors" - "go.step.sm/cli-utils/step" ) // Client wraps http.Client with a transport using the step root and identity. @@ -28,7 +27,7 @@ func (c *Client) ResolveReference(ref *url.URL) *url.URL { // $STEPPATH/config/defaults.json and the identity defined in // $STEPPATH/config/identity.json func LoadClient() (*Client, error) { - defaultsFile := step.DefaultsFile() + defaultsFile := DefaultsFile() b, err := ioutil.ReadFile(defaultsFile) if err != nil { return nil, errors.Wrapf(err, "error reading %s", defaultsFile) @@ -54,7 +53,7 @@ func LoadClient() (*Client, error) { return nil, err } if err := identity.Validate(); err != nil { - return nil, errors.Wrapf(err, "error validating %s", step.IdentityFile()) + return nil, errors.Wrapf(err, "error validating %s", IdentityFile()) } if kind := identity.Kind(); kind != MutualTLS { return nil, errors.Errorf("unsupported identity %s: only mTLS is currently supported", kind) diff --git a/ca/identity/client_test.go b/ca/identity/client_test.go index 402ec7b8..40a35766 100644 --- a/ca/identity/client_test.go +++ b/ca/identity/client_test.go @@ -11,6 +11,12 @@ import ( "testing" ) +func returnInput(val string) func() string { + return func() string { + return val + } +} + func TestClient(t *testing.T) { oldIdentityFile := IdentityFile oldDefaultsFile := DefaultsFile @@ -19,8 +25,8 @@ func TestClient(t *testing.T) { DefaultsFile = oldDefaultsFile }() - IdentityFile = "testdata/config/identity.json" - DefaultsFile = "testdata/config/defaults.json" + IdentityFile = returnInput("testdata/config/identity.json") + DefaultsFile = returnInput("testdata/config/defaults.json") client, err := LoadClient() if err != nil { @@ -140,36 +146,36 @@ func TestLoadClient(t *testing.T) { wantErr bool }{ {"ok", func() { - IdentityFile = "testdata/config/identity.json" - DefaultsFile = "testdata/config/defaults.json" + IdentityFile = returnInput("testdata/config/identity.json") + DefaultsFile = returnInput("testdata/config/defaults.json") }, expected, false}, {"fail identity", func() { - IdentityFile = "testdata/config/missing.json" - DefaultsFile = "testdata/config/defaults.json" + IdentityFile = returnInput("testdata/config/missing.json") + DefaultsFile = returnInput("testdata/config/defaults.json") }, nil, true}, {"fail identity", func() { - IdentityFile = "testdata/config/fail.json" - DefaultsFile = "testdata/config/defaults.json" + IdentityFile = returnInput("testdata/config/fail.json") + DefaultsFile = returnInput("testdata/config/defaults.json") }, nil, true}, {"fail defaults", func() { - IdentityFile = "testdata/config/identity.json" - DefaultsFile = "testdata/config/missing.json" + IdentityFile = returnInput("testdata/config/identity.json") + DefaultsFile = returnInput("testdata/config/missing.json") }, nil, true}, {"fail defaults", func() { - IdentityFile = "testdata/config/identity.json" - DefaultsFile = "testdata/config/fail.json" + IdentityFile = returnInput("testdata/config/identity.json") + DefaultsFile = returnInput("testdata/config/fail.json") }, nil, true}, {"fail ca", func() { - IdentityFile = "testdata/config/identity.json" - DefaultsFile = "testdata/config/badca.json" + IdentityFile = returnInput("testdata/config/identity.json") + DefaultsFile = returnInput("testdata/config/badca.json") }, nil, true}, {"fail root", func() { - IdentityFile = "testdata/config/identity.json" - DefaultsFile = "testdata/config/badroot.json" + IdentityFile = returnInput("testdata/config/identity.json") + DefaultsFile = returnInput("testdata/config/badroot.json") }, nil, true}, {"fail type", func() { - IdentityFile = "testdata/config/badIdentity.json" - DefaultsFile = "testdata/config/defaults.json" + IdentityFile = returnInput("testdata/config/badIdentity.json") + DefaultsFile = returnInput("testdata/config/defaults.json") }, nil, true}, } for _, tt := range tests { diff --git a/ca/identity/identity.go b/ca/identity/identity.go index c294d982..c9bf765d 100644 --- a/ca/identity/identity.go +++ b/ca/identity/identity.go @@ -39,6 +39,19 @@ const TunnelTLS Type = "tTLS" // DefaultLeeway is the duration for matching not before claims. const DefaultLeeway = 1 * time.Minute +var ( + identityDir = step.IdentityPath + configDir = step.ConfigPath + + // IdentityFile contains a pointer to a function that outputs the location of + // the identity file. + IdentityFile = step.IdentityFile + + // DefaultsFile contains a prointer a function that outputs the location of the + // defaults configuration file. + DefaultsFile = step.DefaultsFile +) + // Identity represents the identity file that can be used to authenticate with // the CA. type Identity struct { @@ -68,25 +81,17 @@ func LoadIdentity(filename string) (*Identity, error) { // LoadDefaultIdentity loads the default identity. func LoadDefaultIdentity() (*Identity, error) { - return LoadIdentity(step.IdentityFile()) -} - -func profileConfigDir() string { - return filepath.Join(step.Path(), "config") -} - -func profileIdentityDir() string { - return filepath.Join(step.Path(), "identity") + return LoadIdentity(IdentityFile()) } // WriteDefaultIdentity writes the given certificates and key and the // identity.json pointing to the new files. func WriteDefaultIdentity(certChain []api.Certificate, key crypto.PrivateKey) error { - if err := os.MkdirAll(profileConfigDir(), 0700); err != nil { + if err := os.MkdirAll(configDir(), 0700); err != nil { return errors.Wrap(err, "error creating config directory") } - identityDir := profileIdentityDir() + identityDir := identityDir() if err := os.MkdirAll(identityDir, 0700); err != nil { return errors.Wrap(err, "error creating identity directory") } @@ -123,7 +128,7 @@ func WriteDefaultIdentity(certChain []api.Certificate, key crypto.PrivateKey) er }); err != nil { return errors.Wrap(err, "error writing identity json") } - if err := ioutil.WriteFile(step.IdentityFile(), buf.Bytes(), 0600); err != nil { + if err := ioutil.WriteFile(IdentityFile(), buf.Bytes(), 0600); err != nil { return errors.Wrap(err, "error writing identity certificate") } @@ -132,7 +137,7 @@ func WriteDefaultIdentity(certChain []api.Certificate, key crypto.PrivateKey) er // WriteIdentityCertificate writes the identity certificate to disk. func WriteIdentityCertificate(certChain []api.Certificate) error { - filename := filepath.Join(profileIdentityDir(), "identity.crt") + filename := filepath.Join(identityDir(), "identity.crt") return writeCertificate(filename, certChain) } @@ -315,7 +320,7 @@ func (i *Identity) Renew(client Renewer) error { return errors.Wrap(err, "error encoding identity certificate") } } - certFilename := filepath.Join(profileIdentityDir(), "identity.crt") + certFilename := filepath.Join(identityDir(), "identity.crt") if err := ioutil.WriteFile(certFilename, buf.Bytes(), 0600); err != nil { return errors.Wrap(err, "error writing identity certificate") } diff --git a/ca/identity/identity_test.go b/ca/identity/identity_test.go index ce64768c..d3b1d541 100644 --- a/ca/identity/identity_test.go +++ b/ca/identity/identity_test.go @@ -33,9 +33,9 @@ func TestLoadDefaultIdentity(t *testing.T) { want *Identity wantErr bool }{ - {"ok", func() { IdentityFile = "testdata/config/identity.json" }, expected, false}, - {"fail read", func() { IdentityFile = "testdata/config/missing.json" }, nil, true}, - {"fail unmarshal", func() { IdentityFile = "testdata/config/fail.json" }, nil, true}, + {"ok", func() { IdentityFile = returnInput("testdata/config/identity.json") }, expected, false}, + {"fail read", func() { IdentityFile = returnInput("testdata/config/missing.json") }, nil, true}, + {"fail unmarshal", func() { IdentityFile = returnInput("testdata/config/fail.json") }, nil, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -217,9 +217,9 @@ func TestWriteDefaultIdentity(t *testing.T) { certChain = append(certChain, api.Certificate{Certificate: c}) } - configDir = filepath.Join(tmpDir, "config") - identityDir = filepath.Join(tmpDir, "identity") - IdentityFile = filepath.Join(tmpDir, "config", "identity.json") + configDir = returnInput(filepath.Join(tmpDir, "config")) + identityDir = returnInput(filepath.Join(tmpDir, "identity")) + IdentityFile = returnInput(filepath.Join(tmpDir, "config", "identity.json")) type args struct { certChain []api.Certificate @@ -233,27 +233,27 @@ func TestWriteDefaultIdentity(t *testing.T) { }{ {"ok", func() {}, args{certChain, key}, false}, {"fail mkdir config", func() { - configDir = filepath.Join(tmpDir, "identity", "identity.crt") - identityDir = filepath.Join(tmpDir, "identity") + configDir = returnInput(filepath.Join(tmpDir, "identity", "identity.crt")) + identityDir = returnInput(filepath.Join(tmpDir, "identity")) }, args{certChain, key}, true}, {"fail mkdir identity", func() { - configDir = filepath.Join(tmpDir, "config") - identityDir = filepath.Join(tmpDir, "identity", "identity.crt") + configDir = returnInput(filepath.Join(tmpDir, "config")) + identityDir = returnInput(filepath.Join(tmpDir, "identity", "identity.crt")) }, args{certChain, key}, true}, {"fail certificate", func() { - configDir = filepath.Join(tmpDir, "config") - identityDir = filepath.Join(tmpDir, "bad-dir") - os.MkdirAll(identityDir, 0600) + configDir = returnInput(filepath.Join(tmpDir, "config")) + identityDir = returnInput(filepath.Join(tmpDir, "bad-dir")) + os.MkdirAll(identityDir(), 0600) }, args{certChain, key}, true}, {"fail key", func() { - configDir = filepath.Join(tmpDir, "config") - identityDir = filepath.Join(tmpDir, "identity") + configDir = returnInput(filepath.Join(tmpDir, "config")) + identityDir = returnInput(filepath.Join(tmpDir, "identity")) }, args{certChain, "badKey"}, true}, {"fail write identity", func() { - configDir = filepath.Join(tmpDir, "bad-dir") - identityDir = filepath.Join(tmpDir, "identity") - IdentityFile = filepath.Join(configDir, "identity.json") - os.MkdirAll(configDir, 0600) + configDir = returnInput(filepath.Join(tmpDir, "bad-dir")) + identityDir = returnInput(filepath.Join(tmpDir, "identity")) + IdentityFile = returnInput(filepath.Join(configDir(), "identity.json")) + os.MkdirAll(configDir(), 0600) }, args{certChain, key}, true}, } @@ -377,7 +377,7 @@ func TestIdentity_Renew(t *testing.T) { } oldIdentityDir := identityDir - identityDir = "testdata/identity" + identityDir = returnInput("testdata/identity") defer func() { identityDir = oldIdentityDir os.RemoveAll(tmpDir) @@ -432,8 +432,8 @@ func TestIdentity_Renew(t *testing.T) { {"fail renew", func() {}, fields{"mTLS", "testdata/identity/identity.crt", "testdata/identity/identity_key"}, args{fail}, true}, {"fail certificate", func() {}, fields{"mTLS", "testdata/certs/server.crt", "testdata/identity/identity_key"}, args{ok}, true}, {"fail write identity", func() { - identityDir = filepath.Join(tmpDir, "bad-dir") - os.MkdirAll(identityDir, 0600) + identityDir = returnInput(filepath.Join(tmpDir, "bad-dir")) + os.MkdirAll(identityDir(), 0600) }, fields{"mTLS", "testdata/identity/identity.crt", "testdata/identity/identity_key"}, args{ok}, true}, } for _, tt := range tests { From 922d2391715901cafa8ed8e7741b0303ff442087 Mon Sep 17 00:00:00 2001 From: max furman Date: Tue, 16 Nov 2021 10:02:04 -0800 Subject: [PATCH 20/24] Simplify conditional --- authority/ssh.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/authority/ssh.go b/authority/ssh.go index 1b1645e4..bef673bf 100644 --- a/authority/ssh.go +++ b/authority/ssh.go @@ -105,11 +105,9 @@ func (a *Authority) GetSSHConfig(ctx context.Context, typ string, data map[strin // Backwards compatibility for version of the cli older than v0.18.0. // Before v0.18.0 we were not passing any value for SSHTemplateVersionKey // from the cli. - if o.Name == "step_includes.tpl" { - if val, ok := data[templates.SSHTemplateVersionKey]; !ok || val == "" { - o.Type = templates.File - o.Path = strings.TrimPrefix(o.Path, "${STEPPATH}/") - } + if o.Name == "step_includes.tpl" && data[templates.SSHTemplateVersionKey] == "" { + o.Type = templates.File + o.Path = strings.TrimPrefix(o.Path, "${STEPPATH}/") } output = append(output, o) From 555431448c55ae7bb7909097e456d8785a719d7f Mon Sep 17 00:00:00 2001 From: max furman Date: Tue, 16 Nov 2021 10:08:54 -0800 Subject: [PATCH 21/24] bump version ofcli-utils --- go.mod | 6 ++++-- go.sum | 8 ++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 346e0102..221ec171 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,9 @@ require ( github.com/golang/mock v1.6.0 github.com/google/uuid v1.3.0 github.com/googleapis/gax-go/v2 v2.0.5 + github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect + github.com/lunixbochs/vtclean v1.0.0 // indirect github.com/mattn/go-colorable v0.1.8 // indirect github.com/mattn/go-isatty v0.0.13 // indirect github.com/micromdm/scep/v2 v2.1.0 @@ -32,7 +34,7 @@ require ( github.com/smallstep/nosql v0.3.8 github.com/urfave/cli v1.22.4 go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 - go.step.sm/cli-utils v0.6.2 + go.step.sm/cli-utils v0.7.0-rc1 go.step.sm/crypto v0.13.0 go.step.sm/linkedca v0.7.0 golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 @@ -48,4 +50,4 @@ require ( //replace go.step.sm/crypto => ../crypto -replace go.step.sm/cli-utils => ../cli-utils +//replace go.step.sm/cli-utils => ../cli-utils diff --git a/go.sum b/go.sum index 0f12f0a6..619b1cf3 100644 --- a/go.sum +++ b/go.sum @@ -376,6 +376,8 @@ github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-b github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9kyRqQo= +github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -561,8 +563,10 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.step.sm/cli-utils v0.6.2 h1:ofa3G/EqE3dTDXmzoXHDZr18qJZoFsKSzbzuF+mxuZU= -go.step.sm/cli-utils v0.6.2/go.mod h1:0tZ8F2QwLgD6KbKj4nrQZhMakTasEAnOcW3Ekc5pnrA= +go.step.sm/cli-utils v0.6.0 h1:sH4FxBcjmbxyilKXheSyJuKF/QjpojpiW90ERwUWOgQ= +go.step.sm/cli-utils v0.6.0/go.mod h1:jklBMavFl2PbmGlyxgax08ZnB0uWpadjuOlSKKXz+0U= +go.step.sm/cli-utils v0.7.0-rc1 h1:f5/dMhmo7j69xVz9DHkcgbDQOE0NdcSwC2fUnvaZD5c= +go.step.sm/cli-utils v0.7.0-rc1/go.mod h1:Ur6bqA/yl636kCUJbp30J7Unv5JJ226eW2KqXPDwF/E= go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= go.step.sm/crypto v0.13.0 h1:mQuP9Uu2FNmqCJNO0OTbvolnYXzONy4wdUBtUVcP1s8= go.step.sm/crypto v0.13.0/go.mod h1:5YzQ85BujYBu6NH18jw7nFjwuRnDch35nLzH0ES5sKg= From b5bf79b84ef2303c9f8d65138dbe138a66375bb6 Mon Sep 17 00:00:00 2001 From: max furman Date: Tue, 16 Nov 2021 16:02:19 -0800 Subject: [PATCH 22/24] bump nosql library --- go.mod | 4 +--- go.sum | 8 ++------ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 221ec171..88abd20f 100644 --- a/go.mod +++ b/go.mod @@ -20,9 +20,7 @@ require ( github.com/golang/mock v1.6.0 github.com/google/uuid v1.3.0 github.com/googleapis/gax-go/v2 v2.0.5 - github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect - github.com/lunixbochs/vtclean v1.0.0 // indirect github.com/mattn/go-colorable v0.1.8 // indirect github.com/mattn/go-isatty v0.0.13 // indirect github.com/micromdm/scep/v2 v2.1.0 @@ -31,7 +29,7 @@ require ( github.com/rs/xid v1.2.1 github.com/sirupsen/logrus v1.4.2 github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 - github.com/smallstep/nosql v0.3.8 + github.com/smallstep/nosql v0.3.9 github.com/urfave/cli v1.22.4 go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 go.step.sm/cli-utils v0.7.0-rc1 diff --git a/go.sum b/go.sum index 619b1cf3..96d49594 100644 --- a/go.sum +++ b/go.sum @@ -376,8 +376,6 @@ github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-b github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9kyRqQo= -github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -498,8 +496,8 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/smallstep/assert v0.0.0-20180720014142-de77670473b5/go.mod h1:TC9A4+RjIOS+HyTH7wG17/gSqVv95uDw2J64dQZx7RE= github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262 h1:unQFBIznI+VYD1/1fApl1A+9VcBk+9dcqGfnePY87LY= github.com/smallstep/assert v0.0.0-20200723003110-82e2b9b3b262/go.mod h1:MyOHs9Po2fbM1LHej6sBUT8ozbxmMOFG+E+rx/GSGuc= -github.com/smallstep/nosql v0.3.8 h1:1/EWUbbEdz9ai0g9Fd09VekVjtxp+5+gIHpV2PdwW3o= -github.com/smallstep/nosql v0.3.8/go.mod h1:X2qkYpNcW3yjLUvhEHfgGfClpKbFPapewvx7zo4TOFs= +github.com/smallstep/nosql v0.3.9 h1:YPy5PR3PXClqmpFaVv0wfXDXDc7NXGBE1auyU2c87dc= +github.com/smallstep/nosql v0.3.9/go.mod h1:X2qkYpNcW3yjLUvhEHfgGfClpKbFPapewvx7zo4TOFs= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -563,8 +561,6 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.step.sm/cli-utils v0.6.0 h1:sH4FxBcjmbxyilKXheSyJuKF/QjpojpiW90ERwUWOgQ= -go.step.sm/cli-utils v0.6.0/go.mod h1:jklBMavFl2PbmGlyxgax08ZnB0uWpadjuOlSKKXz+0U= go.step.sm/cli-utils v0.7.0-rc1 h1:f5/dMhmo7j69xVz9DHkcgbDQOE0NdcSwC2fUnvaZD5c= go.step.sm/cli-utils v0.7.0-rc1/go.mod h1:Ur6bqA/yl636kCUJbp30J7Unv5JJ226eW2KqXPDwF/E= go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= From 196f6b45c96bbf94ef16f34712721b7f363d519b Mon Sep 17 00:00:00 2001 From: max furman Date: Tue, 16 Nov 2021 21:43:53 -0800 Subject: [PATCH 23/24] bump cli-utils to 0.7.0 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 88abd20f..2253e816 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/smallstep/nosql v0.3.9 github.com/urfave/cli v1.22.4 go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 - go.step.sm/cli-utils v0.7.0-rc1 + go.step.sm/cli-utils v0.7.0 go.step.sm/crypto v0.13.0 go.step.sm/linkedca v0.7.0 golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 diff --git a/go.sum b/go.sum index 96d49594..4c0d4db1 100644 --- a/go.sum +++ b/go.sum @@ -561,8 +561,8 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.step.sm/cli-utils v0.7.0-rc1 h1:f5/dMhmo7j69xVz9DHkcgbDQOE0NdcSwC2fUnvaZD5c= -go.step.sm/cli-utils v0.7.0-rc1/go.mod h1:Ur6bqA/yl636kCUJbp30J7Unv5JJ226eW2KqXPDwF/E= +go.step.sm/cli-utils v0.7.0 h1:2GvY5Muid1yzp7YQbfCCS+gK3q7zlHjjLL5Z0DXz8ds= +go.step.sm/cli-utils v0.7.0/go.mod h1:Ur6bqA/yl636kCUJbp30J7Unv5JJ226eW2KqXPDwF/E= go.step.sm/crypto v0.9.0/go.mod h1:+CYG05Mek1YDqi5WK0ERc6cOpKly2i/a5aZmU1sfGj0= go.step.sm/crypto v0.13.0 h1:mQuP9Uu2FNmqCJNO0OTbvolnYXzONy4wdUBtUVcP1s8= go.step.sm/crypto v0.13.0/go.mod h1:5YzQ85BujYBu6NH18jw7nFjwuRnDch35nLzH0ES5sKg= From df2843657f8a586a5800ab5383f61248df4aaac2 Mon Sep 17 00:00:00 2001 From: max furman Date: Wed, 17 Nov 2021 11:51:33 -0800 Subject: [PATCH 24/24] [action] only run codecov for go 1.17 --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 78b59f4b..10e7360d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -58,6 +58,7 @@ jobs: run: V=1 make ci - name: Codecov + if: matrix.go == '1.17' uses: codecov/codecov-action@v1.2.1 with: file: ./coverage.out # optional