From 10f6a901ec98f0eb7ba101f772cc96f2694abb25 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Tue, 12 Mar 2024 14:29:55 -0700 Subject: [PATCH] Let the CA determine the RA lifetime When the RA mode with StepCAS is used, let the CA decide which lifetime the RA should get instead of requiring always 24h. This commit also fixes linter warnings. Related to #1094 --- acme/api/middleware.go | 8 ++-- api/api.go | 2 +- api/revoke.go | 2 +- authority/admin/api/provisioner.go | 4 +- authority/admin/db/nosql/admin_test.go | 4 +- authority/admin/db/nosql/provisioner_test.go | 8 ++-- authority/internal/constraints/verify.go | 4 +- authority/provisioner/collection.go | 2 +- authority/provisioner/jwk.go | 2 +- authority/provisioner/keystore.go | 2 +- authority/provisioner/scep.go | 2 +- authority/provisioner/x5c_test.go | 2 +- authority/provisioners.go | 6 +-- authority/root.go | 2 +- authority/tls.go | 10 ++++- ca/adminClient.go | 2 +- ca/ca.go | 2 +- ca/tls.go | 2 +- cas/apiv1/services.go | 8 ++++ cas/apiv1/services_test.go | 39 ++++++++++++++++++++ cas/cloudcas/cloudcas.go | 5 +++ cas/cloudcas/cloudcas_test.go | 17 +++++++++ cas/softcas/softcas.go | 5 +++ cas/softcas/softcas_test.go | 17 +++++++++ cas/stepcas/stepcas.go | 9 ++++- cas/stepcas/stepcas_test.go | 17 +++++++++ cas/vaultcas/vaultcas.go | 5 +++ cas/vaultcas/vaultcas_test.go | 17 +++++++++ commands/app.go | 2 +- db/db.go | 2 +- errs/error.go | 4 +- policy/validate.go | 4 +- 32 files changed, 179 insertions(+), 38 deletions(-) diff --git a/acme/api/middleware.go b/acme/api/middleware.go index c3e1458e..afccca70 100644 --- a/acme/api/middleware.go +++ b/acme/api/middleware.go @@ -147,10 +147,10 @@ func validateJWS(next nextHTTP) nextHTTP { sig := jws.Signatures[0] uh := sig.Unprotected - if len(uh.KeyID) > 0 || + if uh.KeyID != "" || uh.JSONWebKey != nil || - len(uh.Algorithm) > 0 || - len(uh.Nonce) > 0 || + uh.Algorithm != "" || + uh.Nonce != "" || len(uh.ExtraHeaders) > 0 { render.Error(w, acme.NewError(acme.ErrorMalformedType, "unprotected header must not be used")) return @@ -199,7 +199,7 @@ func validateJWS(next nextHTTP) nextHTTP { return } - if hdr.JSONWebKey != nil && len(hdr.KeyID) > 0 { + if hdr.JSONWebKey != nil && hdr.KeyID != "" { render.Error(w, acme.NewError(acme.ErrorMalformedType, "jwk and kid are mutually exclusive")) return } diff --git a/api/api.go b/api/api.go index a12e7e19..6916983b 100644 --- a/api/api.go +++ b/api/api.go @@ -565,7 +565,7 @@ func LogSSHCertificate(w http.ResponseWriter, cert *ssh.Certificate) { func ParseCursor(r *http.Request) (cursor string, limit int, err error) { q := r.URL.Query() cursor = q.Get("cursor") - if v := q.Get("limit"); len(v) > 0 { + if v := q.Get("limit"); v != "" { limit, err = strconv.Atoi(v) if err != nil { return "", 0, errs.BadRequestErr(err, "limit '%s' is not an integer", v) diff --git a/api/revoke.go b/api/revoke.go index 4221696a..dc639d58 100644 --- a/api/revoke.go +++ b/api/revoke.go @@ -78,7 +78,7 @@ func Revoke(w http.ResponseWriter, r *http.Request) { // A token indicates that we are using the api via a provisioner token, // otherwise it is assumed that the certificate is revoking itself over mTLS. - if len(body.OTT) > 0 { + if body.OTT != "" { logOtt(w, body.OTT) if _, err := a.Authorize(ctx, body.OTT); err != nil { render.Error(w, errs.UnauthorizedErr(err)) diff --git a/authority/admin/api/provisioner.go b/authority/admin/api/provisioner.go index d44e9e03..709399dd 100644 --- a/authority/admin/api/provisioner.go +++ b/authority/admin/api/provisioner.go @@ -38,7 +38,7 @@ func GetProvisioner(w http.ResponseWriter, r *http.Request) { auth := mustAuthority(ctx) db := admin.MustFromContext(ctx) - if len(id) > 0 { + if id != "" { if p, err = auth.LoadProvisionerByID(id); err != nil { render.Error(w, admin.WrapErrorISE(err, "error loading provisioner %s", id)) return @@ -116,7 +116,7 @@ func DeleteProvisioner(w http.ResponseWriter, r *http.Request) { name := chi.URLParam(r, "name") auth := mustAuthority(r.Context()) - if len(id) > 0 { + if id != "" { if p, err = auth.LoadProvisionerByID(id); err != nil { render.Error(w, admin.WrapErrorISE(err, "error loading provisioner %s", id)) return diff --git a/authority/admin/db/nosql/admin_test.go b/authority/admin/db/nosql/admin_test.go index 9961d7f5..a50fe58b 100644 --- a/authority/admin/db/nosql/admin_test.go +++ b/authority/admin/db/nosql/admin_test.go @@ -857,7 +857,7 @@ func TestDB_CreateAdmin(t *testing.T) { var _dba = new(dbAdmin) assert.FatalError(t, json.Unmarshal(nu, _dba)) - assert.True(t, len(_dba.ID) > 0 && _dba.ID == string(key)) + assert.True(t, _dba.ID != "" && _dba.ID == string(key)) assert.Equals(t, _dba.AuthorityID, adm.AuthorityId) assert.Equals(t, _dba.ProvisionerID, adm.ProvisionerId) assert.Equals(t, _dba.Subject, adm.Subject) @@ -890,7 +890,7 @@ func TestDB_CreateAdmin(t *testing.T) { var _dba = new(dbAdmin) assert.FatalError(t, json.Unmarshal(nu, _dba)) - assert.True(t, len(_dba.ID) > 0 && _dba.ID == string(key)) + assert.True(t, _dba.ID != "" && _dba.ID == string(key)) assert.Equals(t, _dba.AuthorityID, adm.AuthorityId) assert.Equals(t, _dba.ProvisionerID, adm.ProvisionerId) assert.Equals(t, _dba.Subject, adm.Subject) diff --git a/authority/admin/db/nosql/provisioner_test.go b/authority/admin/db/nosql/provisioner_test.go index 8aa58d49..73e0368d 100644 --- a/authority/admin/db/nosql/provisioner_test.go +++ b/authority/admin/db/nosql/provisioner_test.go @@ -906,7 +906,7 @@ func TestDB_CreateProvisioner(t *testing.T) { var _dbp = new(dbProvisioner) assert.FatalError(t, json.Unmarshal(nu, _dbp)) - assert.True(t, len(_dbp.ID) > 0 && _dbp.ID == string(key)) + assert.True(t, _dbp.ID != "" && _dbp.ID == string(key)) assert.Equals(t, _dbp.AuthorityID, prov.AuthorityId) assert.Equals(t, _dbp.Type, prov.Type) assert.Equals(t, _dbp.Name, prov.Name) @@ -944,7 +944,7 @@ func TestDB_CreateProvisioner(t *testing.T) { var _dbp = new(dbProvisioner) assert.FatalError(t, json.Unmarshal(nu, _dbp)) - assert.True(t, len(_dbp.ID) > 0 && _dbp.ID == string(key)) + assert.True(t, _dbp.ID != "" && _dbp.ID == string(key)) assert.Equals(t, _dbp.AuthorityID, prov.AuthorityId) assert.Equals(t, _dbp.Type, prov.Type) assert.Equals(t, _dbp.Name, prov.Name) @@ -1093,7 +1093,7 @@ func TestDB_UpdateProvisioner(t *testing.T) { var _dbp = new(dbProvisioner) assert.FatalError(t, json.Unmarshal(nu, _dbp)) - assert.True(t, len(_dbp.ID) > 0 && _dbp.ID == string(key)) + assert.True(t, _dbp.ID != "" && _dbp.ID == string(key)) assert.Equals(t, _dbp.AuthorityID, prov.AuthorityId) assert.Equals(t, _dbp.Type, prov.Type) assert.Equals(t, _dbp.Name, prov.Name) @@ -1188,7 +1188,7 @@ func TestDB_UpdateProvisioner(t *testing.T) { var _dbp = new(dbProvisioner) assert.FatalError(t, json.Unmarshal(nu, _dbp)) - assert.True(t, len(_dbp.ID) > 0 && _dbp.ID == string(key)) + assert.True(t, _dbp.ID != "" && _dbp.ID == string(key)) assert.Equals(t, _dbp.AuthorityID, prov.AuthorityId) assert.Equals(t, _dbp.Type, prov.Type) assert.Equals(t, _dbp.Name, prov.Name) diff --git a/authority/internal/constraints/verify.go b/authority/internal/constraints/verify.go index 5d070f1e..eae5c8a5 100644 --- a/authority/internal/constraints/verify.go +++ b/authority/internal/constraints/verify.go @@ -203,7 +203,7 @@ func matchURIConstraint(uri *url.URL, constraint string) (bool, error) { // domainToReverseLabels converts a textual domain name like foo.example.com to // the list of labels in reverse order, e.g. ["com", "example", "foo"]. func domainToReverseLabels(domain string) (reverseLabels []string, ok bool) { - for len(domain) > 0 { + for domain != "" { if i := strings.LastIndexByte(domain, '.'); i == -1 { reverseLabels = append(reverseLabels, domain) domain = "" @@ -316,7 +316,7 @@ func parseRFC2821Mailbox(in string) (mailbox rfc2821Mailbox, ok bool) { } else { // Atom ("." Atom)* NextChar: - for len(in) > 0 { + for in != "" { // atext from RFC 2822, Section 3.2.4 c := in[0] diff --git a/authority/provisioner/collection.go b/authority/provisioner/collection.go index c483a50d..fbb730db 100644 --- a/authority/provisioner/collection.go +++ b/authority/provisioner/collection.go @@ -125,7 +125,7 @@ func (c *Collection) LoadByToken(token *jose.JSONWebToken, claims *jose.Claims) } // Try with azp (OIDC) - if len(payload.AuthorizedParty) > 0 { + if payload.AuthorizedParty != "" { if p, ok := c.LoadByTokenID(payload.AuthorizedParty); ok { return p, ok } diff --git a/authority/provisioner/jwk.go b/authority/provisioner/jwk.go index 3a7512b8..13e8bd48 100644 --- a/authority/provisioner/jwk.go +++ b/authority/provisioner/jwk.go @@ -87,7 +87,7 @@ func (p *JWK) GetType() Type { // GetEncryptedKey returns the base provisioner encrypted key if it's defined. func (p *JWK) GetEncryptedKey() (string, string, bool) { - return p.Key.KeyID, p.EncryptedKey, len(p.EncryptedKey) > 0 + return p.Key.KeyID, p.EncryptedKey, p.EncryptedKey != "" } // Init initializes and validates the fields of a JWK type. diff --git a/authority/provisioner/keystore.go b/authority/provisioner/keystore.go index e74a6b8a..aeaad6a0 100644 --- a/authority/provisioner/keystore.go +++ b/authority/provisioner/keystore.go @@ -105,7 +105,7 @@ func getKeysFromJWKsURI(uri string) (jose.JSONWebKeySet, time.Duration, error) { func getCacheAge(cacheControl string) time.Duration { age := defaultCacheAge - if len(cacheControl) > 0 { + if cacheControl != "" { match := maxAgeRegex.FindAllStringSubmatch(cacheControl, -1) if len(match) > 0 { if len(match[0]) == 2 { diff --git a/authority/provisioner/scep.go b/authority/provisioner/scep.go index a48d11cc..f4067bc5 100644 --- a/authority/provisioner/scep.go +++ b/authority/provisioner/scep.go @@ -304,7 +304,7 @@ func (s *SCEP) Init(config Config) (err error) { } } - if decryptionKeyURI := s.DecrypterKeyURI; len(decryptionKeyURI) > 0 { + if decryptionKeyURI := s.DecrypterKeyURI; decryptionKeyURI != "" { u, err := uri.Parse(s.DecrypterKeyURI) if err != nil { return fmt.Errorf("failed parsing decrypter key: %w", err) diff --git a/authority/provisioner/x5c_test.go b/authority/provisioner/x5c_test.go index 22545446..0493d64a 100644 --- a/authority/provisioner/x5c_test.go +++ b/authority/provisioner/x5c_test.go @@ -813,7 +813,7 @@ func TestX5C_AuthorizeSSHSign(t *testing.T) { } tot++ } - if len(tc.claims.Step.SSH.CertType) > 0 { + if tc.claims.Step.SSH.CertType != "" { assert.Equals(t, tot, 12) } else { assert.Equals(t, tot, 10) diff --git a/authority/provisioners.go b/authority/provisioners.go index 551411de..34cc75ed 100644 --- a/authority/provisioners.go +++ b/authority/provisioners.go @@ -608,19 +608,19 @@ func provisionerWebhookToLinkedca(pwh *provisioner.Webhook) *linkedca.Webhook { } func durationsToCertificates(d *linkedca.Durations) (min, max, def *provisioner.Duration, err error) { - if len(d.Min) > 0 { + if d.Min != "" { min, err = provisioner.NewDuration(d.Min) if err != nil { return nil, nil, nil, admin.WrapErrorISE(err, "error parsing minimum duration '%s'", d.Min) } } - if len(d.Max) > 0 { + if d.Max != "" { max, err = provisioner.NewDuration(d.Max) if err != nil { return nil, nil, nil, admin.WrapErrorISE(err, "error parsing maximum duration '%s'", d.Max) } } - if len(d.Default) > 0 { + if d.Default != "" { def, err = provisioner.NewDuration(d.Default) if err != nil { return nil, nil, nil, admin.WrapErrorISE(err, "error parsing default duration '%s'", d.Default) diff --git a/authority/root.go b/authority/root.go index f391997f..37038cfa 100644 --- a/authority/root.go +++ b/authority/root.go @@ -45,7 +45,7 @@ func (a *Authority) GetRoots() ([]*x509.Certificate, error) { // GetFederation returns all the root certificates in the federation. // This method implements the Authority interface. func (a *Authority) GetFederation() (federation []*x509.Certificate, err error) { - a.certificates.Range(func(k, v interface{}) bool { + a.certificates.Range(func(_, v interface{}) bool { crt, ok := v.(*x509.Certificate) if !ok { federation = nil diff --git a/authority/tls.go b/authority/tls.go index 1f3f5130..049febba 100644 --- a/authority/tls.go +++ b/authority/tls.go @@ -59,7 +59,7 @@ var ( ) func withDefaultASN1DN(def *config.ASN1DN) provisioner.CertificateModifierFunc { - return func(crt *x509.Certificate, opts provisioner.SignOptions) error { + return func(crt *x509.Certificate, _ provisioner.SignOptions) error { if def == nil { return errors.New("default ASN1DN template cannot be nil") } @@ -913,10 +913,16 @@ func (a *Authority) GetTLSCertificate() (*tls.Certificate, error) { return fatal(err) } + // For StepCAS RA let the lifetime to the provisioner used by the CA. + var lifetime time.Duration + if casapi.TypeOf(a.x509CAService) != casapi.StepCAS { + lifetime = 24 * time.Hour + } + resp, err := a.x509CAService.CreateCertificate(&casapi.CreateCertificateRequest{ Template: certTpl, CSR: cr, - Lifetime: 24 * time.Hour, + Lifetime: lifetime, Backdate: 1 * time.Minute, IsCAServerCert: true, }) diff --git a/ca/adminClient.go b/ca/adminClient.go index 18221146..3ead6629 100644 --- a/ca/adminClient.go +++ b/ca/adminClient.go @@ -204,7 +204,7 @@ func (o *adminOptions) apply(opts []AdminOption) (err error) { func (o *adminOptions) rawQuery() string { v := url.Values{} - if len(o.cursor) > 0 { + if o.cursor != "" { v.Set("cursor", o.cursor) } if o.limit > 0 { diff --git a/ca/ca.go b/ca/ca.go index 8f60dc2c..0b426ded 100644 --- a/ca/ca.go +++ b/ca/ca.go @@ -678,7 +678,7 @@ func (ca *CA) shouldServeSCEPEndpoints() bool { //nolint:unused // useful for debugging func dumpRoutes(mux chi.Routes) { // helpful routine for logging all routes - walkFunc := func(method string, route string, handler http.Handler, middlewares ...func(http.Handler) http.Handler) error { + walkFunc := func(method string, route string, _ http.Handler, _ ...func(http.Handler) http.Handler) error { fmt.Printf("%s %s\n", method, route) return nil } diff --git a/ca/tls.go b/ca/tls.go index d5d479f3..d7bed58a 100644 --- a/ca/tls.go +++ b/ca/tls.go @@ -69,7 +69,7 @@ func init() { GetClientCertificate: id.GetClientCertificateFunc(), }, } - return func(ctx context.Context, network, address string) (net.Conn, error) { + return func(ctx context.Context, _, _ string) (net.Conn, error) { return d.DialContext(ctx, "tcp", net.JoinHostPort(host, port)) } } diff --git a/cas/apiv1/services.go b/cas/apiv1/services.go index fdd35f16..00ecc2a8 100644 --- a/cas/apiv1/services.go +++ b/cas/apiv1/services.go @@ -67,6 +67,14 @@ func (t Type) String() string { return strings.ToLower(string(t)) } +// TypeOf returns the type of the given CertificateAuthorityService. +func TypeOf(c CertificateAuthorityService) Type { + if ct, ok := c.(interface{ Type() Type }); ok { + return ct.Type() + } + return ExternalCAS +} + // NotImplementedError is the type of error returned if an operation is not implemented. type NotImplementedError struct { Message string diff --git a/cas/apiv1/services_test.go b/cas/apiv1/services_test.go index b4f1def7..2080f843 100644 --- a/cas/apiv1/services_test.go +++ b/cas/apiv1/services_test.go @@ -4,6 +4,24 @@ import ( "testing" ) +type simpleCAS struct{} + +func (*simpleCAS) CreateCertificate(req *CreateCertificateRequest) (*CreateCertificateResponse, error) { + return nil, NotImplementedError{} +} +func (*simpleCAS) RenewCertificate(req *RenewCertificateRequest) (*RenewCertificateResponse, error) { + return nil, NotImplementedError{} +} +func (*simpleCAS) RevokeCertificate(req *RevokeCertificateRequest) (*RevokeCertificateResponse, error) { + return nil, NotImplementedError{} +} + +type fakeCAS struct { + simpleCAS +} + +func (*fakeCAS) Type() Type { return SoftCAS } + func TestType_String(t *testing.T) { tests := []struct { name string @@ -25,6 +43,27 @@ func TestType_String(t *testing.T) { } } +func TestTypeOf(t *testing.T) { + type args struct { + c CertificateAuthorityService + } + tests := []struct { + name string + args args + want Type + }{ + {"ok", args{&simpleCAS{}}, ExternalCAS}, + {"ok with type", args{&fakeCAS{}}, SoftCAS}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := TypeOf(tt.args.c); got != tt.want { + t.Errorf("TypeOf() = %v, want %v", got, tt.want) + } + }) + } +} + func TestNotImplementedError_Error(t *testing.T) { type fields struct { Message string diff --git a/cas/cloudcas/cloudcas.go b/cas/cloudcas/cloudcas.go index c9c8364f..398f7fed 100644 --- a/cas/cloudcas/cloudcas.go +++ b/cas/cloudcas/cloudcas.go @@ -154,6 +154,11 @@ func New(ctx context.Context, opts apiv1.Options) (*CloudCAS, error) { }, nil } +// Type returns the type of this CertificateAuthorityService. +func (c *CloudCAS) Type() apiv1.Type { + return apiv1.CloudCAS +} + // GetCertificateAuthority returns the root certificate for the given // certificate authority. It implements apiv1.CertificateAuthorityGetter // interface. diff --git a/cas/cloudcas/cloudcas_test.go b/cas/cloudcas/cloudcas_test.go index 95446ee6..6e5d2133 100644 --- a/cas/cloudcas/cloudcas_test.go +++ b/cas/cloudcas/cloudcas_test.go @@ -443,6 +443,23 @@ func TestNew_real(t *testing.T) { } } +func TestCloudCAS_Type(t *testing.T) { + tests := []struct { + name string + want apiv1.Type + }{ + {"ok", apiv1.CloudCAS}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &CloudCAS{} + if got := c.Type(); got != tt.want { + t.Errorf("CloudCAS.Type() = %v, want %v", got, tt.want) + } + }) + } +} + func TestCloudCAS_GetCertificateAuthority(t *testing.T) { root := mustParseCertificate(t, testRootCertificate) type fields struct { diff --git a/cas/softcas/softcas.go b/cas/softcas/softcas.go index 58be8aab..dd961975 100644 --- a/cas/softcas/softcas.go +++ b/cas/softcas/softcas.go @@ -53,6 +53,11 @@ func New(_ context.Context, opts apiv1.Options) (*SoftCAS, error) { }, nil } +// Type returns the type of this CertificateAuthorityService. +func (c *SoftCAS) Type() apiv1.Type { + return apiv1.SoftCAS +} + // CreateCertificate signs a new certificate using Golang or KMS crypto. func (c *SoftCAS) CreateCertificate(req *apiv1.CreateCertificateRequest) (*apiv1.CreateCertificateResponse, error) { switch { diff --git a/cas/softcas/softcas_test.go b/cas/softcas/softcas_test.go index 11bf217a..8c04de3a 100644 --- a/cas/softcas/softcas_test.go +++ b/cas/softcas/softcas_test.go @@ -252,6 +252,23 @@ func TestNew_register(t *testing.T) { } } +func TestSoftCAS_Type(t *testing.T) { + tests := []struct { + name string + want apiv1.Type + }{ + {"ok", apiv1.SoftCAS}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &SoftCAS{} + if got := c.Type(); got != tt.want { + t.Errorf("SoftCAS.Type() = %v, want %v", got, tt.want) + } + }) + } +} + func TestSoftCAS_CreateCertificate(t *testing.T) { mockNow(t) // Set rand.Reader to EOF diff --git a/cas/stepcas/stepcas.go b/cas/stepcas/stepcas.go index 51c5f687..cac0d8ed 100644 --- a/cas/stepcas/stepcas.go +++ b/cas/stepcas/stepcas.go @@ -65,6 +65,11 @@ func New(ctx context.Context, opts apiv1.Options) (*StepCAS, error) { }, nil } +// Type returns the type of this CertificateAuthorityService. +func (s *StepCAS) Type() apiv1.Type { + return apiv1.StepCAS +} + // CreateCertificate uses the step-ca sign request with the configured // provisioner to get a new certificate from the certificate authority. func (s *StepCAS) CreateCertificate(req *apiv1.CreateCertificateRequest) (*apiv1.CreateCertificateResponse, error) { @@ -73,8 +78,8 @@ func (s *StepCAS) CreateCertificate(req *apiv1.CreateCertificateRequest) (*apiv1 return nil, errors.New("createCertificateRequest `csr` cannot be nil") case req.Template == nil: return nil, errors.New("createCertificateRequest `template` cannot be nil") - case req.Lifetime == 0: - return nil, errors.New("createCertificateRequest `lifetime` cannot be 0") + case req.Lifetime < 0: + return nil, errors.New("createCertificateRequest `lifetime` cannot less than 0") } info := &raInfo{ diff --git a/cas/stepcas/stepcas_test.go b/cas/stepcas/stepcas_test.go index f7746da0..d2846fb0 100644 --- a/cas/stepcas/stepcas_test.go +++ b/cas/stepcas/stepcas_test.go @@ -624,6 +624,23 @@ func TestNew(t *testing.T) { } } +func TestStepCAS_Type(t *testing.T) { + tests := []struct { + name string + want apiv1.Type + }{ + {"ok", apiv1.StepCAS}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &StepCAS{} + if got := c.Type(); got != tt.want { + t.Errorf("StepCAS.Type() = %v, want %v", got, tt.want) + } + }) + } +} + func TestStepCAS_CreateCertificate(t *testing.T) { caURL, client := testCAHelper(t) x5c := testX5CIssuer(t, caURL, "") diff --git a/cas/vaultcas/vaultcas.go b/cas/vaultcas/vaultcas.go index 5908cb7d..73d1b926 100644 --- a/cas/vaultcas/vaultcas.go +++ b/cas/vaultcas/vaultcas.go @@ -110,6 +110,11 @@ func New(ctx context.Context, opts apiv1.Options) (*VaultCAS, error) { }, nil } +// Type returns the type of this CertificateAuthorityService. +func (v *VaultCAS) Type() apiv1.Type { + return apiv1.VaultCAS +} + // CreateCertificate signs a new certificate using Hashicorp Vault. func (v *VaultCAS) CreateCertificate(req *apiv1.CreateCertificateRequest) (*apiv1.CreateCertificateResponse, error) { switch { diff --git a/cas/vaultcas/vaultcas_test.go b/cas/vaultcas/vaultcas_test.go index 0ea0c4b1..2f44bc05 100644 --- a/cas/vaultcas/vaultcas_test.go +++ b/cas/vaultcas/vaultcas_test.go @@ -193,6 +193,23 @@ func TestNew_register(t *testing.T) { } } +func TestVaultCAS_Type(t *testing.T) { + tests := []struct { + name string + want apiv1.Type + }{ + {"ok", apiv1.VaultCAS}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &VaultCAS{} + if got := c.Type(); got != tt.want { + t.Errorf("VaultCAS.Type() = %v, want %v", got, tt.want) + } + }) + } +} + func TestVaultCAS_CreateCertificate(t *testing.T) { _, client := testCAHelper(t) diff --git a/commands/app.go b/commands/app.go index c96b50ae..1ccaaf3c 100644 --- a/commands/app.go +++ b/commands/app.go @@ -239,7 +239,7 @@ To get a linked authority token: // replace resolver if requested if resolver != "" { net.DefaultResolver.PreferGo = true - net.DefaultResolver.Dial = func(ctx context.Context, network, address string) (net.Conn, error) { + net.DefaultResolver.Dial = func(_ context.Context, network, _ string) (net.Conn, error) { return net.Dial(network, resolver) } } diff --git a/db/db.go b/db/db.go index 39452672..503a7c14 100644 --- a/db/db.go +++ b/db/db.go @@ -116,7 +116,7 @@ func New(c *Config) (AuthDB, error) { opts := []nosql.Option{nosql.WithDatabase(c.Database), nosql.WithValueDir(c.ValueDir)} - if len(c.BadgerFileLoadingMode) > 0 { + if c.BadgerFileLoadingMode != "" { opts = append(opts, nosql.WithBadgerFileLoadingMode(c.BadgerFileLoadingMode)) } diff --git a/errs/error.go b/errs/error.go index c9ad92a6..4ea5001e 100644 --- a/errs/error.go +++ b/errs/error.go @@ -80,7 +80,7 @@ func (e *Error) StatusCode() int { // Message returns a user friendly error, if one is set. func (e *Error) Message() string { - if len(e.Msg) > 0 { + if e.Msg != "" { return e.Msg } return e.Err.Error() @@ -123,7 +123,7 @@ func Wrapf(status int, e error, format string, args ...interface{}) error { // MarshalJSON implements json.Marshaller interface for the Error struct. func (e *Error) MarshalJSON() ([]byte, error) { var msg string - if len(e.Msg) > 0 { + if e.Msg != "" { msg = e.Msg } else { msg = http.StatusText(e.Status) diff --git a/policy/validate.go b/policy/validate.go index f7cf6e70..3ea42cc2 100644 --- a/policy/validate.go +++ b/policy/validate.go @@ -288,7 +288,7 @@ func checkNameConstraints( // domainToReverseLabels converts a textual domain name like foo.example.com to // the list of labels in reverse order, e.g. ["com", "example", "foo"]. func domainToReverseLabels(domain string) (reverseLabels []string, ok bool) { - for len(domain) > 0 { + for domain != "" { if i := strings.LastIndexByte(domain, '.'); i == -1 { reverseLabels = append(reverseLabels, domain) domain = "" @@ -401,7 +401,7 @@ func parseRFC2821Mailbox(in string) (mailbox rfc2821Mailbox, ok bool) { } else { // Atom ("." Atom)* NextChar: - for len(in) > 0 { + for in != "" { // atext from RFC 2822, Section 3.2.4 c := in[0]