From 6c64fb3ed293c526beab7243ed07db2efa737462 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Wed, 22 Jul 2020 18:24:45 -0700 Subject: [PATCH] Rename provisioner options structs: * provisioner.ProvisionerOptions => provisioner.Options * provisioner.Options => provisioner.SignOptions * provisioner.SSHOptions => provisioner.SingSSHOptions --- acme/common.go | 10 +- acme/order.go | 2 +- acme/order_test.go | 10 +- api/api.go | 2 +- api/api_test.go | 8 +- api/sign.go | 2 +- api/ssh.go | 6 +- api/ssh_test.go | 4 +- authority/authority_test.go | 2 +- authority/authorize_test.go | 6 +- authority/provisioner/acme.go | 12 +-- authority/provisioner/aws.go | 18 ++-- authority/provisioner/aws_test.go | 40 +++---- authority/provisioner/azure.go | 20 ++-- authority/provisioner/azure_test.go | 32 +++--- authority/provisioner/gcp.go | 20 ++-- authority/provisioner/gcp_test.go | 40 +++---- authority/provisioner/jwk.go | 14 +-- authority/provisioner/jwk_test.go | 98 ++++++++--------- authority/provisioner/k8sSA.go | 10 +- authority/provisioner/oidc.go | 26 ++--- authority/provisioner/oidc_test.go | 58 +++++----- authority/provisioner/options.go | 19 ++-- authority/provisioner/options_test.go | 36 +++---- authority/provisioner/sign_options.go | 22 ++-- authority/provisioner/sign_options_test.go | 54 +++++----- authority/provisioner/sign_ssh_options.go | 36 +++---- .../provisioner/sign_ssh_options_test.go | 102 +++++++++--------- authority/provisioner/ssh_test.go | 4 +- authority/provisioner/utils_test.go | 6 +- authority/provisioner/x5c.go | 10 +- authority/provisioner/x5c_test.go | 8 +- authority/ssh.go | 4 +- authority/ssh_test.go | 50 ++++----- authority/tls.go | 4 +- authority/tls_test.go | 14 +-- ca/provisioner.go | 2 +- 37 files changed, 405 insertions(+), 406 deletions(-) diff --git a/acme/common.go b/acme/common.go index b78d0da3..d2d710cc 100644 --- a/acme/common.go +++ b/acme/common.go @@ -18,7 +18,7 @@ type Provisioner interface { AuthorizeSign(ctx context.Context, token string) ([]provisioner.SignOption, error) GetName() string DefaultTLSCertDuration() time.Duration - GetOptions() *provisioner.ProvisionerOptions + GetOptions() *provisioner.Options } // MockProvisioner for testing @@ -28,7 +28,7 @@ type MockProvisioner struct { MgetName func() string MauthorizeSign func(ctx context.Context, ott string) ([]provisioner.SignOption, error) MdefaultTLSCertDuration func() time.Duration - MgetOptions func() *provisioner.ProvisionerOptions + MgetOptions func() *provisioner.Options } // GetName mock @@ -55,11 +55,11 @@ func (m *MockProvisioner) DefaultTLSCertDuration() time.Duration { return m.Mret1.(time.Duration) } -func (m *MockProvisioner) GetOptions() *provisioner.ProvisionerOptions { +func (m *MockProvisioner) GetOptions() *provisioner.Options { if m.MgetOptions != nil { return m.MgetOptions() } - return m.Mret1.(*provisioner.ProvisionerOptions) + return m.Mret1.(*provisioner.Options) } // ContextKey is the key type for storing and searching for ACME request @@ -134,7 +134,7 @@ func ProvisionerFromContext(ctx context.Context) (Provisioner, error) { // SignAuthority is the interface implemented by a CA authority. type SignAuthority interface { - Sign(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error) + Sign(cr *x509.CertificateRequest, opts provisioner.SignOptions, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error) LoadProvisionerByID(string) (provisioner.Interface, error) } diff --git a/acme/order.go b/acme/order.go index cf9002dc..99dffb89 100644 --- a/acme/order.go +++ b/acme/order.go @@ -338,7 +338,7 @@ func (o *order) finalize(db nosql.DB, csr *x509.CertificateRequest, auth SignAut signOps = append(signOps, templateOptions) // Create and store a new certificate. - certChain, err := auth.Sign(csr, provisioner.Options{ + certChain, err := auth.Sign(csr, provisioner.SignOptions{ NotBefore: provisioner.NewTimeDuration(o.NotBefore), NotAfter: provisioner.NewTimeDuration(o.NotAfter), }, signOps...) diff --git a/acme/order_test.go b/acme/order_test.go index 3411bba8..785b24c4 100644 --- a/acme/order_test.go +++ b/acme/order_test.go @@ -895,13 +895,13 @@ func TestOrderUpdateStatus(t *testing.T) { } type mockSignAuth struct { - sign func(csr *x509.CertificateRequest, signOpts provisioner.Options, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) + sign func(csr *x509.CertificateRequest, signOpts provisioner.SignOptions, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) loadProvisionerByID func(string) (provisioner.Interface, error) ret1, ret2 interface{} err error } -func (m *mockSignAuth) Sign(csr *x509.CertificateRequest, signOpts provisioner.Options, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) { +func (m *mockSignAuth) Sign(csr *x509.CertificateRequest, signOpts provisioner.SignOptions, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) { if m.sign != nil { return m.sign(csr, signOpts, extraOpts...) } else if m.err != nil { @@ -1262,7 +1262,7 @@ func TestOrderFinalize(t *testing.T) { res: clone, csr: csr, sa: &mockSignAuth{ - sign: func(csr *x509.CertificateRequest, pops provisioner.Options, signOps ...provisioner.SignOption) ([]*x509.Certificate, error) { + sign: func(csr *x509.CertificateRequest, pops provisioner.SignOptions, signOps ...provisioner.SignOption) ([]*x509.Certificate, error) { assert.Equals(t, len(signOps), 6) return []*x509.Certificate{crt, inter}, nil }, @@ -1311,7 +1311,7 @@ func TestOrderFinalize(t *testing.T) { res: &clone, csr: csr, sa: &mockSignAuth{ - sign: func(csr *x509.CertificateRequest, pops provisioner.Options, signOps ...provisioner.SignOption) ([]*x509.Certificate, error) { + sign: func(csr *x509.CertificateRequest, pops provisioner.SignOptions, signOps ...provisioner.SignOption) ([]*x509.Certificate, error) { assert.Equals(t, len(signOps), 6) return []*x509.Certificate{crt, inter}, nil }, @@ -1358,7 +1358,7 @@ func TestOrderFinalize(t *testing.T) { res: &clone, csr: csr, sa: &mockSignAuth{ - sign: func(csr *x509.CertificateRequest, pops provisioner.Options, signOps ...provisioner.SignOption) ([]*x509.Certificate, error) { + sign: func(csr *x509.CertificateRequest, pops provisioner.SignOptions, signOps ...provisioner.SignOption) ([]*x509.Certificate, error) { assert.Equals(t, len(signOps), 6) return []*x509.Certificate{crt, inter}, nil }, diff --git a/api/api.go b/api/api.go index f83a2354..be735d69 100644 --- a/api/api.go +++ b/api/api.go @@ -34,7 +34,7 @@ type Authority interface { AuthorizeSign(ott string) ([]provisioner.SignOption, error) GetTLSOptions() *tlsutil.TLSOptions Root(shasum string) (*x509.Certificate, error) - Sign(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error) + Sign(cr *x509.CertificateRequest, opts provisioner.SignOptions, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error) Renew(peer *x509.Certificate) ([]*x509.Certificate, error) Rekey(peer *x509.Certificate, pk crypto.PublicKey) ([]*x509.Certificate, error) LoadProvisionerByCertificate(*x509.Certificate) (provisioner.Interface, error) diff --git a/api/api_test.go b/api/api_test.go index 646dfd09..aab47e53 100644 --- a/api/api_test.go +++ b/api/api_test.go @@ -550,7 +550,7 @@ type mockAuthority struct { authorizeSign func(ott string) ([]provisioner.SignOption, error) getTLSOptions func() *tlsutil.TLSOptions root func(shasum string) (*x509.Certificate, error) - sign func(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error) + sign func(cr *x509.CertificateRequest, opts provisioner.SignOptions, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error) renew func(cert *x509.Certificate) ([]*x509.Certificate, error) rekey func(oldCert *x509.Certificate, pk crypto.PublicKey) ([]*x509.Certificate, error) loadProvisionerByCertificate func(cert *x509.Certificate) (provisioner.Interface, error) @@ -560,7 +560,7 @@ type mockAuthority struct { getEncryptedKey func(kid string) (string, error) getRoots func() ([]*x509.Certificate, error) getFederation func() ([]*x509.Certificate, error) - signSSH func(ctx context.Context, key ssh.PublicKey, opts provisioner.SSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) + signSSH func(ctx context.Context, key ssh.PublicKey, opts provisioner.SignSSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) signSSHAddUser func(ctx context.Context, key ssh.PublicKey, cert *ssh.Certificate) (*ssh.Certificate, error) renewSSH func(ctx context.Context, cert *ssh.Certificate) (*ssh.Certificate, error) rekeySSH func(ctx context.Context, cert *ssh.Certificate, key ssh.PublicKey, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) @@ -599,7 +599,7 @@ func (m *mockAuthority) Root(shasum string) (*x509.Certificate, error) { return m.ret1.(*x509.Certificate), m.err } -func (m *mockAuthority) Sign(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error) { +func (m *mockAuthority) Sign(cr *x509.CertificateRequest, opts provisioner.SignOptions, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error) { if m.sign != nil { return m.sign(cr, opts, signOpts...) } @@ -669,7 +669,7 @@ func (m *mockAuthority) GetFederation() ([]*x509.Certificate, error) { return m.ret1.([]*x509.Certificate), m.err } -func (m *mockAuthority) SignSSH(ctx context.Context, key ssh.PublicKey, opts provisioner.SSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) { +func (m *mockAuthority) SignSSH(ctx context.Context, key ssh.PublicKey, opts provisioner.SignSSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) { if m.signSSH != nil { return m.signSSH(ctx, key, opts, signOpts...) } diff --git a/api/sign.go b/api/sign.go index a6087dc6..f24f4d02 100644 --- a/api/sign.go +++ b/api/sign.go @@ -60,7 +60,7 @@ func (h *caHandler) Sign(w http.ResponseWriter, r *http.Request) { return } - opts := provisioner.Options{ + opts := provisioner.SignOptions{ NotBefore: body.NotBefore, NotAfter: body.NotAfter, TemplateData: body.TemplateData, diff --git a/api/ssh.go b/api/ssh.go index f423583b..70469fbf 100644 --- a/api/ssh.go +++ b/api/ssh.go @@ -19,7 +19,7 @@ import ( // SSHAuthority is the interface implemented by a SSH CA authority. type SSHAuthority interface { - SignSSH(ctx context.Context, key ssh.PublicKey, opts provisioner.SSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) + SignSSH(ctx context.Context, key ssh.PublicKey, opts provisioner.SignSSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) RenewSSH(ctx context.Context, cert *ssh.Certificate) (*ssh.Certificate, error) RekeySSH(ctx context.Context, cert *ssh.Certificate, key ssh.PublicKey, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) SignSSHAddUser(ctx context.Context, key ssh.PublicKey, cert *ssh.Certificate) (*ssh.Certificate, error) @@ -274,7 +274,7 @@ func (h *caHandler) SSHSign(w http.ResponseWriter, r *http.Request) { } } - opts := provisioner.SSHOptions{ + opts := provisioner.SignSSHOptions{ CertType: body.CertType, KeyID: body.KeyID, Principals: body.Principals, @@ -322,7 +322,7 @@ func (h *caHandler) SSHSign(w http.ResponseWriter, r *http.Request) { NotAfter: time.Unix(int64(cert.ValidBefore), 0), }) - certChain, err := h.Authority.Sign(cr, provisioner.Options{}, signOpts...) + certChain, err := h.Authority.Sign(cr, provisioner.SignOptions{}, signOpts...) if err != nil { WriteError(w, errs.ForbiddenErr(err)) return diff --git a/api/ssh_test.go b/api/ssh_test.go index cb1afa6f..7561709a 100644 --- a/api/ssh_test.go +++ b/api/ssh_test.go @@ -319,13 +319,13 @@ func Test_caHandler_SSHSign(t *testing.T) { authorizeSign: func(ott string) ([]provisioner.SignOption, error) { return []provisioner.SignOption{}, tt.authErr }, - signSSH: func(ctx context.Context, key ssh.PublicKey, opts provisioner.SSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) { + signSSH: func(ctx context.Context, key ssh.PublicKey, opts provisioner.SignSSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) { return tt.signCert, tt.signErr }, signSSHAddUser: func(ctx context.Context, key ssh.PublicKey, cert *ssh.Certificate) (*ssh.Certificate, error) { return tt.addUserCert, tt.addUserErr }, - sign: func(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error) { + sign: func(cr *x509.CertificateRequest, opts provisioner.SignOptions, signOpts ...provisioner.SignOption) ([]*x509.Certificate, error) { return tt.tlsSignCerts, tt.tlsSignErr }, }).(*caHandler) diff --git a/authority/authority_test.go b/authority/authority_test.go index 3ab3e142..f87f1df3 100644 --- a/authority/authority_test.go +++ b/authority/authority_test.go @@ -283,7 +283,7 @@ func TestNewEmbedded_Sign(t *testing.T) { csr, err := x509.ParseCertificateRequest(cr) assert.FatalError(t, err) - cert, err := a.Sign(csr, provisioner.Options{}) + cert, err := a.Sign(csr, provisioner.SignOptions{}) assert.FatalError(t, err) assert.Equals(t, []string{"foo.bar.zar"}, cert[0].DNSNames) assert.Equals(t, crt, cert[1]) diff --git a/authority/authorize_test.go b/authority/authorize_test.go index 1f53504f..c562437c 100644 --- a/authority/authorize_test.go +++ b/authority/authorize_test.go @@ -830,17 +830,17 @@ func TestAuthority_authorizeRenew(t *testing.T) { } func generateSimpleSSHUserToken(iss, aud string, jwk *jose.JSONWebKey) (string, error) { - return generateSSHToken("subject@localhost", iss, aud, time.Now(), &provisioner.SSHOptions{ + return generateSSHToken("subject@localhost", iss, aud, time.Now(), &provisioner.SignSSHOptions{ CertType: "user", Principals: []string{"name"}, }, jwk) } type stepPayload struct { - SSH *provisioner.SSHOptions `json:"ssh,omitempty"` + SSH *provisioner.SignSSHOptions `json:"ssh,omitempty"` } -func generateSSHToken(sub, iss, aud string, iat time.Time, sshOpts *provisioner.SSHOptions, jwk *jose.JSONWebKey) (string, error) { +func generateSSHToken(sub, iss, aud string, iat time.Time, sshOpts *provisioner.SignSSHOptions, jwk *jose.JSONWebKey) (string, error) { sig, err := jose.NewSigner( jose.SigningKey{Algorithm: jose.ES256, Key: jwk.Key}, new(jose.SignerOptions).WithType("JWT").WithHeader("kid", jwk.KeyID), diff --git a/authority/provisioner/acme.go b/authority/provisioner/acme.go index 418f733c..a36c496d 100644 --- a/authority/provisioner/acme.go +++ b/authority/provisioner/acme.go @@ -13,11 +13,11 @@ import ( // provisioning flow. type ACME struct { *base - Type string `json:"type"` - Name string `json:"name"` - ForceCN bool `json:"forceCN,omitempty"` - Claims *Claims `json:"claims,omitempty"` - Options *ProvisionerOptions `json:"options,omitempty"` + Type string `json:"type"` + Name string `json:"name"` + ForceCN bool `json:"forceCN,omitempty"` + Claims *Claims `json:"claims,omitempty"` + Options *Options `json:"options,omitempty"` claimer *Claimer } @@ -47,7 +47,7 @@ func (p *ACME) GetEncryptedKey() (string, string, bool) { } // GetOptions returns the configured provisioner options. -func (p *ACME) GetOptions() *ProvisionerOptions { +func (p *ACME) GetOptions() *Options { return p.Options } diff --git a/authority/provisioner/aws.go b/authority/provisioner/aws.go index 327467a7..9f3764c0 100644 --- a/authority/provisioner/aws.go +++ b/authority/provisioner/aws.go @@ -126,14 +126,14 @@ type awsInstanceIdentityDocument struct { // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html type AWS struct { *base - Type string `json:"type"` - Name string `json:"name"` - Accounts []string `json:"accounts"` - DisableCustomSANs bool `json:"disableCustomSANs"` - DisableTrustOnFirstUse bool `json:"disableTrustOnFirstUse"` - InstanceAge Duration `json:"instanceAge,omitempty"` - Claims *Claims `json:"claims,omitempty"` - Options *ProvisionerOptions `json:"options,omitempty"` + Type string `json:"type"` + Name string `json:"name"` + Accounts []string `json:"accounts"` + DisableCustomSANs bool `json:"disableCustomSANs"` + DisableTrustOnFirstUse bool `json:"disableTrustOnFirstUse"` + InstanceAge Duration `json:"instanceAge,omitempty"` + Claims *Claims `json:"claims,omitempty"` + Options *Options `json:"options,omitempty"` claimer *Claimer config *awsConfig audiences Audiences @@ -483,7 +483,7 @@ func (p *AWS) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption, } // Default to cert type to host - defaults := SSHOptions{ + defaults := SignSSHOptions{ CertType: SSHHostCert, Principals: principals, } diff --git a/authority/provisioner/aws_test.go b/authority/provisioner/aws_test.go index 665f379f..4c4dbae4 100644 --- a/authority/provisioner/aws_test.go +++ b/authority/provisioner/aws_test.go @@ -647,51 +647,51 @@ func TestAWS_AuthorizeSSHSign(t *testing.T) { assert.FatalError(t, err) hostDuration := p1.claimer.DefaultHostSSHCertDuration() - expectedHostOptions := &SSHOptions{ + expectedHostOptions := &SignSSHOptions{ CertType: "host", Principals: []string{"127.0.0.1", "ip-127-0-0-1.us-west-1.compute.internal"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)), } - expectedHostOptionsIP := &SSHOptions{ + expectedHostOptionsIP := &SignSSHOptions{ CertType: "host", Principals: []string{"127.0.0.1"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)), } - expectedHostOptionsHostname := &SSHOptions{ + expectedHostOptionsHostname := &SignSSHOptions{ CertType: "host", Principals: []string{"ip-127-0-0-1.us-west-1.compute.internal"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)), } - expectedCustomOptions := &SSHOptions{ + expectedCustomOptions := &SignSSHOptions{ CertType: "host", Principals: []string{"foo.local"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)), } type args struct { token string - sshOpts SSHOptions + sshOpts SignSSHOptions key interface{} } tests := []struct { name string aws *AWS args args - expected *SSHOptions + expected *SignSSHOptions code int wantErr bool wantSignErr bool }{ - {"ok", p1, args{t1, SSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false}, - {"ok-rsa2048", p1, args{t1, SSHOptions{}, rsa2048.Public()}, expectedHostOptions, http.StatusOK, false, false}, - {"ok-type", p1, args{t1, SSHOptions{CertType: "host"}, pub}, expectedHostOptions, http.StatusOK, false, false}, - {"ok-principals", p1, args{t1, SSHOptions{Principals: []string{"127.0.0.1", "ip-127-0-0-1.us-west-1.compute.internal"}}, pub}, expectedHostOptions, http.StatusOK, false, false}, - {"ok-principal-ip", p1, args{t1, SSHOptions{Principals: []string{"127.0.0.1"}}, pub}, expectedHostOptionsIP, http.StatusOK, false, false}, - {"ok-principal-hostname", p1, args{t1, SSHOptions{Principals: []string{"ip-127-0-0-1.us-west-1.compute.internal"}}, pub}, expectedHostOptionsHostname, http.StatusOK, false, false}, - {"ok-options", p1, args{t1, SSHOptions{CertType: "host", Principals: []string{"127.0.0.1", "ip-127-0-0-1.us-west-1.compute.internal"}}, pub}, expectedHostOptions, http.StatusOK, false, false}, - {"ok-custom", p2, args{t2, SSHOptions{Principals: []string{"foo.local"}}, pub}, expectedCustomOptions, http.StatusOK, false, false}, - {"fail-rsa1024", p1, args{t1, SSHOptions{}, rsa1024.Public()}, expectedHostOptions, http.StatusOK, false, true}, - {"fail-type", p1, args{t1, SSHOptions{CertType: "user"}, pub}, nil, http.StatusOK, false, true}, - {"fail-principal", p1, args{t1, SSHOptions{Principals: []string{"smallstep.com"}}, pub}, nil, http.StatusOK, false, true}, - {"fail-extra-principal", p1, args{t1, SSHOptions{Principals: []string{"127.0.0.1", "ip-127-0-0-1.us-west-1.compute.internal", "smallstep.com"}}, pub}, nil, http.StatusOK, false, true}, - {"fail-sshCA-disabled", p3, args{"foo", SSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false}, - {"fail-invalid-token", p1, args{"foo", SSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false}, + {"ok", p1, args{t1, SignSSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false}, + {"ok-rsa2048", p1, args{t1, SignSSHOptions{}, rsa2048.Public()}, expectedHostOptions, http.StatusOK, false, false}, + {"ok-type", p1, args{t1, SignSSHOptions{CertType: "host"}, pub}, expectedHostOptions, http.StatusOK, false, false}, + {"ok-principals", p1, args{t1, SignSSHOptions{Principals: []string{"127.0.0.1", "ip-127-0-0-1.us-west-1.compute.internal"}}, pub}, expectedHostOptions, http.StatusOK, false, false}, + {"ok-principal-ip", p1, args{t1, SignSSHOptions{Principals: []string{"127.0.0.1"}}, pub}, expectedHostOptionsIP, http.StatusOK, false, false}, + {"ok-principal-hostname", p1, args{t1, SignSSHOptions{Principals: []string{"ip-127-0-0-1.us-west-1.compute.internal"}}, pub}, expectedHostOptionsHostname, http.StatusOK, false, false}, + {"ok-options", p1, args{t1, SignSSHOptions{CertType: "host", Principals: []string{"127.0.0.1", "ip-127-0-0-1.us-west-1.compute.internal"}}, pub}, expectedHostOptions, http.StatusOK, false, false}, + {"ok-custom", p2, args{t2, SignSSHOptions{Principals: []string{"foo.local"}}, pub}, expectedCustomOptions, http.StatusOK, false, false}, + {"fail-rsa1024", p1, args{t1, SignSSHOptions{}, rsa1024.Public()}, expectedHostOptions, http.StatusOK, false, true}, + {"fail-type", p1, args{t1, SignSSHOptions{CertType: "user"}, pub}, nil, http.StatusOK, false, true}, + {"fail-principal", p1, args{t1, SignSSHOptions{Principals: []string{"smallstep.com"}}, pub}, nil, http.StatusOK, false, true}, + {"fail-extra-principal", p1, args{t1, SignSSHOptions{Principals: []string{"127.0.0.1", "ip-127-0-0-1.us-west-1.compute.internal", "smallstep.com"}}, pub}, nil, http.StatusOK, false, true}, + {"fail-sshCA-disabled", p3, args{"foo", SignSSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false}, + {"fail-invalid-token", p1, args{"foo", SignSSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/authority/provisioner/azure.go b/authority/provisioner/azure.go index 865eee91..a677f9a9 100644 --- a/authority/provisioner/azure.go +++ b/authority/provisioner/azure.go @@ -83,15 +83,15 @@ type azurePayload struct { // and https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service type Azure struct { *base - Type string `json:"type"` - Name string `json:"name"` - TenantID string `json:"tenantID"` - ResourceGroups []string `json:"resourceGroups"` - Audience string `json:"audience,omitempty"` - DisableCustomSANs bool `json:"disableCustomSANs"` - DisableTrustOnFirstUse bool `json:"disableTrustOnFirstUse"` - Claims *Claims `json:"claims,omitempty"` - Options *ProvisionerOptions `json:"options,omitempty"` + Type string `json:"type"` + Name string `json:"name"` + TenantID string `json:"tenantID"` + ResourceGroups []string `json:"resourceGroups"` + Audience string `json:"audience,omitempty"` + DisableCustomSANs bool `json:"disableCustomSANs"` + DisableTrustOnFirstUse bool `json:"disableTrustOnFirstUse"` + Claims *Claims `json:"claims,omitempty"` + Options *Options `json:"options,omitempty"` claimer *Claimer config *azureConfig oidcConfig openIDConfiguration @@ -350,7 +350,7 @@ func (p *Azure) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOptio } // Default to host + known hostnames - defaults := SSHOptions{ + defaults := SignSSHOptions{ CertType: SSHHostCert, Principals: principals, } diff --git a/authority/provisioner/azure_test.go b/authority/provisioner/azure_test.go index 90d36fd6..e919a5cd 100644 --- a/authority/provisioner/azure_test.go +++ b/authority/provisioner/azure_test.go @@ -571,41 +571,41 @@ func TestAzure_AuthorizeSSHSign(t *testing.T) { assert.FatalError(t, err) hostDuration := p1.claimer.DefaultHostSSHCertDuration() - expectedHostOptions := &SSHOptions{ + expectedHostOptions := &SignSSHOptions{ CertType: "host", Principals: []string{"virtualMachine"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)), } - expectedCustomOptions := &SSHOptions{ + expectedCustomOptions := &SignSSHOptions{ CertType: "host", Principals: []string{"foo.bar"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)), } type args struct { token string - sshOpts SSHOptions + sshOpts SignSSHOptions key interface{} } tests := []struct { name string azure *Azure args args - expected *SSHOptions + expected *SignSSHOptions code int wantErr bool wantSignErr bool }{ - {"ok", p1, args{t1, SSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false}, - {"ok-rsa2048", p1, args{t1, SSHOptions{}, rsa2048.Public()}, expectedHostOptions, http.StatusOK, false, false}, - {"ok-type", p1, args{t1, SSHOptions{CertType: "host"}, pub}, expectedHostOptions, http.StatusOK, false, false}, - {"ok-principals", p1, args{t1, SSHOptions{Principals: []string{"virtualMachine"}}, pub}, expectedHostOptions, http.StatusOK, false, false}, - {"ok-options", p1, args{t1, SSHOptions{CertType: "host", Principals: []string{"virtualMachine"}}, pub}, expectedHostOptions, http.StatusOK, false, false}, - {"ok-custom", p2, args{t2, SSHOptions{Principals: []string{"foo.bar"}}, pub}, expectedCustomOptions, http.StatusOK, false, false}, - {"fail-rsa1024", p1, args{t1, SSHOptions{}, rsa1024.Public()}, expectedHostOptions, http.StatusOK, false, true}, - {"fail-type", p1, args{t1, SSHOptions{CertType: "user"}, pub}, nil, http.StatusOK, false, true}, - {"fail-principal", p1, args{t1, SSHOptions{Principals: []string{"smallstep.com"}}, pub}, nil, http.StatusOK, false, true}, - {"fail-extra-principal", p1, args{t1, SSHOptions{Principals: []string{"virtualMachine", "smallstep.com"}}, pub}, nil, http.StatusOK, false, true}, - {"fail-sshCA-disabled", p3, args{"foo", SSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false}, - {"fail-invalid-token", p1, args{"foo", SSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false}, + {"ok", p1, args{t1, SignSSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false}, + {"ok-rsa2048", p1, args{t1, SignSSHOptions{}, rsa2048.Public()}, expectedHostOptions, http.StatusOK, false, false}, + {"ok-type", p1, args{t1, SignSSHOptions{CertType: "host"}, pub}, expectedHostOptions, http.StatusOK, false, false}, + {"ok-principals", p1, args{t1, SignSSHOptions{Principals: []string{"virtualMachine"}}, pub}, expectedHostOptions, http.StatusOK, false, false}, + {"ok-options", p1, args{t1, SignSSHOptions{CertType: "host", Principals: []string{"virtualMachine"}}, pub}, expectedHostOptions, http.StatusOK, false, false}, + {"ok-custom", p2, args{t2, SignSSHOptions{Principals: []string{"foo.bar"}}, pub}, expectedCustomOptions, http.StatusOK, false, false}, + {"fail-rsa1024", p1, args{t1, SignSSHOptions{}, rsa1024.Public()}, expectedHostOptions, http.StatusOK, false, true}, + {"fail-type", p1, args{t1, SignSSHOptions{CertType: "user"}, pub}, nil, http.StatusOK, false, true}, + {"fail-principal", p1, args{t1, SignSSHOptions{Principals: []string{"smallstep.com"}}, pub}, nil, http.StatusOK, false, true}, + {"fail-extra-principal", p1, args{t1, SignSSHOptions{Principals: []string{"virtualMachine", "smallstep.com"}}, pub}, nil, http.StatusOK, false, true}, + {"fail-sshCA-disabled", p3, args{"foo", SignSSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false}, + {"fail-invalid-token", p1, args{"foo", SignSSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/authority/provisioner/gcp.go b/authority/provisioner/gcp.go index f083b759..69a42ec2 100644 --- a/authority/provisioner/gcp.go +++ b/authority/provisioner/gcp.go @@ -77,15 +77,15 @@ func newGCPConfig() *gcpConfig { // https://cloud.google.com/compute/docs/instances/verifying-instance-identity type GCP struct { *base - Type string `json:"type"` - Name string `json:"name"` - ServiceAccounts []string `json:"serviceAccounts"` - ProjectIDs []string `json:"projectIDs"` - DisableCustomSANs bool `json:"disableCustomSANs"` - DisableTrustOnFirstUse bool `json:"disableTrustOnFirstUse"` - InstanceAge Duration `json:"instanceAge,omitempty"` - Claims *Claims `json:"claims,omitempty"` - Options *ProvisionerOptions `json:"options,omitempty"` + Type string `json:"type"` + Name string `json:"name"` + ServiceAccounts []string `json:"serviceAccounts"` + ProjectIDs []string `json:"projectIDs"` + DisableCustomSANs bool `json:"disableCustomSANs"` + DisableTrustOnFirstUse bool `json:"disableTrustOnFirstUse"` + InstanceAge Duration `json:"instanceAge,omitempty"` + Claims *Claims `json:"claims,omitempty"` + Options *Options `json:"options,omitempty"` claimer *Claimer config *gcpConfig keyStore *keyStore @@ -394,7 +394,7 @@ func (p *GCP) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption, } // Default to host + known hostnames - defaults := SSHOptions{ + defaults := SignSSHOptions{ CertType: SSHHostCert, Principals: principals, } diff --git a/authority/provisioner/gcp_test.go b/authority/provisioner/gcp_test.go index 66b2ea0e..23e306f4 100644 --- a/authority/provisioner/gcp_test.go +++ b/authority/provisioner/gcp_test.go @@ -623,51 +623,51 @@ func TestGCP_AuthorizeSSHSign(t *testing.T) { assert.FatalError(t, err) hostDuration := p1.claimer.DefaultHostSSHCertDuration() - expectedHostOptions := &SSHOptions{ + expectedHostOptions := &SignSSHOptions{ CertType: "host", Principals: []string{"instance-name.c.project-id.internal", "instance-name.zone.c.project-id.internal"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)), } - expectedHostOptionsPrincipal1 := &SSHOptions{ + expectedHostOptionsPrincipal1 := &SignSSHOptions{ CertType: "host", Principals: []string{"instance-name.c.project-id.internal"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)), } - expectedHostOptionsPrincipal2 := &SSHOptions{ + expectedHostOptionsPrincipal2 := &SignSSHOptions{ CertType: "host", Principals: []string{"instance-name.zone.c.project-id.internal"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)), } - expectedCustomOptions := &SSHOptions{ + expectedCustomOptions := &SignSSHOptions{ CertType: "host", Principals: []string{"foo.bar", "bar.foo"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)), } type args struct { token string - sshOpts SSHOptions + sshOpts SignSSHOptions key interface{} } tests := []struct { name string gcp *GCP args args - expected *SSHOptions + expected *SignSSHOptions code int wantErr bool wantSignErr bool }{ - {"ok", p1, args{t1, SSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false}, - {"ok-rsa2048", p1, args{t1, SSHOptions{}, rsa2048.Public()}, expectedHostOptions, http.StatusOK, false, false}, - {"ok-type", p1, args{t1, SSHOptions{CertType: "host"}, pub}, expectedHostOptions, http.StatusOK, false, false}, - {"ok-principals", p1, args{t1, SSHOptions{Principals: []string{"instance-name.c.project-id.internal", "instance-name.zone.c.project-id.internal"}}, pub}, expectedHostOptions, http.StatusOK, false, false}, - {"ok-principal1", p1, args{t1, SSHOptions{Principals: []string{"instance-name.c.project-id.internal"}}, pub}, expectedHostOptionsPrincipal1, http.StatusOK, false, false}, - {"ok-principal2", p1, args{t1, SSHOptions{Principals: []string{"instance-name.zone.c.project-id.internal"}}, pub}, expectedHostOptionsPrincipal2, http.StatusOK, false, false}, - {"ok-options", p1, args{t1, SSHOptions{CertType: "host", Principals: []string{"instance-name.c.project-id.internal", "instance-name.zone.c.project-id.internal"}}, pub}, expectedHostOptions, http.StatusOK, false, false}, - {"ok-custom", p2, args{t2, SSHOptions{Principals: []string{"foo.bar", "bar.foo"}}, pub}, expectedCustomOptions, http.StatusOK, false, false}, - {"fail-rsa1024", p1, args{t1, SSHOptions{}, rsa1024.Public()}, expectedHostOptions, http.StatusOK, false, true}, - {"fail-type", p1, args{t1, SSHOptions{CertType: "user"}, pub}, nil, http.StatusOK, false, true}, - {"fail-principal", p1, args{t1, SSHOptions{Principals: []string{"smallstep.com"}}, pub}, nil, http.StatusOK, false, true}, - {"fail-extra-principal", p1, args{t1, SSHOptions{Principals: []string{"instance-name.c.project-id.internal", "instance-name.zone.c.project-id.internal", "smallstep.com"}}, pub}, nil, http.StatusOK, false, true}, - {"fail-sshCA-disabled", p3, args{"foo", SSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false}, - {"fail-invalid-token", p1, args{"foo", SSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false}, + {"ok", p1, args{t1, SignSSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false}, + {"ok-rsa2048", p1, args{t1, SignSSHOptions{}, rsa2048.Public()}, expectedHostOptions, http.StatusOK, false, false}, + {"ok-type", p1, args{t1, SignSSHOptions{CertType: "host"}, pub}, expectedHostOptions, http.StatusOK, false, false}, + {"ok-principals", p1, args{t1, SignSSHOptions{Principals: []string{"instance-name.c.project-id.internal", "instance-name.zone.c.project-id.internal"}}, pub}, expectedHostOptions, http.StatusOK, false, false}, + {"ok-principal1", p1, args{t1, SignSSHOptions{Principals: []string{"instance-name.c.project-id.internal"}}, pub}, expectedHostOptionsPrincipal1, http.StatusOK, false, false}, + {"ok-principal2", p1, args{t1, SignSSHOptions{Principals: []string{"instance-name.zone.c.project-id.internal"}}, pub}, expectedHostOptionsPrincipal2, http.StatusOK, false, false}, + {"ok-options", p1, args{t1, SignSSHOptions{CertType: "host", Principals: []string{"instance-name.c.project-id.internal", "instance-name.zone.c.project-id.internal"}}, pub}, expectedHostOptions, http.StatusOK, false, false}, + {"ok-custom", p2, args{t2, SignSSHOptions{Principals: []string{"foo.bar", "bar.foo"}}, pub}, expectedCustomOptions, http.StatusOK, false, false}, + {"fail-rsa1024", p1, args{t1, SignSSHOptions{}, rsa1024.Public()}, expectedHostOptions, http.StatusOK, false, true}, + {"fail-type", p1, args{t1, SignSSHOptions{CertType: "user"}, pub}, nil, http.StatusOK, false, true}, + {"fail-principal", p1, args{t1, SignSSHOptions{Principals: []string{"smallstep.com"}}, pub}, nil, http.StatusOK, false, true}, + {"fail-extra-principal", p1, args{t1, SignSSHOptions{Principals: []string{"instance-name.c.project-id.internal", "instance-name.zone.c.project-id.internal", "smallstep.com"}}, pub}, nil, http.StatusOK, false, true}, + {"fail-sshCA-disabled", p3, args{"foo", SignSSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false}, + {"fail-invalid-token", p1, args{"foo", SignSSHOptions{}, pub}, expectedHostOptions, http.StatusUnauthorized, true, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/authority/provisioner/jwk.go b/authority/provisioner/jwk.go index 68b104ce..2133727b 100644 --- a/authority/provisioner/jwk.go +++ b/authority/provisioner/jwk.go @@ -20,19 +20,19 @@ type jwtPayload struct { } type stepPayload struct { - SSH *SSHOptions `json:"ssh,omitempty"` + SSH *SignSSHOptions `json:"ssh,omitempty"` } // JWK is the default provisioner, an entity that can sign tokens necessary for // signature requests. type JWK struct { *base - Type string `json:"type"` - Name string `json:"name"` - Key *jose.JSONWebKey `json:"key"` - EncryptedKey string `json:"encryptedKey,omitempty"` - Claims *Claims `json:"claims,omitempty"` - Options *ProvisionerOptions `json:"options,omitempty"` + Type string `json:"type"` + Name string `json:"name"` + Key *jose.JSONWebKey `json:"key"` + EncryptedKey string `json:"encryptedKey,omitempty"` + Claims *Claims `json:"claims,omitempty"` + Options *Options `json:"options,omitempty"` claimer *Claimer audiences Audiences } diff --git a/authority/provisioner/jwk_test.go b/authority/provisioner/jwk_test.go index 1af89c8b..2048bc64 100644 --- a/authority/provisioner/jwk_test.go +++ b/authority/provisioner/jwk_test.go @@ -404,41 +404,41 @@ func TestJWK_AuthorizeSSHSign(t *testing.T) { userDuration := p1.claimer.DefaultUserSSHCertDuration() hostDuration := p1.claimer.DefaultHostSSHCertDuration() - expectedUserOptions := &SSHOptions{ + expectedUserOptions := &SignSSHOptions{ CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration)), } - expectedHostOptions := &SSHOptions{ + expectedHostOptions := &SignSSHOptions{ CertType: "host", Principals: []string{"smallstep.com"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)), } type args struct { token string - sshOpts SSHOptions + sshOpts SignSSHOptions key interface{} } tests := []struct { name string prov *JWK args args - expected *SSHOptions + expected *SignSSHOptions code int wantErr bool wantSignErr bool }{ - {"user", p1, args{t1, SSHOptions{}, pub}, expectedUserOptions, http.StatusOK, false, false}, - {"user-rsa2048", p1, args{t1, SSHOptions{}, rsa2048.Public()}, expectedUserOptions, http.StatusOK, false, false}, - {"user-type", p1, args{t1, SSHOptions{CertType: "user"}, pub}, expectedUserOptions, http.StatusOK, false, false}, - {"user-principals", p1, args{t1, SSHOptions{Principals: []string{"name"}}, pub}, expectedUserOptions, http.StatusOK, false, false}, - {"user-options", p1, args{t1, SSHOptions{CertType: "user", Principals: []string{"name"}}, pub}, expectedUserOptions, http.StatusOK, false, false}, - {"host", p1, args{t2, SSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false}, - {"host-type", p1, args{t2, SSHOptions{CertType: "host"}, pub}, expectedHostOptions, http.StatusOK, false, false}, - {"host-principals", p1, args{t2, SSHOptions{Principals: []string{"smallstep.com"}}, pub}, expectedHostOptions, http.StatusOK, false, false}, - {"host-options", p1, args{t2, SSHOptions{CertType: "host", Principals: []string{"smallstep.com"}}, pub}, expectedHostOptions, http.StatusOK, false, false}, - {"fail-sshCA-disabled", p2, args{"foo", SSHOptions{}, pub}, expectedUserOptions, http.StatusUnauthorized, true, false}, - {"fail-signature", p1, args{failSig, SSHOptions{}, pub}, nil, http.StatusUnauthorized, true, false}, - {"rail-rsa1024", p1, args{t1, SSHOptions{}, rsa1024.Public()}, expectedUserOptions, http.StatusOK, false, true}, + {"user", p1, args{t1, SignSSHOptions{}, pub}, expectedUserOptions, http.StatusOK, false, false}, + {"user-rsa2048", p1, args{t1, SignSSHOptions{}, rsa2048.Public()}, expectedUserOptions, http.StatusOK, false, false}, + {"user-type", p1, args{t1, SignSSHOptions{CertType: "user"}, pub}, expectedUserOptions, http.StatusOK, false, false}, + {"user-principals", p1, args{t1, SignSSHOptions{Principals: []string{"name"}}, pub}, expectedUserOptions, http.StatusOK, false, false}, + {"user-options", p1, args{t1, SignSSHOptions{CertType: "user", Principals: []string{"name"}}, pub}, expectedUserOptions, http.StatusOK, false, false}, + {"host", p1, args{t2, SignSSHOptions{}, pub}, expectedHostOptions, http.StatusOK, false, false}, + {"host-type", p1, args{t2, SignSSHOptions{CertType: "host"}, pub}, expectedHostOptions, http.StatusOK, false, false}, + {"host-principals", p1, args{t2, SignSSHOptions{Principals: []string{"smallstep.com"}}, pub}, expectedHostOptions, http.StatusOK, false, false}, + {"host-options", p1, args{t2, SignSSHOptions{CertType: "host", Principals: []string{"smallstep.com"}}, pub}, expectedHostOptions, http.StatusOK, false, false}, + {"fail-sshCA-disabled", p2, args{"foo", SignSSHOptions{}, pub}, expectedUserOptions, http.StatusUnauthorized, true, false}, + {"fail-signature", p1, args{failSig, SignSSHOptions{}, pub}, nil, http.StatusUnauthorized, true, false}, + {"rail-rsa1024", p1, args{t1, SignSSHOptions{}, rsa1024.Public()}, expectedUserOptions, http.StatusOK, false, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -487,72 +487,72 @@ func TestJWK_AuthorizeSign_SSHOptions(t *testing.T) { userDuration := p1.claimer.DefaultUserSSHCertDuration() hostDuration := p1.claimer.DefaultHostSSHCertDuration() - expectedUserOptions := &SSHOptions{ + expectedUserOptions := &SignSSHOptions{ CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration)), } - expectedHostOptions := &SSHOptions{ + expectedHostOptions := &SignSSHOptions{ CertType: "host", Principals: []string{"smallstep.com"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)), } type args struct { sub, iss, aud string iat time.Time - tokSSHOpts *SSHOptions - userSSHOpts *SSHOptions + tokSSHOpts *SignSSHOptions + userSSHOpts *SignSSHOptions jwk *jose.JSONWebKey } tests := []struct { name string prov *JWK args args - expected *SSHOptions + expected *SignSSHOptions wantErr bool wantSignErr bool }{ - {"ok-user", p1, args{sub, iss, aud, iat, &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{}, jwk}, expectedUserOptions, false, false}, - {"ok-host", p1, args{sub, iss, aud, iat, &SSHOptions{CertType: "host", Principals: []string{"smallstep.com"}}, &SSHOptions{}, jwk}, expectedHostOptions, false, false}, - {"ok-user-opts", p1, args{sub, iss, aud, iat, &SSHOptions{}, &SSHOptions{CertType: "user", Principals: []string{"name"}}, jwk}, expectedUserOptions, false, false}, - {"ok-host-opts", p1, args{sub, iss, aud, iat, &SSHOptions{}, &SSHOptions{CertType: "host", Principals: []string{"smallstep.com"}}, jwk}, expectedHostOptions, false, false}, - {"ok-user-mixed", p1, args{sub, iss, aud, iat, &SSHOptions{CertType: "user"}, &SSHOptions{Principals: []string{"name"}}, jwk}, expectedUserOptions, false, false}, - {"ok-host-mixed", p1, args{sub, iss, aud, iat, &SSHOptions{Principals: []string{"smallstep.com"}}, &SSHOptions{CertType: "host"}, jwk}, expectedHostOptions, false, false}, - {"ok-user-validAfter", p1, args{sub, iss, aud, iat, &SSHOptions{ + {"ok-user", p1, args{sub, iss, aud, iat, &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{}, jwk}, expectedUserOptions, false, false}, + {"ok-host", p1, args{sub, iss, aud, iat, &SignSSHOptions{CertType: "host", Principals: []string{"smallstep.com"}}, &SignSSHOptions{}, jwk}, expectedHostOptions, false, false}, + {"ok-user-opts", p1, args{sub, iss, aud, iat, &SignSSHOptions{}, &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, jwk}, expectedUserOptions, false, false}, + {"ok-host-opts", p1, args{sub, iss, aud, iat, &SignSSHOptions{}, &SignSSHOptions{CertType: "host", Principals: []string{"smallstep.com"}}, jwk}, expectedHostOptions, false, false}, + {"ok-user-mixed", p1, args{sub, iss, aud, iat, &SignSSHOptions{CertType: "user"}, &SignSSHOptions{Principals: []string{"name"}}, jwk}, expectedUserOptions, false, false}, + {"ok-host-mixed", p1, args{sub, iss, aud, iat, &SignSSHOptions{Principals: []string{"smallstep.com"}}, &SignSSHOptions{CertType: "host"}, jwk}, expectedHostOptions, false, false}, + {"ok-user-validAfter", p1, args{sub, iss, aud, iat, &SignSSHOptions{ CertType: "user", Principals: []string{"name"}, - }, &SSHOptions{ + }, &SignSSHOptions{ ValidAfter: NewTimeDuration(tm.Add(-time.Hour)), - }, jwk}, &SSHOptions{ + }, jwk}, &SignSSHOptions{ CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm.Add(-time.Hour)), ValidBefore: NewTimeDuration(tm.Add(userDuration - time.Hour)), }, false, false}, - {"ok-user-validBefore", p1, args{sub, iss, aud, iat, &SSHOptions{ + {"ok-user-validBefore", p1, args{sub, iss, aud, iat, &SignSSHOptions{ CertType: "user", Principals: []string{"name"}, - }, &SSHOptions{ + }, &SignSSHOptions{ ValidBefore: NewTimeDuration(tm.Add(time.Hour)), - }, jwk}, &SSHOptions{ + }, jwk}, &SignSSHOptions{ CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(time.Hour)), }, false, false}, - {"ok-user-validAfter-validBefore", p1, args{sub, iss, aud, iat, &SSHOptions{ + {"ok-user-validAfter-validBefore", p1, args{sub, iss, aud, iat, &SignSSHOptions{ CertType: "user", Principals: []string{"name"}, - }, &SSHOptions{ + }, &SignSSHOptions{ ValidAfter: NewTimeDuration(tm.Add(10 * time.Minute)), ValidBefore: NewTimeDuration(tm.Add(time.Hour)), - }, jwk}, &SSHOptions{ + }, jwk}, &SignSSHOptions{ CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm.Add(10 * time.Minute)), ValidBefore: NewTimeDuration(tm.Add(time.Hour)), }, false, false}, - {"ok-user-match", p1, args{sub, iss, aud, iat, &SSHOptions{ + {"ok-user-match", p1, args{sub, iss, aud, iat, &SignSSHOptions{ CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(1 * time.Hour)), - }, &SSHOptions{ + }, &SignSSHOptions{ CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(1 * time.Hour)), - }, jwk}, &SSHOptions{ + }, jwk}, &SignSSHOptions{ CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(time.Hour)), }, false, false}, - {"fail-certType", p1, args{sub, iss, aud, iat, &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{CertType: "host"}, jwk}, nil, false, true}, - {"fail-principals", p1, args{sub, iss, aud, iat, &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{Principals: []string{"root"}}, jwk}, nil, false, true}, - {"fail-validAfter", p1, args{sub, iss, aud, iat, &SSHOptions{CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm)}, &SSHOptions{ValidAfter: NewTimeDuration(tm.Add(time.Hour))}, jwk}, nil, false, true}, - {"fail-validBefore", p1, args{sub, iss, aud, iat, &SSHOptions{CertType: "user", Principals: []string{"name"}, ValidBefore: NewTimeDuration(tm.Add(time.Hour))}, &SSHOptions{ValidBefore: NewTimeDuration(tm.Add(10 * time.Hour))}, jwk}, nil, false, true}, - {"fail-subject", p1, args{"", iss, aud, iat, &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{}, jwk}, nil, true, false}, - {"fail-issuer", p1, args{sub, "invalid", aud, iat, &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{}, jwk}, nil, true, false}, - {"fail-audience", p1, args{sub, iss, "invalid", iat, &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{}, jwk}, nil, true, false}, - {"fail-expired", p1, args{sub, iss, aud, iat.Add(-6 * time.Minute), &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{}, jwk}, nil, true, false}, - {"fail-notBefore", p1, args{sub, iss, aud, iat.Add(5 * time.Minute), &SSHOptions{CertType: "user", Principals: []string{"name"}}, &SSHOptions{}, jwk}, nil, true, false}, + {"fail-certType", p1, args{sub, iss, aud, iat, &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{CertType: "host"}, jwk}, nil, false, true}, + {"fail-principals", p1, args{sub, iss, aud, iat, &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{Principals: []string{"root"}}, jwk}, nil, false, true}, + {"fail-validAfter", p1, args{sub, iss, aud, iat, &SignSSHOptions{CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm)}, &SignSSHOptions{ValidAfter: NewTimeDuration(tm.Add(time.Hour))}, jwk}, nil, false, true}, + {"fail-validBefore", p1, args{sub, iss, aud, iat, &SignSSHOptions{CertType: "user", Principals: []string{"name"}, ValidBefore: NewTimeDuration(tm.Add(time.Hour))}, &SignSSHOptions{ValidBefore: NewTimeDuration(tm.Add(10 * time.Hour))}, jwk}, nil, false, true}, + {"fail-subject", p1, args{"", iss, aud, iat, &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{}, jwk}, nil, true, false}, + {"fail-issuer", p1, args{sub, "invalid", aud, iat, &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{}, jwk}, nil, true, false}, + {"fail-audience", p1, args{sub, iss, "invalid", iat, &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{}, jwk}, nil, true, false}, + {"fail-expired", p1, args{sub, iss, aud, iat.Add(-6 * time.Minute), &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{}, jwk}, nil, true, false}, + {"fail-notBefore", p1, args{sub, iss, aud, iat.Add(5 * time.Minute), &SignSSHOptions{CertType: "user", Principals: []string{"name"}}, &SignSSHOptions{}, jwk}, nil, true, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -561,7 +561,7 @@ func TestJWK_AuthorizeSign_SSHOptions(t *testing.T) { if got, err := tt.prov.AuthorizeSSHSign(context.Background(), token); (err != nil) != tt.wantErr { t.Errorf("JWK.AuthorizeSSHSign() error = %v, wantErr %v", err, tt.wantErr) } else if !tt.wantErr && assert.NotNil(t, got) { - var opts SSHOptions + var opts SignSSHOptions if tt.args.userSSHOpts != nil { opts = *tt.args.userSSHOpts } diff --git a/authority/provisioner/k8sSA.go b/authority/provisioner/k8sSA.go index 15e6569c..3c37cae7 100644 --- a/authority/provisioner/k8sSA.go +++ b/authority/provisioner/k8sSA.go @@ -41,11 +41,11 @@ type k8sSAPayload struct { // entity trusted to make signature requests. type K8sSA struct { *base - Type string `json:"type"` - Name string `json:"name"` - PubKeys []byte `json:"publicKeys,omitempty"` - Claims *Claims `json:"claims,omitempty"` - Options *ProvisionerOptions `json:"options,omitempty"` + Type string `json:"type"` + Name string `json:"name"` + PubKeys []byte `json:"publicKeys,omitempty"` + Claims *Claims `json:"claims,omitempty"` + Options *Options `json:"options,omitempty"` claimer *Claimer audiences Audiences //kauthn kauthn.AuthenticationV1Interface diff --git a/authority/provisioner/oidc.go b/authority/provisioner/oidc.go index eaac13a9..c4fa4839 100644 --- a/authority/provisioner/oidc.go +++ b/authority/provisioner/oidc.go @@ -53,18 +53,18 @@ type openIDPayload struct { // ClientSecret is mandatory, but it can be an empty string. type OIDC struct { *base - Type string `json:"type"` - Name string `json:"name"` - ClientID string `json:"clientID"` - ClientSecret string `json:"clientSecret"` - ConfigurationEndpoint string `json:"configurationEndpoint"` - TenantID string `json:"tenantID,omitempty"` - Admins []string `json:"admins,omitempty"` - Domains []string `json:"domains,omitempty"` - Groups []string `json:"groups,omitempty"` - ListenAddress string `json:"listenAddress,omitempty"` - Claims *Claims `json:"claims,omitempty"` - Options *ProvisionerOptions `json:"options,omitempty"` + Type string `json:"type"` + Name string `json:"name"` + ClientID string `json:"clientID"` + ClientSecret string `json:"clientSecret"` + ConfigurationEndpoint string `json:"configurationEndpoint"` + TenantID string `json:"tenantID,omitempty"` + Admins []string `json:"admins,omitempty"` + Domains []string `json:"domains,omitempty"` + Groups []string `json:"groups,omitempty"` + ListenAddress string `json:"listenAddress,omitempty"` + Claims *Claims `json:"claims,omitempty"` + Options *Options `json:"options,omitempty"` configuration openIDConfiguration keyStore *keyStore claimer *Claimer @@ -380,7 +380,7 @@ func (o *OIDC) AuthorizeSSHSign(ctx context.Context, token string) ([]SignOption if err != nil { return nil, errs.Wrap(http.StatusInternalServerError, err, "oidc.AuthorizeSSHSign") } - defaults := SSHOptions{ + defaults := SignSSHOptions{ CertType: SSHUserCert, Principals: iden.Usernames, } diff --git a/authority/provisioner/oidc_test.go b/authority/provisioner/oidc_test.go index 7bfd68ef..55093a91 100644 --- a/authority/provisioner/oidc_test.go +++ b/authority/provisioner/oidc_test.go @@ -534,64 +534,64 @@ func TestOIDC_AuthorizeSSHSign(t *testing.T) { userDuration := p1.claimer.DefaultUserSSHCertDuration() hostDuration := p1.claimer.DefaultHostSSHCertDuration() - expectedUserOptions := &SSHOptions{ + expectedUserOptions := &SignSSHOptions{ CertType: "user", Principals: []string{"name", "name@smallstep.com"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration)), } - expectedAdminOptions := &SSHOptions{ + expectedAdminOptions := &SignSSHOptions{ CertType: "user", Principals: []string{"root", "root@example.com"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration)), } - expectedHostOptions := &SSHOptions{ + expectedHostOptions := &SignSSHOptions{ CertType: "host", Principals: []string{"smallstep.com"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(hostDuration)), } type args struct { token string - sshOpts SSHOptions + sshOpts SignSSHOptions key interface{} } tests := []struct { name string prov *OIDC args args - expected *SSHOptions + expected *SignSSHOptions code int wantErr bool wantSignErr bool }{ - {"ok", p1, args{t1, SSHOptions{}, pub}, expectedUserOptions, http.StatusOK, false, false}, - {"ok-rsa2048", p1, args{t1, SSHOptions{}, rsa2048.Public()}, expectedUserOptions, http.StatusOK, false, false}, - {"ok-user", p1, args{t1, SSHOptions{CertType: "user"}, pub}, expectedUserOptions, http.StatusOK, false, false}, - {"ok-principals", p1, args{t1, SSHOptions{Principals: []string{"name"}}, pub}, - &SSHOptions{CertType: "user", Principals: []string{"name"}, + {"ok", p1, args{t1, SignSSHOptions{}, pub}, expectedUserOptions, http.StatusOK, false, false}, + {"ok-rsa2048", p1, args{t1, SignSSHOptions{}, rsa2048.Public()}, expectedUserOptions, http.StatusOK, false, false}, + {"ok-user", p1, args{t1, SignSSHOptions{CertType: "user"}, pub}, expectedUserOptions, http.StatusOK, false, false}, + {"ok-principals", p1, args{t1, SignSSHOptions{Principals: []string{"name"}}, pub}, + &SignSSHOptions{CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false}, - {"ok-principals-getIdentity", p4, args{okGetIdentityToken, SSHOptions{Principals: []string{"mariano"}}, pub}, - &SSHOptions{CertType: "user", Principals: []string{"mariano"}, + {"ok-principals-getIdentity", p4, args{okGetIdentityToken, SignSSHOptions{Principals: []string{"mariano"}}, pub}, + &SignSSHOptions{CertType: "user", Principals: []string{"mariano"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false}, - {"ok-emptyPrincipals-getIdentity", p4, args{okGetIdentityToken, SSHOptions{}, pub}, - &SSHOptions{CertType: "user", Principals: []string{"max", "mariano"}, + {"ok-emptyPrincipals-getIdentity", p4, args{okGetIdentityToken, SignSSHOptions{}, pub}, + &SignSSHOptions{CertType: "user", Principals: []string{"max", "mariano"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false}, - {"ok-options", p1, args{t1, SSHOptions{CertType: "user", Principals: []string{"name"}}, pub}, - &SSHOptions{CertType: "user", Principals: []string{"name"}, + {"ok-options", p1, args{t1, SignSSHOptions{CertType: "user", Principals: []string{"name"}}, pub}, + &SignSSHOptions{CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false}, - {"admin", p3, args{okAdmin, SSHOptions{}, pub}, expectedAdminOptions, http.StatusOK, false, false}, - {"admin-user", p3, args{okAdmin, SSHOptions{CertType: "user"}, pub}, expectedAdminOptions, http.StatusOK, false, false}, - {"admin-principals", p3, args{okAdmin, SSHOptions{Principals: []string{"root"}}, pub}, - &SSHOptions{CertType: "user", Principals: []string{"root"}, + {"admin", p3, args{okAdmin, SignSSHOptions{}, pub}, expectedAdminOptions, http.StatusOK, false, false}, + {"admin-user", p3, args{okAdmin, SignSSHOptions{CertType: "user"}, pub}, expectedAdminOptions, http.StatusOK, false, false}, + {"admin-principals", p3, args{okAdmin, SignSSHOptions{Principals: []string{"root"}}, pub}, + &SignSSHOptions{CertType: "user", Principals: []string{"root"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false}, - {"admin-options", p3, args{okAdmin, SSHOptions{CertType: "user", Principals: []string{"name"}}, pub}, - &SSHOptions{CertType: "user", Principals: []string{"name"}, + {"admin-options", p3, args{okAdmin, SignSSHOptions{CertType: "user", Principals: []string{"name"}}, pub}, + &SignSSHOptions{CertType: "user", Principals: []string{"name"}, ValidAfter: NewTimeDuration(tm), ValidBefore: NewTimeDuration(tm.Add(userDuration))}, http.StatusOK, false, false}, - {"admin-host", p3, args{okAdmin, SSHOptions{CertType: "host", Principals: []string{"smallstep.com"}}, pub}, + {"admin-host", p3, args{okAdmin, SignSSHOptions{CertType: "host", Principals: []string{"smallstep.com"}}, pub}, expectedHostOptions, http.StatusOK, false, false}, - {"fail-rsa1024", p1, args{t1, SSHOptions{}, rsa1024.Public()}, expectedUserOptions, http.StatusOK, false, true}, - {"fail-user-host", p1, args{t1, SSHOptions{CertType: "host"}, pub}, nil, http.StatusOK, false, true}, - {"fail-user-principals", p1, args{t1, SSHOptions{Principals: []string{"root"}}, pub}, nil, http.StatusOK, false, true}, - {"fail-email", p3, args{failEmail, SSHOptions{}, pub}, nil, http.StatusUnauthorized, true, false}, - {"fail-getIdentity", p5, args{failGetIdentityToken, SSHOptions{}, pub}, nil, http.StatusInternalServerError, true, false}, - {"fail-sshCA-disabled", p6, args{"foo", SSHOptions{}, pub}, nil, http.StatusUnauthorized, true, false}, + {"fail-rsa1024", p1, args{t1, SignSSHOptions{}, rsa1024.Public()}, expectedUserOptions, http.StatusOK, false, true}, + {"fail-user-host", p1, args{t1, SignSSHOptions{CertType: "host"}, pub}, nil, http.StatusOK, false, true}, + {"fail-user-principals", p1, args{t1, SignSSHOptions{Principals: []string{"root"}}, pub}, nil, http.StatusOK, false, true}, + {"fail-email", p3, args{failEmail, SignSSHOptions{}, pub}, nil, http.StatusUnauthorized, true, false}, + {"fail-getIdentity", p5, args{failGetIdentityToken, SignSSHOptions{}, pub}, nil, http.StatusInternalServerError, true, false}, + {"fail-sshCA-disabled", p6, args{"foo", SignSSHOptions{}, pub}, nil, http.StatusUnauthorized, true, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/authority/provisioner/options.go b/authority/provisioner/options.go index f3df716f..ba1c8efb 100644 --- a/authority/provisioner/options.go +++ b/authority/provisioner/options.go @@ -12,19 +12,18 @@ import ( // CertificateOptions is an interface that returns a list of options passed when // creating a new certificate. type CertificateOptions interface { - Options(Options) []x509util.Option + Options(SignOptions) []x509util.Option } -type certificateOptionsFunc func(Options) []x509util.Option +type certificateOptionsFunc func(SignOptions) []x509util.Option -func (fn certificateOptionsFunc) Options(so Options) []x509util.Option { +func (fn certificateOptionsFunc) Options(so SignOptions) []x509util.Option { return fn(so) } -// ProvisionerOptions are a collection of custom options that can be added to +// Options are a collection of custom options that can be added to // each provisioner. -// nolint:golint -type ProvisionerOptions struct { +type Options struct { // Template contains a X.509 certificate template. It can be a JSON template // escaped in a string or it can be also encoded in base64. Template string `json:"template"` @@ -38,7 +37,7 @@ type ProvisionerOptions struct { } // HasTemplate returns true if a template is defined in the provisioner options. -func (o *ProvisionerOptions) HasTemplate() bool { +func (o *Options) HasTemplate() bool { return o != nil && (o.Template != "" || o.TemplateFile != "") } @@ -46,7 +45,7 @@ func (o *ProvisionerOptions) HasTemplate() bool { // defined in the ProvisionerOptions, the provisioner generated data, and the // user data provided in the request. If no template has been provided, // x509util.DefaultLeafTemplate will be used. -func TemplateOptions(o *ProvisionerOptions, data x509util.TemplateData) (CertificateOptions, error) { +func TemplateOptions(o *Options, data x509util.TemplateData) (CertificateOptions, error) { return CustomTemplateOptions(o, data, x509util.DefaultLeafTemplate) } @@ -54,7 +53,7 @@ func TemplateOptions(o *ProvisionerOptions, data x509util.TemplateData) (Certifi // defined in the ProvisionerOptions, the provisioner generated data and the // user data provided in the request. If no template has been provided in the // ProvisionerOptions, the given template will be used. -func CustomTemplateOptions(o *ProvisionerOptions, data x509util.TemplateData, defaultTemplate string) (CertificateOptions, error) { +func CustomTemplateOptions(o *Options, data x509util.TemplateData, defaultTemplate string) (CertificateOptions, error) { if o != nil { if data == nil { data = x509util.NewTemplateData() @@ -68,7 +67,7 @@ func CustomTemplateOptions(o *ProvisionerOptions, data x509util.TemplateData, de } } - return certificateOptionsFunc(func(so Options) []x509util.Option { + return certificateOptionsFunc(func(so SignOptions) []x509util.Option { // We're not provided user data without custom templates. if !o.HasTemplate() { return []x509util.Option{ diff --git a/authority/provisioner/options_test.go b/authority/provisioner/options_test.go index cb47062c..a7ab3ece 100644 --- a/authority/provisioner/options_test.go +++ b/authority/provisioner/options_test.go @@ -42,7 +42,7 @@ func TestProvisionerOptions_HasTemplate(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - o := &ProvisionerOptions{ + o := &Options{ Template: tt.fields.Template, TemplateFile: tt.fields.TemplateFile, TemplateData: tt.fields.TemplateData, @@ -65,7 +65,7 @@ func TestTemplateOptions(t *testing.T) { }, } type args struct { - o *ProvisionerOptions + o *Options data x509util.TemplateData } tests := []struct { @@ -81,14 +81,14 @@ func TestTemplateOptions(t *testing.T) { "keyUsage": ["digitalSignature"], "extKeyUsage": ["serverAuth", "clientAuth"] }`)}, false}, - {"okCustomTemplate", args{&ProvisionerOptions{Template: x509util.DefaultIIDLeafTemplate}, data}, x509util.Options{ + {"okCustomTemplate", args{&Options{Template: x509util.DefaultIIDLeafTemplate}, data}, x509util.Options{ CertBuffer: bytes.NewBufferString(`{ "subject": {"commonName":"foo"}, "sans": [{"type":"dns","value":"foo.com"}], "keyUsage": ["digitalSignature"], "extKeyUsage": ["serverAuth", "clientAuth"] }`)}, false}, - {"fail", args{&ProvisionerOptions{TemplateData: []byte(`{"badJSON`)}, data}, x509util.Options{}, true}, + {"fail", args{&Options{TemplateData: []byte(`{"badJSON`)}, data}, x509util.Options{}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -99,7 +99,7 @@ func TestTemplateOptions(t *testing.T) { } var opts x509util.Options if cof != nil { - for _, fn := range cof.Options(Options{}) { + for _, fn := range cof.Options(SignOptions{}) { if err := fn(csr, &opts); err != nil { t.Errorf("x509util.Options() error = %v", err) return @@ -125,10 +125,10 @@ func TestCustomTemplateOptions(t *testing.T) { }, } type args struct { - o *ProvisionerOptions + o *Options data x509util.TemplateData defaultTemplate string - userOptions Options + userOptions SignOptions } tests := []struct { name string @@ -136,48 +136,48 @@ func TestCustomTemplateOptions(t *testing.T) { want x509util.Options wantErr bool }{ - {"ok", args{nil, data, x509util.DefaultLeafTemplate, Options{}}, x509util.Options{ + {"ok", args{nil, data, x509util.DefaultLeafTemplate, SignOptions{}}, x509util.Options{ CertBuffer: bytes.NewBufferString(`{ "subject": {"commonName":"foobar"}, "sans": [{"type":"dns","value":"foo.com"}], "keyUsage": ["digitalSignature"], "extKeyUsage": ["serverAuth", "clientAuth"] }`)}, false}, - {"okIID", args{nil, data, x509util.DefaultIIDLeafTemplate, Options{}}, x509util.Options{ + {"okIID", args{nil, data, x509util.DefaultIIDLeafTemplate, SignOptions{}}, x509util.Options{ CertBuffer: bytes.NewBufferString(`{ "subject": {"commonName":"foo"}, "sans": [{"type":"dns","value":"foo.com"}], "keyUsage": ["digitalSignature"], "extKeyUsage": ["serverAuth", "clientAuth"] }`)}, false}, - {"okNoData", args{&ProvisionerOptions{}, nil, x509util.DefaultLeafTemplate, Options{}}, x509util.Options{ + {"okNoData", args{&Options{}, nil, x509util.DefaultLeafTemplate, SignOptions{}}, x509util.Options{ CertBuffer: bytes.NewBufferString(`{ "subject": null, "sans": null, "keyUsage": ["digitalSignature"], "extKeyUsage": ["serverAuth", "clientAuth"] }`)}, false}, - {"okTemplateData", args{&ProvisionerOptions{TemplateData: []byte(`{"foo":"bar"}`)}, data, x509util.DefaultLeafTemplate, Options{}}, x509util.Options{ + {"okTemplateData", args{&Options{TemplateData: []byte(`{"foo":"bar"}`)}, data, x509util.DefaultLeafTemplate, SignOptions{}}, x509util.Options{ CertBuffer: bytes.NewBufferString(`{ "subject": {"commonName":"foobar"}, "sans": [{"type":"dns","value":"foo.com"}], "keyUsage": ["digitalSignature"], "extKeyUsage": ["serverAuth", "clientAuth"] }`)}, false}, - {"okTemplate", args{&ProvisionerOptions{Template: "{{ toJson .Insecure.CR }}"}, data, x509util.DefaultLeafTemplate, Options{}}, x509util.Options{ + {"okTemplate", args{&Options{Template: "{{ toJson .Insecure.CR }}"}, data, x509util.DefaultLeafTemplate, SignOptions{}}, x509util.Options{ CertBuffer: bytes.NewBufferString(csrCertificate)}, false}, - {"okFile", args{&ProvisionerOptions{TemplateFile: "./testdata/templates/cr.tpl"}, data, x509util.DefaultLeafTemplate, Options{}}, x509util.Options{ + {"okFile", args{&Options{TemplateFile: "./testdata/templates/cr.tpl"}, data, x509util.DefaultLeafTemplate, SignOptions{}}, x509util.Options{ CertBuffer: bytes.NewBufferString(csrCertificate)}, false}, - {"okBase64", args{&ProvisionerOptions{Template: "e3sgdG9Kc29uIC5JbnNlY3VyZS5DUiB9fQ=="}, data, x509util.DefaultLeafTemplate, Options{}}, x509util.Options{ + {"okBase64", args{&Options{Template: "e3sgdG9Kc29uIC5JbnNlY3VyZS5DUiB9fQ=="}, data, x509util.DefaultLeafTemplate, SignOptions{}}, x509util.Options{ CertBuffer: bytes.NewBufferString(csrCertificate)}, false}, - {"okUserOptions", args{&ProvisionerOptions{Template: `{"foo": "{{.Insecure.User.foo}}"}`}, data, x509util.DefaultLeafTemplate, Options{TemplateData: []byte(`{"foo":"bar"}`)}}, x509util.Options{ + {"okUserOptions", args{&Options{Template: `{"foo": "{{.Insecure.User.foo}}"}`}, data, x509util.DefaultLeafTemplate, SignOptions{TemplateData: []byte(`{"foo":"bar"}`)}}, x509util.Options{ CertBuffer: bytes.NewBufferString(`{"foo": "bar"}`), }, false}, - {"okBadUserOptions", args{&ProvisionerOptions{Template: `{"foo": "{{.Insecure.User.foo}}"}`}, data, x509util.DefaultLeafTemplate, Options{TemplateData: []byte(`{"badJSON"}`)}}, x509util.Options{ + {"okBadUserOptions", args{&Options{Template: `{"foo": "{{.Insecure.User.foo}}"}`}, data, x509util.DefaultLeafTemplate, SignOptions{TemplateData: []byte(`{"badJSON"}`)}}, x509util.Options{ CertBuffer: bytes.NewBufferString(`{"foo": ""}`), }, false}, - {"fail", args{&ProvisionerOptions{TemplateData: []byte(`{"badJSON`)}, data, x509util.DefaultLeafTemplate, Options{}}, x509util.Options{}, true}, - {"failTemplateData", args{&ProvisionerOptions{TemplateData: []byte(`{"badJSON}`)}, data, x509util.DefaultLeafTemplate, Options{}}, x509util.Options{}, true}, + {"fail", args{&Options{TemplateData: []byte(`{"badJSON`)}, data, x509util.DefaultLeafTemplate, SignOptions{}}, x509util.Options{}, true}, + {"failTemplateData", args{&Options{TemplateData: []byte(`{"badJSON}`)}, data, x509util.DefaultLeafTemplate, SignOptions{}}, x509util.Options{}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/authority/provisioner/sign_options.go b/authority/provisioner/sign_options.go index 85d0e967..d3ca4683 100644 --- a/authority/provisioner/sign_options.go +++ b/authority/provisioner/sign_options.go @@ -20,9 +20,9 @@ import ( // DefaultCertValidity is the default validity for a certificate if none is specified. const DefaultCertValidity = 24 * time.Hour -// Options contains the options that can be passed to the Sign method. Backdate +// SignOptions contains the options that can be passed to the Sign method. Backdate // is automatically filled and can only be configured in the CA. -type Options struct { +type SignOptions struct { NotAfter TimeDuration `json:"notAfter"` NotBefore TimeDuration `json:"notBefore"` TemplateData json.RawMessage `json:"templateData"` @@ -35,7 +35,7 @@ type SignOption interface{} // CertificateValidator is an interface used to validate a given X.509 certificate. type CertificateValidator interface { - Valid(cert *x509.Certificate, opts Options) error + Valid(cert *x509.Certificate, opts SignOptions) error } // CertificateRequestValidator is an interface used to validate a given X.509 certificate request. @@ -47,7 +47,7 @@ type CertificateRequestValidator interface { // Types implementing this interface will be validated with a // CertificateValidator. type CertificateModifier interface { - Modify(cert *x509.Certificate, opts Options) error + Modify(cert *x509.Certificate, opts SignOptions) error } // CertificateEnforcer is an interface used to modify a given X.509 certificate. @@ -59,10 +59,10 @@ type CertificateEnforcer interface { // CertificateModifierFunc allows to create simple certificate modifiers just // with a function. -type CertificateModifierFunc func(cert *x509.Certificate, opts Options) error +type CertificateModifierFunc func(cert *x509.Certificate, opts SignOptions) error // Modify implements CertificateModifier and just calls the defined function. -func (fn CertificateModifierFunc) Modify(cert *x509.Certificate, opts Options) error { +func (fn CertificateModifierFunc) Modify(cert *x509.Certificate, opts SignOptions) error { return fn(cert, opts) } @@ -270,7 +270,7 @@ func (eee ExtraExtsEnforcer) Enforce(cert *x509.Certificate) error { // duration. type profileDefaultDuration time.Duration -func (v profileDefaultDuration) Modify(cert *x509.Certificate, so Options) error { +func (v profileDefaultDuration) Modify(cert *x509.Certificate, so SignOptions) error { var backdate time.Duration notBefore := so.NotBefore.Time() if notBefore.IsZero() { @@ -301,7 +301,7 @@ type profileLimitDuration struct { // Option returns an x509util option that limits the validity period of a // certificate to one that is superficially imposed. -func (v profileLimitDuration) Modify(cert *x509.Certificate, so Options) error { +func (v profileLimitDuration) Modify(cert *x509.Certificate, so SignOptions) error { var backdate time.Duration notBefore := so.NotBefore.Time() if notBefore.IsZero() { @@ -347,7 +347,7 @@ func newValidityValidator(min, max time.Duration) *validityValidator { // Valid validates the certificate validity settings (notBefore/notAfter) and // and total duration. -func (v *validityValidator) Valid(cert *x509.Certificate, o Options) error { +func (v *validityValidator) Valid(cert *x509.Certificate, o SignOptions) error { var ( na = cert.NotAfter.Truncate(time.Second) nb = cert.NotBefore.Truncate(time.Second) @@ -397,7 +397,7 @@ func newForceCNOption(forceCN bool) *forceCNOption { return &forceCNOption{forceCN} } -func (o *forceCNOption) Modify(cert *x509.Certificate, _ Options) error { +func (o *forceCNOption) Modify(cert *x509.Certificate, _ SignOptions) error { if !o.ForceCN { // Forcing CN is disabled, do nothing to certificate return nil @@ -430,7 +430,7 @@ func newProvisionerExtensionOption(typ Type, name, credentialID string, keyValue } } -func (o *provisionerExtensionOption) Modify(cert *x509.Certificate, _ Options) error { +func (o *provisionerExtensionOption) Modify(cert *x509.Certificate, _ SignOptions) error { ext, err := createProvisionerExtension(o.Type, o.Name, o.CredentialID, o.KeyValuePairs...) if err != nil { return err diff --git a/authority/provisioner/sign_options_test.go b/authority/provisioner/sign_options_test.go index e85e6360..459455bc 100644 --- a/authority/provisioner/sign_options_test.go +++ b/authority/provisioner/sign_options_test.go @@ -399,7 +399,7 @@ func Test_ExtraExtsEnforcer_Enforce(t *testing.T) { func Test_validityValidator_Valid(t *testing.T) { type test struct { cert *x509.Certificate - opts Options + opts SignOptions vv *validityValidator err error } @@ -408,7 +408,7 @@ func Test_validityValidator_Valid(t *testing.T) { return test{ vv: &validityValidator{5 * time.Minute, 24 * time.Hour}, cert: &x509.Certificate{NotAfter: time.Now().Add(-5 * time.Minute)}, - opts: Options{}, + opts: SignOptions{}, err: errors.New("notAfter cannot be in the past"), } }, @@ -417,7 +417,7 @@ func Test_validityValidator_Valid(t *testing.T) { vv: &validityValidator{5 * time.Minute, 24 * time.Hour}, cert: &x509.Certificate{NotBefore: time.Now().Add(10 * time.Minute), NotAfter: time.Now().Add(5 * time.Minute)}, - opts: Options{}, + opts: SignOptions{}, err: errors.New("notAfter cannot be before notBefore"), } }, @@ -427,7 +427,7 @@ func Test_validityValidator_Valid(t *testing.T) { vv: &validityValidator{5 * time.Minute, 24 * time.Hour}, cert: &x509.Certificate{NotBefore: n, NotAfter: n.Add(3 * time.Minute)}, - opts: Options{}, + opts: SignOptions{}, err: errors.New("is less than the authorized minimum certificate duration of "), } }, @@ -437,7 +437,7 @@ func Test_validityValidator_Valid(t *testing.T) { vv: &validityValidator{5 * time.Minute, 24 * time.Hour}, cert: &x509.Certificate{NotBefore: n, NotAfter: n.Add(5 * time.Minute)}, - opts: Options{}, + opts: SignOptions{}, } }, "fail/duration-too-great": func() test { @@ -464,7 +464,7 @@ func Test_validityValidator_Valid(t *testing.T) { return test{ vv: &validityValidator{5 * time.Minute, 24 * time.Hour}, cert: cert, - opts: Options{Backdate: time.Second}, + opts: SignOptions{Backdate: time.Second}, } }, "ok/duration-exact-max-with-backdate": func() test { @@ -475,7 +475,7 @@ func Test_validityValidator_Valid(t *testing.T) { return test{ vv: &validityValidator{5 * time.Minute, 24 * time.Hour}, cert: cert, - opts: Options{Backdate: backdate}, + opts: SignOptions{Backdate: backdate}, } }, } @@ -496,7 +496,7 @@ func Test_validityValidator_Valid(t *testing.T) { func Test_forceCN_Option(t *testing.T) { type test struct { - so Options + so SignOptions fcn forceCNOption cert *x509.Certificate valid func(*x509.Certificate) @@ -507,7 +507,7 @@ func Test_forceCN_Option(t *testing.T) { "ok/CN-not-forced": func() test { return test{ fcn: forceCNOption{false}, - so: Options{}, + so: SignOptions{}, cert: &x509.Certificate{ Subject: pkix.Name{}, DNSNames: []string{"acme.example.com", "step.example.com"}, @@ -520,7 +520,7 @@ func Test_forceCN_Option(t *testing.T) { "ok/CN-forced-and-set": func() test { return test{ fcn: forceCNOption{true}, - so: Options{}, + so: SignOptions{}, cert: &x509.Certificate{ Subject: pkix.Name{ CommonName: "Some Common Name", @@ -535,7 +535,7 @@ func Test_forceCN_Option(t *testing.T) { "ok/CN-forced-and-not-set": func() test { return test{ fcn: forceCNOption{true}, - so: Options{}, + so: SignOptions{}, cert: &x509.Certificate{ Subject: pkix.Name{}, DNSNames: []string{"acme.example.com", "step.example.com"}, @@ -548,7 +548,7 @@ func Test_forceCN_Option(t *testing.T) { "fail/CN-forced-and-empty-DNSNames": func() test { return test{ fcn: forceCNOption{true}, - so: Options{}, + so: SignOptions{}, cert: &x509.Certificate{ Subject: pkix.Name{}, DNSNames: []string{}, @@ -576,7 +576,7 @@ func Test_forceCN_Option(t *testing.T) { func Test_profileDefaultDuration_Option(t *testing.T) { type test struct { - so Options + so SignOptions pdd profileDefaultDuration cert *x509.Certificate valid func(*x509.Certificate) @@ -585,7 +585,7 @@ func Test_profileDefaultDuration_Option(t *testing.T) { "ok/notBefore-notAfter-duration-empty": func() test { return test{ pdd: profileDefaultDuration(0), - so: Options{}, + so: SignOptions{}, cert: new(x509.Certificate), valid: func(cert *x509.Certificate) { n := now() @@ -601,7 +601,7 @@ func Test_profileDefaultDuration_Option(t *testing.T) { nb := time.Now().Add(5 * time.Minute).UTC() return test{ pdd: profileDefaultDuration(0), - so: Options{NotBefore: NewTimeDuration(nb)}, + so: SignOptions{NotBefore: NewTimeDuration(nb)}, cert: new(x509.Certificate), valid: func(cert *x509.Certificate) { assert.Equals(t, cert.NotBefore, nb) @@ -613,7 +613,7 @@ func Test_profileDefaultDuration_Option(t *testing.T) { d := 4 * time.Hour return test{ pdd: profileDefaultDuration(d), - so: Options{Backdate: time.Second}, + so: SignOptions{Backdate: time.Second}, cert: new(x509.Certificate), valid: func(cert *x509.Certificate) { n := now() @@ -629,7 +629,7 @@ func Test_profileDefaultDuration_Option(t *testing.T) { na := now().Add(10 * time.Minute).UTC() return test{ pdd: profileDefaultDuration(0), - so: Options{NotAfter: NewTimeDuration(na)}, + so: SignOptions{NotAfter: NewTimeDuration(na)}, cert: new(x509.Certificate), valid: func(cert *x509.Certificate) { n := now() @@ -646,7 +646,7 @@ func Test_profileDefaultDuration_Option(t *testing.T) { d := 4 * time.Hour return test{ pdd: profileDefaultDuration(d), - so: Options{NotBefore: NewTimeDuration(nb), NotAfter: NewTimeDuration(na)}, + so: SignOptions{NotBefore: NewTimeDuration(nb), NotAfter: NewTimeDuration(na)}, cert: new(x509.Certificate), valid: func(cert *x509.Certificate) { assert.Equals(t, cert.NotBefore, nb) @@ -698,7 +698,7 @@ func Test_newProvisionerExtension_Option(t *testing.T) { for name, run := range tests { t.Run(name, func(t *testing.T) { tt := run() - assert.FatalError(t, newProvisionerExtensionOption(TypeJWK, "foo", "bar", "baz", "zap").Modify(tt.cert, Options{})) + assert.FatalError(t, newProvisionerExtensionOption(TypeJWK, "foo", "bar", "baz", "zap").Modify(tt.cert, SignOptions{})) tt.valid(tt.cert) }) } @@ -710,7 +710,7 @@ func Test_profileLimitDuration_Option(t *testing.T) { type test struct { pld profileLimitDuration - so Options + so SignOptions cert *x509.Certificate valid func(*x509.Certificate) err error @@ -721,7 +721,7 @@ func Test_profileLimitDuration_Option(t *testing.T) { assert.FatalError(t, err) return test{ pld: profileLimitDuration{def: 4 * time.Hour, notBefore: n.Add(8 * time.Hour)}, - so: Options{NotBefore: d}, + so: SignOptions{NotBefore: d}, cert: new(x509.Certificate), err: errors.New("requested certificate notBefore ("), } @@ -731,7 +731,7 @@ func Test_profileLimitDuration_Option(t *testing.T) { assert.FatalError(t, err) return test{ pld: profileLimitDuration{def: 4 * time.Hour, notAfter: n.Add(6 * time.Hour)}, - so: Options{NotBefore: NewTimeDuration(n.Add(3 * time.Hour)), NotAfter: d}, + so: SignOptions{NotBefore: NewTimeDuration(n.Add(3 * time.Hour)), NotAfter: d}, cert: new(x509.Certificate), err: errors.New("requested certificate notAfter ("), } @@ -741,7 +741,7 @@ func Test_profileLimitDuration_Option(t *testing.T) { assert.FatalError(t, err) return test{ pld: profileLimitDuration{def: 4 * time.Hour, notAfter: n.Add(6 * time.Hour)}, - so: Options{NotBefore: NewTimeDuration(n.Add(3 * time.Hour)), NotAfter: d, Backdate: 1 * time.Minute}, + so: SignOptions{NotBefore: NewTimeDuration(n.Add(3 * time.Hour)), NotAfter: d, Backdate: 1 * time.Minute}, cert: new(x509.Certificate), valid: func(cert *x509.Certificate) { assert.Equals(t, cert.NotBefore, n.Add(3*time.Hour)) @@ -752,7 +752,7 @@ func Test_profileLimitDuration_Option(t *testing.T) { "ok/valid-notAfter-nil-limit-over-default": func() test { return test{ pld: profileLimitDuration{def: 1 * time.Hour, notAfter: n.Add(6 * time.Hour)}, - so: Options{NotBefore: NewTimeDuration(n.Add(3 * time.Hour)), Backdate: 1 * time.Minute}, + so: SignOptions{NotBefore: NewTimeDuration(n.Add(3 * time.Hour)), Backdate: 1 * time.Minute}, cert: new(x509.Certificate), valid: func(cert *x509.Certificate) { assert.Equals(t, cert.NotBefore, n.Add(3*time.Hour)) @@ -763,7 +763,7 @@ func Test_profileLimitDuration_Option(t *testing.T) { "ok/valid-notAfter-nil-limit-under-default": func() test { return test{ pld: profileLimitDuration{def: 4 * time.Hour, notAfter: n.Add(6 * time.Hour)}, - so: Options{NotBefore: NewTimeDuration(n.Add(3 * time.Hour)), Backdate: 1 * time.Minute}, + so: SignOptions{NotBefore: NewTimeDuration(n.Add(3 * time.Hour)), Backdate: 1 * time.Minute}, cert: new(x509.Certificate), valid: func(cert *x509.Certificate) { assert.Equals(t, cert.NotBefore, n.Add(3*time.Hour)) @@ -774,7 +774,7 @@ func Test_profileLimitDuration_Option(t *testing.T) { "ok/over-limit-with-backdate": func() test { return test{ pld: profileLimitDuration{def: 24 * time.Hour, notAfter: n.Add(6 * time.Hour)}, - so: Options{Backdate: 1 * time.Minute}, + so: SignOptions{Backdate: 1 * time.Minute}, cert: new(x509.Certificate), valid: func(cert *x509.Certificate) { assert.Equals(t, cert.NotBefore, n.Add(-time.Minute)) @@ -785,7 +785,7 @@ func Test_profileLimitDuration_Option(t *testing.T) { "ok/under-limit-with-backdate": func() test { return test{ pld: profileLimitDuration{def: 24 * time.Hour, notAfter: n.Add(30 * time.Hour)}, - so: Options{Backdate: 1 * time.Minute}, + so: SignOptions{Backdate: 1 * time.Minute}, cert: new(x509.Certificate), valid: func(cert *x509.Certificate) { assert.Equals(t, cert.NotBefore, n.Add(-time.Minute)) diff --git a/authority/provisioner/sign_ssh_options.go b/authority/provisioner/sign_ssh_options.go index 34bc069f..e823a7d8 100644 --- a/authority/provisioner/sign_ssh_options.go +++ b/authority/provisioner/sign_ssh_options.go @@ -30,20 +30,20 @@ type SSHCertModifier interface { // to modify the SSH certificate. type SSHCertOptionModifier interface { SignOption - Option(o SSHOptions) SSHCertModifier + Option(o SignSSHOptions) SSHCertModifier } // SSHCertValidator is the interface used to validate an SSH certificate. type SSHCertValidator interface { SignOption - Valid(cert *ssh.Certificate, opts SSHOptions) error + Valid(cert *ssh.Certificate, opts SignSSHOptions) error } // SSHCertOptionsValidator is the interface used to validate the custom // options used to modify the SSH certificate. type SSHCertOptionsValidator interface { SignOption - Valid(got SSHOptions) error + Valid(got SignSSHOptions) error } // sshModifierFunc is an adapter to allow the use of ordinary functions as SSH @@ -54,8 +54,8 @@ func (f sshModifierFunc) Modify(cert *ssh.Certificate) error { return f(cert) } -// SSHOptions contains the options that can be passed to the SignSSH method. -type SSHOptions struct { +// SignSSHOptions contains the options that can be passed to the SignSSH method. +type SignSSHOptions struct { CertType string `json:"certType"` KeyID string `json:"keyID"` Principals []string `json:"principals"` @@ -65,12 +65,12 @@ type SSHOptions struct { } // Type returns the uint32 representation of the CertType. -func (o SSHOptions) Type() uint32 { +func (o SignSSHOptions) Type() uint32 { return sshCertTypeUInt32(o.CertType) } // Modify implements SSHCertModifier and sets the SSHOption in the ssh.Certificate. -func (o SSHOptions) Modify(cert *ssh.Certificate) error { +func (o SignSSHOptions) Modify(cert *ssh.Certificate) error { switch o.CertType { case "": // ignore case SSHUserCert: @@ -100,7 +100,7 @@ func (o SSHOptions) Modify(cert *ssh.Certificate) error { // match compares two SSHOptions and return an error if they don't match. It // ignores zero values. -func (o SSHOptions) match(got SSHOptions) error { +func (o SignSSHOptions) match(got SignSSHOptions) error { if o.CertType != "" && got.CertType != "" && o.CertType != got.CertType { return errors.Errorf("ssh certificate type does not match - got %v, want %v", got.CertType, o.CertType) } @@ -165,7 +165,7 @@ func (m sshCertValidBeforeModifier) Modify(cert *ssh.Certificate) error { // sshCertDefaultsModifier implements a SSHCertModifier that // modifies the certificate with the given options if they are not set. -type sshCertDefaultsModifier SSHOptions +type sshCertDefaultsModifier SignSSHOptions // Modify implements the SSHCertModifier interface. func (m sshCertDefaultsModifier) Modify(cert *ssh.Certificate) error { @@ -215,7 +215,7 @@ type sshDefaultDuration struct { *Claimer } -func (m *sshDefaultDuration) Option(o SSHOptions) SSHCertModifier { +func (m *sshDefaultDuration) Option(o SignSSHOptions) SSHCertModifier { return sshModifierFunc(func(cert *ssh.Certificate) error { d, err := m.DefaultSSHCertDuration(cert.CertType) if err != nil { @@ -248,7 +248,7 @@ type sshLimitDuration struct { NotAfter time.Time } -func (m *sshLimitDuration) Option(o SSHOptions) SSHCertModifier { +func (m *sshLimitDuration) Option(o SignSSHOptions) SSHCertModifier { if m.NotAfter.IsZero() { defaultDuration := &sshDefaultDuration{m.Claimer} return defaultDuration.Option(o) @@ -297,12 +297,12 @@ func (m *sshLimitDuration) Option(o SSHOptions) SSHCertModifier { // sshCertOptionsValidator validates the user SSHOptions with the ones // usually present in the token. -type sshCertOptionsValidator SSHOptions +type sshCertOptionsValidator SignSSHOptions // Valid implements SSHCertOptionsValidator and returns nil if both // SSHOptions match. -func (v sshCertOptionsValidator) Valid(got SSHOptions) error { - want := SSHOptions(v) +func (v sshCertOptionsValidator) Valid(got SignSSHOptions) error { + want := SignSSHOptions(v) return want.match(got) } @@ -310,7 +310,7 @@ type sshCertValidityValidator struct { *Claimer } -func (v *sshCertValidityValidator) Valid(cert *ssh.Certificate, opts SSHOptions) error { +func (v *sshCertValidityValidator) Valid(cert *ssh.Certificate, opts SignSSHOptions) error { switch { case cert.ValidAfter == 0: return errors.New("ssh certificate validAfter cannot be 0") @@ -355,7 +355,7 @@ func (v *sshCertValidityValidator) Valid(cert *ssh.Certificate, opts SSHOptions) type sshCertDefaultValidator struct{} // Valid returns an error if the given certificate does not contain the necessary fields. -func (v *sshCertDefaultValidator) Valid(cert *ssh.Certificate, o SSHOptions) error { +func (v *sshCertDefaultValidator) Valid(cert *ssh.Certificate, o SignSSHOptions) error { switch { case len(cert.Nonce) == 0: return errors.New("ssh certificate nonce cannot be empty") @@ -390,7 +390,7 @@ func (v *sshCertDefaultValidator) Valid(cert *ssh.Certificate, o SSHOptions) err type sshDefaultPublicKeyValidator struct{} // Valid checks that certificate request common name matches the one configured. -func (v sshDefaultPublicKeyValidator) Valid(cert *ssh.Certificate, o SSHOptions) error { +func (v sshDefaultPublicKeyValidator) Valid(cert *ssh.Certificate, o SignSSHOptions) error { if cert.Key == nil { return errors.New("ssh certificate key cannot be nil") } @@ -420,7 +420,7 @@ func (v sshDefaultPublicKeyValidator) Valid(cert *ssh.Certificate, o SSHOptions) type sshCertKeyIDValidator string // Valid returns an error if the given certificate does not contain the necessary fields. -func (v sshCertKeyIDValidator) Valid(cert *ssh.Certificate, o SSHOptions) error { +func (v sshCertKeyIDValidator) Valid(cert *ssh.Certificate, o SignSSHOptions) error { if string(v) != cert.KeyId { return errors.Errorf("invalid ssh certificate KeyId; want %s, but got %s", string(v), cert.KeyId) } diff --git a/authority/provisioner/sign_ssh_options_test.go b/authority/provisioner/sign_ssh_options_test.go index 940fc0e2..600fd975 100644 --- a/authority/provisioner/sign_ssh_options_test.go +++ b/authority/provisioner/sign_ssh_options_test.go @@ -28,7 +28,7 @@ func TestSSHOptions_Type(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - o := SSHOptions{ + o := SignSSHOptions{ CertType: tt.fields.CertType, } if got := o.Type(); got != tt.want { @@ -40,7 +40,7 @@ func TestSSHOptions_Type(t *testing.T) { func TestSSHOptions_Modify(t *testing.T) { type test struct { - so *SSHOptions + so *SignSSHOptions cert *ssh.Certificate valid func(*ssh.Certificate) err error @@ -48,21 +48,21 @@ func TestSSHOptions_Modify(t *testing.T) { tests := map[string](func() test){ "fail/unexpected-cert-type": func() test { return test{ - so: &SSHOptions{CertType: "foo"}, + so: &SignSSHOptions{CertType: "foo"}, cert: new(ssh.Certificate), err: errors.Errorf("ssh certificate has an unknown type - foo"), } }, "fail/validAfter-greater-validBefore": func() test { return test{ - so: &SSHOptions{CertType: "user"}, + so: &SignSSHOptions{CertType: "user"}, cert: &ssh.Certificate{ValidAfter: uint64(15), ValidBefore: uint64(10)}, err: errors.Errorf("ssh certificate valid after cannot be greater than valid before"), } }, "ok/user-cert": func() test { return test{ - so: &SSHOptions{CertType: "user"}, + so: &SignSSHOptions{CertType: "user"}, cert: new(ssh.Certificate), valid: func(cert *ssh.Certificate) { assert.Equals(t, cert.CertType, uint32(ssh.UserCert)) @@ -71,7 +71,7 @@ func TestSSHOptions_Modify(t *testing.T) { }, "ok/host-cert": func() test { return test{ - so: &SSHOptions{CertType: "host"}, + so: &SignSSHOptions{CertType: "host"}, cert: new(ssh.Certificate), valid: func(cert *ssh.Certificate) { assert.Equals(t, cert.CertType, uint32(ssh.HostCert)) @@ -81,7 +81,7 @@ func TestSSHOptions_Modify(t *testing.T) { "ok": func() test { va := time.Now().Add(5 * time.Minute) vb := time.Now().Add(1 * time.Hour) - so := &SSHOptions{CertType: "host", KeyID: "foo", Principals: []string{"foo", "bar"}, + so := &SignSSHOptions{CertType: "host", KeyID: "foo", Principals: []string{"foo", "bar"}, ValidAfter: NewTimeDuration(va), ValidBefore: NewTimeDuration(vb)} return test{ so: so, @@ -114,43 +114,43 @@ func TestSSHOptions_Modify(t *testing.T) { func TestSSHOptions_Match(t *testing.T) { type test struct { - so SSHOptions - cmp SSHOptions + so SignSSHOptions + cmp SignSSHOptions err error } tests := map[string](func() test){ "fail/cert-type": func() test { return test{ - so: SSHOptions{CertType: "foo"}, - cmp: SSHOptions{CertType: "bar"}, + so: SignSSHOptions{CertType: "foo"}, + cmp: SignSSHOptions{CertType: "bar"}, err: errors.Errorf("ssh certificate type does not match - got bar, want foo"), } }, "fail/pricipals": func() test { return test{ - so: SSHOptions{Principals: []string{"foo"}}, - cmp: SSHOptions{Principals: []string{"bar"}}, + so: SignSSHOptions{Principals: []string{"foo"}}, + cmp: SignSSHOptions{Principals: []string{"bar"}}, err: errors.Errorf("ssh certificate principals does not match - got [bar], want [foo]"), } }, "fail/validAfter": func() test { return test{ - so: SSHOptions{ValidAfter: NewTimeDuration(time.Now().Add(1 * time.Minute))}, - cmp: SSHOptions{ValidAfter: NewTimeDuration(time.Now().Add(5 * time.Minute))}, + so: SignSSHOptions{ValidAfter: NewTimeDuration(time.Now().Add(1 * time.Minute))}, + cmp: SignSSHOptions{ValidAfter: NewTimeDuration(time.Now().Add(5 * time.Minute))}, err: errors.Errorf("ssh certificate valid after does not match"), } }, "fail/validBefore": func() test { return test{ - so: SSHOptions{ValidBefore: NewTimeDuration(time.Now().Add(1 * time.Minute))}, - cmp: SSHOptions{ValidBefore: NewTimeDuration(time.Now().Add(5 * time.Minute))}, + so: SignSSHOptions{ValidBefore: NewTimeDuration(time.Now().Add(1 * time.Minute))}, + cmp: SignSSHOptions{ValidBefore: NewTimeDuration(time.Now().Add(5 * time.Minute))}, err: errors.Errorf("ssh certificate valid before does not match"), } }, "ok/original-empty": func() test { return test{ - so: SSHOptions{}, - cmp: SSHOptions{ + so: SignSSHOptions{}, + cmp: SignSSHOptions{ CertType: "foo", Principals: []string{"foo"}, ValidAfter: NewTimeDuration(time.Now().Add(1 * time.Minute)), @@ -160,8 +160,8 @@ func TestSSHOptions_Match(t *testing.T) { }, "ok/cmp-empty": func() test { return test{ - cmp: SSHOptions{}, - so: SSHOptions{ + cmp: SignSSHOptions{}, + so: SignSSHOptions{ CertType: "foo", Principals: []string{"foo"}, ValidAfter: NewTimeDuration(time.Now().Add(1 * time.Minute)), @@ -174,13 +174,13 @@ func TestSSHOptions_Match(t *testing.T) { va := NewTimeDuration(n.Add(1 * time.Minute)) vb := NewTimeDuration(n.Add(5 * time.Minute)) return test{ - cmp: SSHOptions{ + cmp: SignSSHOptions{ CertType: "foo", Principals: []string{"foo"}, ValidAfter: va, ValidBefore: vb, }, - so: SSHOptions{ + so: SignSSHOptions{ CertType: "foo", Principals: []string{"foo"}, ValidAfter: va, @@ -330,7 +330,7 @@ func Test_sshCertDefaultsModifier_Modify(t *testing.T) { n := time.Now() va := NewTimeDuration(n.Add(1 * time.Minute)) vb := NewTimeDuration(n.Add(5 * time.Minute)) - so := SSHOptions{ + so := SignSSHOptions{ Principals: []string{"foo", "bar"}, CertType: "host", ValidAfter: va, @@ -349,7 +349,7 @@ func Test_sshCertDefaultsModifier_Modify(t *testing.T) { }, "ok/no-changes": func() test { n := time.Now() - so := SSHOptions{ + so := SignSSHOptions{ Principals: []string{"foo", "bar"}, CertType: "host", ValidAfter: NewTimeDuration(n.Add(15 * time.Minute)), @@ -659,7 +659,7 @@ func Test_sshCertDefaultValidator_Valid(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := v.Valid(tt.cert, SSHOptions{}); err != nil { + if err := v.Valid(tt.cert, SignSSHOptions{}); err != nil { if assert.NotNil(t, tt.err) { assert.HasPrefix(t, err.Error(), tt.err.Error()) } @@ -678,31 +678,31 @@ func Test_sshCertValidityValidator(t *testing.T) { tests := []struct { name string cert *ssh.Certificate - opts SSHOptions + opts SignSSHOptions err error }{ { "fail/validAfter-0", &ssh.Certificate{CertType: ssh.UserCert}, - SSHOptions{}, + SignSSHOptions{}, errors.New("ssh certificate validAfter cannot be 0"), }, { "fail/validBefore-in-past", &ssh.Certificate{CertType: ssh.UserCert, ValidAfter: uint64(now().Unix()), ValidBefore: uint64(now().Add(-time.Minute).Unix())}, - SSHOptions{}, + SignSSHOptions{}, errors.New("ssh certificate validBefore cannot be in the past"), }, { "fail/validBefore-before-validAfter", &ssh.Certificate{CertType: ssh.UserCert, ValidAfter: uint64(now().Add(5 * time.Minute).Unix()), ValidBefore: uint64(now().Add(3 * time.Minute).Unix())}, - SSHOptions{}, + SignSSHOptions{}, errors.New("ssh certificate validBefore cannot be before validAfter"), }, { "fail/cert-type-not-set", &ssh.Certificate{ValidAfter: uint64(now().Unix()), ValidBefore: uint64(now().Add(10 * time.Minute).Unix())}, - SSHOptions{}, + SignSSHOptions{}, errors.New("ssh certificate type has not been set"), }, { @@ -712,7 +712,7 @@ func Test_sshCertValidityValidator(t *testing.T) { ValidAfter: uint64(now().Unix()), ValidBefore: uint64(now().Add(10 * time.Minute).Unix()), }, - SSHOptions{}, + SignSSHOptions{}, errors.New("unknown ssh certificate type 3"), }, { @@ -722,7 +722,7 @@ func Test_sshCertValidityValidator(t *testing.T) { ValidAfter: uint64(n.Unix()), ValidBefore: uint64(n.Add(4 * time.Minute).Unix()), }, - SSHOptions{Backdate: time.Second}, + SignSSHOptions{Backdate: time.Second}, errors.New("requested duration of 4m0s is less than minimum accepted duration for selected provisioner of 5m0s"), }, { @@ -732,7 +732,7 @@ func Test_sshCertValidityValidator(t *testing.T) { ValidAfter: uint64(n.Unix()), ValidBefore: uint64(n.Add(5 * time.Minute).Unix()), }, - SSHOptions{Backdate: time.Second}, + SignSSHOptions{Backdate: time.Second}, nil, }, { @@ -742,7 +742,7 @@ func Test_sshCertValidityValidator(t *testing.T) { ValidAfter: uint64(n.Unix()), ValidBefore: uint64(n.Add(48 * time.Hour).Unix()), }, - SSHOptions{Backdate: time.Second}, + SignSSHOptions{Backdate: time.Second}, errors.New("requested duration of 48h0m0s is greater than maximum accepted duration for selected provisioner of 24h0m1s"), }, { @@ -752,7 +752,7 @@ func Test_sshCertValidityValidator(t *testing.T) { ValidAfter: uint64(n.Unix()), ValidBefore: uint64(n.Add(24*time.Hour + time.Second).Unix()), }, - SSHOptions{Backdate: time.Second}, + SignSSHOptions{Backdate: time.Second}, nil, }, { @@ -762,7 +762,7 @@ func Test_sshCertValidityValidator(t *testing.T) { ValidAfter: uint64(now().Unix()), ValidBefore: uint64(now().Add(8 * time.Hour).Unix()), }, - SSHOptions{Backdate: time.Second}, + SignSSHOptions{Backdate: time.Second}, nil, }, } @@ -908,7 +908,7 @@ func Test_sshValidityModifier(t *testing.T) { for name, run := range tests { t.Run(name, func(t *testing.T) { tt := run() - if err := tt.svm.Option(SSHOptions{}).Modify(tt.cert); err != nil { + if err := tt.svm.Option(SignSSHOptions{}).Modify(tt.cert); err != nil { if assert.NotNil(t, tt.err) { assert.HasPrefix(t, err.Error(), tt.err.Error()) } @@ -962,7 +962,7 @@ func Test_sshDefaultDuration_Option(t *testing.T) { Claimer *Claimer } type args struct { - o SSHOptions + o SignSSHOptions cert *ssh.Certificate } tests := []struct { @@ -972,26 +972,26 @@ func Test_sshDefaultDuration_Option(t *testing.T) { want *ssh.Certificate wantErr bool }{ - {"user", fields{newClaimer(nil)}, args{SSHOptions{}, &ssh.Certificate{CertType: ssh.UserCert}}, + {"user", fields{newClaimer(nil)}, args{SignSSHOptions{}, &ssh.Certificate{CertType: ssh.UserCert}}, &ssh.Certificate{CertType: ssh.UserCert, ValidAfter: unix(0), ValidBefore: unix(16 * time.Hour)}, false}, - {"host", fields{newClaimer(nil)}, args{SSHOptions{}, &ssh.Certificate{CertType: ssh.HostCert}}, + {"host", fields{newClaimer(nil)}, args{SignSSHOptions{}, &ssh.Certificate{CertType: ssh.HostCert}}, &ssh.Certificate{CertType: ssh.HostCert, ValidAfter: unix(0), ValidBefore: unix(30 * 24 * time.Hour)}, false}, - {"user claim", fields{newClaimer(&Claims{DefaultUserSSHDur: &Duration{1 * time.Hour}})}, args{SSHOptions{}, &ssh.Certificate{CertType: ssh.UserCert}}, + {"user claim", fields{newClaimer(&Claims{DefaultUserSSHDur: &Duration{1 * time.Hour}})}, args{SignSSHOptions{}, &ssh.Certificate{CertType: ssh.UserCert}}, &ssh.Certificate{CertType: ssh.UserCert, ValidAfter: unix(0), ValidBefore: unix(1 * time.Hour)}, false}, - {"host claim", fields{newClaimer(&Claims{DefaultHostSSHDur: &Duration{1 * time.Hour}})}, args{SSHOptions{}, &ssh.Certificate{CertType: ssh.HostCert}}, + {"host claim", fields{newClaimer(&Claims{DefaultHostSSHDur: &Duration{1 * time.Hour}})}, args{SignSSHOptions{}, &ssh.Certificate{CertType: ssh.HostCert}}, &ssh.Certificate{CertType: ssh.HostCert, ValidAfter: unix(0), ValidBefore: unix(1 * time.Hour)}, false}, - {"user backdate", fields{newClaimer(nil)}, args{SSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.UserCert}}, + {"user backdate", fields{newClaimer(nil)}, args{SignSSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.UserCert}}, &ssh.Certificate{CertType: ssh.UserCert, ValidAfter: unix(-1 * time.Minute), ValidBefore: unix(16 * time.Hour)}, false}, - {"host backdate", fields{newClaimer(nil)}, args{SSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.HostCert}}, + {"host backdate", fields{newClaimer(nil)}, args{SignSSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.HostCert}}, &ssh.Certificate{CertType: ssh.HostCert, ValidAfter: unix(-1 * time.Minute), ValidBefore: unix(30 * 24 * time.Hour)}, false}, - {"user validAfter", fields{newClaimer(nil)}, args{SSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.UserCert, ValidAfter: unix(1 * time.Hour)}}, + {"user validAfter", fields{newClaimer(nil)}, args{SignSSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.UserCert, ValidAfter: unix(1 * time.Hour)}}, &ssh.Certificate{CertType: ssh.UserCert, ValidAfter: unix(time.Hour), ValidBefore: unix(17 * time.Hour)}, false}, - {"user validBefore", fields{newClaimer(nil)}, args{SSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.UserCert, ValidBefore: unix(1 * time.Hour)}}, + {"user validBefore", fields{newClaimer(nil)}, args{SignSSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.UserCert, ValidBefore: unix(1 * time.Hour)}}, &ssh.Certificate{CertType: ssh.UserCert, ValidAfter: unix(-1 * time.Minute), ValidBefore: unix(time.Hour)}, false}, - {"host validAfter validBefore", fields{newClaimer(nil)}, args{SSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.HostCert, ValidAfter: unix(1 * time.Minute), ValidBefore: unix(2 * time.Minute)}}, + {"host validAfter validBefore", fields{newClaimer(nil)}, args{SignSSHOptions{Backdate: 1 * time.Minute}, &ssh.Certificate{CertType: ssh.HostCert, ValidAfter: unix(1 * time.Minute), ValidBefore: unix(2 * time.Minute)}}, &ssh.Certificate{CertType: ssh.HostCert, ValidAfter: unix(1 * time.Minute), ValidBefore: unix(2 * time.Minute)}, false}, - {"fail zero", fields{newClaimer(nil)}, args{SSHOptions{}, &ssh.Certificate{}}, &ssh.Certificate{}, true}, - {"fail type", fields{newClaimer(nil)}, args{SSHOptions{}, &ssh.Certificate{CertType: 3}}, &ssh.Certificate{CertType: 3}, true}, + {"fail zero", fields{newClaimer(nil)}, args{SignSSHOptions{}, &ssh.Certificate{}}, &ssh.Certificate{}, true}, + {"fail type", fields{newClaimer(nil)}, args{SignSSHOptions{}, &ssh.Certificate{CertType: 3}}, &ssh.Certificate{CertType: 3}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -1015,7 +1015,7 @@ func Test_sshLimitDuration_Option(t *testing.T) { NotAfter time.Time } type args struct { - o SSHOptions + o SignSSHOptions } tests := []struct { name string diff --git a/authority/provisioner/ssh_test.go b/authority/provisioner/ssh_test.go index be102a1a..c08ddc3e 100644 --- a/authority/provisioner/ssh_test.go +++ b/authority/provisioner/ssh_test.go @@ -10,7 +10,7 @@ import ( "golang.org/x/crypto/ssh" ) -func validateSSHCertificate(cert *ssh.Certificate, opts *SSHOptions) error { +func validateSSHCertificate(cert *ssh.Certificate, opts *SignSSHOptions) error { switch { case cert == nil: return fmt.Errorf("certificate is nil") @@ -39,7 +39,7 @@ func validateSSHCertificate(cert *ssh.Certificate, opts *SSHOptions) error { } } -func signSSHCertificate(key crypto.PublicKey, opts SSHOptions, signOpts []SignOption, signKey crypto.Signer) (*ssh.Certificate, error) { +func signSSHCertificate(key crypto.PublicKey, opts SignSSHOptions, signOpts []SignOption, signKey crypto.Signer) (*ssh.Certificate, error) { pub, err := ssh.NewPublicKey(key) if err != nil { return nil, err diff --git a/authority/provisioner/utils_test.go b/authority/provisioner/utils_test.go index 418e6a5b..ec02a5dc 100644 --- a/authority/provisioner/utils_test.go +++ b/authority/provisioner/utils_test.go @@ -713,20 +713,20 @@ func generateK8sSAToken(jwk *jose.JSONWebKey, claims *k8sSAPayload, tokOpts ...t } func generateSimpleSSHUserToken(iss, aud string, jwk *jose.JSONWebKey) (string, error) { - return generateSSHToken("subject@localhost", iss, aud, time.Now(), &SSHOptions{ + return generateSSHToken("subject@localhost", iss, aud, time.Now(), &SignSSHOptions{ CertType: "user", Principals: []string{"name"}, }, jwk) } func generateSimpleSSHHostToken(iss, aud string, jwk *jose.JSONWebKey) (string, error) { - return generateSSHToken("subject@localhost", iss, aud, time.Now(), &SSHOptions{ + return generateSSHToken("subject@localhost", iss, aud, time.Now(), &SignSSHOptions{ CertType: "host", Principals: []string{"smallstep.com"}, }, jwk) } -func generateSSHToken(sub, iss, aud string, iat time.Time, sshOpts *SSHOptions, jwk *jose.JSONWebKey) (string, error) { +func generateSSHToken(sub, iss, aud string, iat time.Time, sshOpts *SignSSHOptions, jwk *jose.JSONWebKey) (string, error) { sig, err := jose.NewSigner( jose.SigningKey{Algorithm: jose.ES256, Key: jwk.Key}, new(jose.SignerOptions).WithType("JWT").WithHeader("kid", jwk.KeyID), diff --git a/authority/provisioner/x5c.go b/authority/provisioner/x5c.go index 8ec1ddae..ff01b151 100644 --- a/authority/provisioner/x5c.go +++ b/authority/provisioner/x5c.go @@ -25,11 +25,11 @@ type x5cPayload struct { // signature requests. type X5C struct { *base - Type string `json:"type"` - Name string `json:"name"` - Roots []byte `json:"roots"` - Claims *Claims `json:"claims,omitempty"` - Options *ProvisionerOptions `json:"options,omitempty"` + Type string `json:"type"` + Name string `json:"name"` + Roots []byte `json:"roots"` + Claims *Claims `json:"claims,omitempty"` + Options *Options `json:"options,omitempty"` claimer *Claimer audiences Audiences rootPool *x509.CertPool diff --git a/authority/provisioner/x5c_test.go b/authority/provisioner/x5c_test.go index e4bf5443..73a3ba9f 100644 --- a/authority/provisioner/x5c_test.go +++ b/authority/provisioner/x5c_test.go @@ -696,7 +696,7 @@ func TestX5C_AuthorizeSSHSign(t *testing.T) { Expiry: jose.NewNumericDate(now.Add(5 * time.Minute)), Audience: []string{testAudiences.SSHSign[0]}, }, - Step: &stepPayload{SSH: &SSHOptions{ + Step: &stepPayload{SSH: &SignSSHOptions{ CertType: SSHHostCert, Principals: []string{"max", "mariano", "alan"}, ValidAfter: TimeDuration{d: 5 * time.Minute}, @@ -728,7 +728,7 @@ func TestX5C_AuthorizeSSHSign(t *testing.T) { Expiry: jose.NewNumericDate(now.Add(5 * time.Minute)), Audience: []string{testAudiences.SSHSign[0]}, }, - Step: &stepPayload{SSH: &SSHOptions{}}, + Step: &stepPayload{SSH: &SignSSHOptions{}}, } tok, err := generateX5CSSHToken(x5cJWK, claims, withX5CHdr(x5cCerts)) assert.FatalError(t, err) @@ -759,7 +759,7 @@ func TestX5C_AuthorizeSSHSign(t *testing.T) { case sshCertOptionsValidator: tc.claims.Step.SSH.ValidAfter.t = time.Time{} tc.claims.Step.SSH.ValidBefore.t = time.Time{} - assert.Equals(t, SSHOptions(v), *tc.claims.Step.SSH) + assert.Equals(t, SignSSHOptions(v), *tc.claims.Step.SSH) case sshCertKeyIDModifier: assert.Equals(t, string(v), "foo") case sshCertTypeModifier: @@ -771,7 +771,7 @@ func TestX5C_AuthorizeSSHSign(t *testing.T) { case sshCertValidBeforeModifier: assert.Equals(t, int64(v), tc.claims.Step.SSH.ValidBefore.RelativeTime(nw).Unix()) case sshCertDefaultsModifier: - assert.Equals(t, SSHOptions(v), SSHOptions{CertType: SSHUserCert}) + assert.Equals(t, SignSSHOptions(v), SignSSHOptions{CertType: SSHUserCert}) case *sshLimitDuration: assert.Equals(t, v.Claimer, tc.p.claimer) assert.Equals(t, v.NotAfter, x5cCerts[0].NotAfter) diff --git a/authority/ssh.go b/authority/ssh.go index 70a15649..05b899e6 100644 --- a/authority/ssh.go +++ b/authority/ssh.go @@ -204,7 +204,7 @@ func (a *Authority) GetSSHBastion(ctx context.Context, user string, hostname str } // SignSSH creates a signed SSH certificate with the given public key and options. -func (a *Authority) SignSSH(ctx context.Context, key ssh.PublicKey, opts provisioner.SSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) { +func (a *Authority) SignSSH(ctx context.Context, key ssh.PublicKey, opts provisioner.SignSSHOptions, signOpts ...provisioner.SignOption) (*ssh.Certificate, error) { var mods []provisioner.SSHCertModifier var validators []provisioner.SSHCertValidator @@ -453,7 +453,7 @@ func (a *Authority) RekeySSH(ctx context.Context, oldCert *ssh.Certificate, pub // Apply validators from provisioner. for _, v := range validators { - if err := v.Valid(cert, provisioner.SSHOptions{Backdate: backdate}); err != nil { + if err := v.Valid(cert, provisioner.SignSSHOptions{Backdate: backdate}); err != nil { return nil, errs.Wrap(http.StatusForbidden, err, "rekeySSH") } } diff --git a/authority/ssh_test.go b/authority/ssh_test.go index 2756f099..8e64b108 100644 --- a/authority/ssh_test.go +++ b/authority/ssh_test.go @@ -62,7 +62,7 @@ func (m sshTestCertModifier) Modify(cert *ssh.Certificate) error { type sshTestCertValidator string -func (v sshTestCertValidator) Valid(crt *ssh.Certificate, opts provisioner.SSHOptions) error { +func (v sshTestCertValidator) Valid(crt *ssh.Certificate, opts provisioner.SignSSHOptions) error { if v == "" { return nil } @@ -71,7 +71,7 @@ func (v sshTestCertValidator) Valid(crt *ssh.Certificate, opts provisioner.SSHOp type sshTestOptionsValidator string -func (v sshTestOptionsValidator) Valid(opts provisioner.SSHOptions) error { +func (v sshTestOptionsValidator) Valid(opts provisioner.SignSSHOptions) error { if v == "" { return nil } @@ -80,7 +80,7 @@ func (v sshTestOptionsValidator) Valid(opts provisioner.SSHOptions) error { type sshTestOptionsModifier string -func (m sshTestOptionsModifier) Option(opts provisioner.SSHOptions) provisioner.SSHCertModifier { +func (m sshTestOptionsModifier) Option(opts provisioner.SignSSHOptions) provisioner.SSHCertModifier { return sshTestCertModifier(string(m)) } @@ -109,7 +109,7 @@ func TestAuthority_SignSSH(t *testing.T) { } type args struct { key ssh.PublicKey - opts provisioner.SSHOptions + opts provisioner.SignSSHOptions signOpts []provisioner.SignOption } type want struct { @@ -125,27 +125,27 @@ func TestAuthority_SignSSH(t *testing.T) { want want wantErr bool }{ - {"ok-user", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions}}, want{CertType: ssh.UserCert}, false}, - {"ok-host", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{hostOptions}}, want{CertType: ssh.HostCert}, false}, - {"ok-opts-type-user", fields{signer, signer}, args{pub, provisioner.SSHOptions{CertType: "user"}, []provisioner.SignOption{}}, want{CertType: ssh.UserCert}, false}, - {"ok-opts-type-host", fields{signer, signer}, args{pub, provisioner.SSHOptions{CertType: "host"}, []provisioner.SignOption{}}, want{CertType: ssh.HostCert}, false}, - {"ok-opts-principals", fields{signer, signer}, args{pub, provisioner.SSHOptions{CertType: "user", Principals: []string{"user"}}, []provisioner.SignOption{}}, want{CertType: ssh.UserCert, Principals: []string{"user"}}, false}, - {"ok-opts-principals", fields{signer, signer}, args{pub, provisioner.SSHOptions{CertType: "host", Principals: []string{"foo.test.com", "bar.test.com"}}, []provisioner.SignOption{}}, want{CertType: ssh.HostCert, Principals: []string{"foo.test.com", "bar.test.com"}}, false}, - {"ok-opts-valid-after", fields{signer, signer}, args{pub, provisioner.SSHOptions{CertType: "user", ValidAfter: provisioner.NewTimeDuration(now)}, []provisioner.SignOption{}}, want{CertType: ssh.UserCert, ValidAfter: uint64(now.Unix())}, false}, - {"ok-opts-valid-before", fields{signer, signer}, args{pub, provisioner.SSHOptions{CertType: "host", ValidBefore: provisioner.NewTimeDuration(now)}, []provisioner.SignOption{}}, want{CertType: ssh.HostCert, ValidBefore: uint64(now.Unix())}, false}, - {"ok-cert-validator", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions, sshTestCertValidator("")}}, want{CertType: ssh.UserCert}, false}, - {"ok-cert-modifier", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions, sshTestCertModifier("")}}, want{CertType: ssh.UserCert}, false}, - {"ok-opts-validator", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions, sshTestOptionsValidator("")}}, want{CertType: ssh.UserCert}, false}, - {"ok-opts-modifier", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions, sshTestOptionsModifier("")}}, want{CertType: ssh.UserCert}, false}, - {"fail-opts-type", fields{signer, signer}, args{pub, provisioner.SSHOptions{CertType: "foo"}, []provisioner.SignOption{}}, want{}, true}, - {"fail-cert-validator", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions, sshTestCertValidator("an error")}}, want{}, true}, - {"fail-cert-modifier", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions, sshTestCertModifier("an error")}}, want{}, true}, - {"fail-opts-validator", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions, sshTestOptionsValidator("an error")}}, want{}, true}, - {"fail-opts-modifier", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions, sshTestOptionsModifier("an error")}}, want{}, true}, - {"fail-bad-sign-options", fields{signer, signer}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{userOptions, "wrong type"}}, want{}, true}, - {"fail-no-user-key", fields{nil, signer}, args{pub, provisioner.SSHOptions{CertType: "user"}, []provisioner.SignOption{}}, want{}, true}, - {"fail-no-host-key", fields{signer, nil}, args{pub, provisioner.SSHOptions{CertType: "host"}, []provisioner.SignOption{}}, want{}, true}, - {"fail-bad-type", fields{signer, nil}, args{pub, provisioner.SSHOptions{}, []provisioner.SignOption{sshTestModifier{CertType: 0}}}, want{}, true}, + {"ok-user", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions}}, want{CertType: ssh.UserCert}, false}, + {"ok-host", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{hostOptions}}, want{CertType: ssh.HostCert}, false}, + {"ok-opts-type-user", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{CertType: "user"}, []provisioner.SignOption{}}, want{CertType: ssh.UserCert}, false}, + {"ok-opts-type-host", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{CertType: "host"}, []provisioner.SignOption{}}, want{CertType: ssh.HostCert}, false}, + {"ok-opts-principals", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{CertType: "user", Principals: []string{"user"}}, []provisioner.SignOption{}}, want{CertType: ssh.UserCert, Principals: []string{"user"}}, false}, + {"ok-opts-principals", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{CertType: "host", Principals: []string{"foo.test.com", "bar.test.com"}}, []provisioner.SignOption{}}, want{CertType: ssh.HostCert, Principals: []string{"foo.test.com", "bar.test.com"}}, false}, + {"ok-opts-valid-after", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{CertType: "user", ValidAfter: provisioner.NewTimeDuration(now)}, []provisioner.SignOption{}}, want{CertType: ssh.UserCert, ValidAfter: uint64(now.Unix())}, false}, + {"ok-opts-valid-before", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{CertType: "host", ValidBefore: provisioner.NewTimeDuration(now)}, []provisioner.SignOption{}}, want{CertType: ssh.HostCert, ValidBefore: uint64(now.Unix())}, false}, + {"ok-cert-validator", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestCertValidator("")}}, want{CertType: ssh.UserCert}, false}, + {"ok-cert-modifier", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestCertModifier("")}}, want{CertType: ssh.UserCert}, false}, + {"ok-opts-validator", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestOptionsValidator("")}}, want{CertType: ssh.UserCert}, false}, + {"ok-opts-modifier", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestOptionsModifier("")}}, want{CertType: ssh.UserCert}, false}, + {"fail-opts-type", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{CertType: "foo"}, []provisioner.SignOption{}}, want{}, true}, + {"fail-cert-validator", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestCertValidator("an error")}}, want{}, true}, + {"fail-cert-modifier", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestCertModifier("an error")}}, want{}, true}, + {"fail-opts-validator", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestOptionsValidator("an error")}}, want{}, true}, + {"fail-opts-modifier", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions, sshTestOptionsModifier("an error")}}, want{}, true}, + {"fail-bad-sign-options", fields{signer, signer}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{userOptions, "wrong type"}}, want{}, true}, + {"fail-no-user-key", fields{nil, signer}, args{pub, provisioner.SignSSHOptions{CertType: "user"}, []provisioner.SignOption{}}, want{}, true}, + {"fail-no-host-key", fields{signer, nil}, args{pub, provisioner.SignSSHOptions{CertType: "host"}, []provisioner.SignOption{}}, want{}, true}, + {"fail-bad-type", fields{signer, nil}, args{pub, provisioner.SignSSHOptions{}, []provisioner.SignOption{sshTestModifier{CertType: 0}}}, want{}, true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/authority/tls.go b/authority/tls.go index cd0593dc..5c88b37e 100644 --- a/authority/tls.go +++ b/authority/tls.go @@ -32,7 +32,7 @@ var oidAuthorityKeyIdentifier = asn1.ObjectIdentifier{2, 5, 29, 35} var oidSubjectKeyIdentifier = asn1.ObjectIdentifier{2, 5, 29, 14} func withDefaultASN1DN(def *x509legacy.ASN1DN) provisioner.CertificateModifierFunc { - return func(crt *x509.Certificate, opts provisioner.Options) error { + return func(crt *x509.Certificate, opts provisioner.SignOptions) error { if def == nil { return errors.New("default ASN1DN template cannot be nil") } @@ -61,7 +61,7 @@ func withDefaultASN1DN(def *x509legacy.ASN1DN) provisioner.CertificateModifierFu } // Sign creates a signed certificate from a certificate signing request. -func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Options, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) { +func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.SignOptions, extraOpts ...provisioner.SignOption) ([]*x509.Certificate, error) { var ( certOptions []x509util.Option certValidators []provisioner.CertificateValidator diff --git a/authority/tls_test.go b/authority/tls_test.go index 46d2250a..01da4926 100644 --- a/authority/tls_test.go +++ b/authority/tls_test.go @@ -132,7 +132,7 @@ func TestAuthority_Sign(t *testing.T) { } nb := time.Now() - signOpts := provisioner.Options{ + signOpts := provisioner.SignOptions{ NotBefore: provisioner.NewTimeDuration(nb), NotAfter: provisioner.NewTimeDuration(nb.Add(time.Minute * 5)), } @@ -150,7 +150,7 @@ func TestAuthority_Sign(t *testing.T) { type signTest struct { auth *Authority csr *x509.CertificateRequest - signOpts provisioner.Options + signOpts provisioner.SignOptions extraOpts []provisioner.SignOption notBefore time.Time notAfter time.Time @@ -210,7 +210,7 @@ func TestAuthority_Sign(t *testing.T) { }, "fail provisioner duration claim": func(t *testing.T) *signTest { csr := getCSR(t, priv) - _signOpts := provisioner.Options{ + _signOpts := provisioner.SignOptions{ NotBefore: provisioner.NewTimeDuration(nb), NotAfter: provisioner.NewTimeDuration(nb.Add(time.Hour * 25)), } @@ -429,14 +429,14 @@ func TestAuthority_Renew(t *testing.T) { certModToWithOptions := func(m provisioner.CertificateModifierFunc) x509util.WithOption { return func(p x509util.Profile) error { crt := p.Subject() - return m.Modify(crt, provisioner.Options{}) + return m.Modify(crt, provisioner.SignOptions{}) } } now := time.Now().UTC() nb1 := now.Add(-time.Minute * 7) na1 := now - so := &provisioner.Options{ + so := &provisioner.SignOptions{ NotBefore: provisioner.NewTimeDuration(nb1), NotAfter: provisioner.NewTimeDuration(na1), } @@ -656,14 +656,14 @@ func TestAuthority_Rekey(t *testing.T) { certModToWithOptions := func(m provisioner.CertificateModifierFunc) x509util.WithOption { return func(p x509util.Profile) error { crt := p.Subject() - return m.Modify(crt, provisioner.Options{}) + return m.Modify(crt, provisioner.SignOptions{}) } } now := time.Now().UTC() nb1 := now.Add(-time.Minute * 7) na1 := now - so := &provisioner.Options{ + so := &provisioner.SignOptions{ NotBefore: provisioner.NewTimeDuration(nb1), NotAfter: provisioner.NewTimeDuration(na1), } diff --git a/ca/provisioner.go b/ca/provisioner.go index 1b7067e0..d5dfd648 100644 --- a/ca/provisioner.go +++ b/ca/provisioner.go @@ -133,7 +133,7 @@ func (p *Provisioner) SSHToken(certType, keyID string, principals []string) (str token.WithIssuer(p.name), token.WithAudience(p.sshAudience), token.WithValidity(notBefore, notAfter), - token.WithSSH(provisioner.SSHOptions{ + token.WithSSH(provisioner.SignSSHOptions{ CertType: certType, Principals: principals, KeyID: keyID,