From 96de4e6ec8fe98c930ae70c91f888fe1f3a52861 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Mon, 22 Mar 2021 12:56:12 -0700 Subject: [PATCH] Return a non-implemented error in stepcas.RenewCertificate. --- cas/apiv1/services.go | 20 ++++++++++++++ cas/apiv1/services_test.go | 52 ++++++++++++++++++++++++++++++++++++- cas/stepcas/stepcas.go | 21 ++++----------- cas/stepcas/stepcas_test.go | 21 +-------------- 4 files changed, 77 insertions(+), 37 deletions(-) diff --git a/cas/apiv1/services.go b/cas/apiv1/services.go index 40122601..c47f778d 100644 --- a/cas/apiv1/services.go +++ b/cas/apiv1/services.go @@ -1,6 +1,7 @@ package apiv1 import ( + "net/http" "strings" ) @@ -48,3 +49,22 @@ func (t Type) String() string { } return strings.ToLower(string(t)) } + +// ErrNotImplemented is the type of error returned if an operation is not +// implemented. +type ErrNotImplemented struct { + Message string +} + +func (e ErrNotImplemented) Error() string { + if e.Message != "" { + return e.Message + } + return "not implemented" +} + +// StatusCode implements the StatusCoder interface and returns the HTTP 501 +// error. +func (s ErrNotImplemented) StatusCode() int { + return http.StatusNotImplemented +} diff --git a/cas/apiv1/services_test.go b/cas/apiv1/services_test.go index f9ab9042..eb7d502e 100644 --- a/cas/apiv1/services_test.go +++ b/cas/apiv1/services_test.go @@ -1,6 +1,8 @@ package apiv1 -import "testing" +import ( + "testing" +) func TestType_String(t *testing.T) { tests := []struct { @@ -21,3 +23,51 @@ func TestType_String(t *testing.T) { }) } } + +func TestErrNotImplemented_Error(t *testing.T) { + type fields struct { + Message string + } + tests := []struct { + name string + fields fields + want string + }{ + {"default", fields{""}, "not implemented"}, + {"with message", fields{"method not supported"}, "method not supported"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := ErrNotImplemented{ + Message: tt.fields.Message, + } + if got := e.Error(); got != tt.want { + t.Errorf("ErrNotImplemented.Error() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestErrNotImplemented_StatusCode(t *testing.T) { + type fields struct { + Message string + } + tests := []struct { + name string + fields fields + want int + }{ + {"default", fields{""}, 501}, + {"with message", fields{"method not supported"}, 501}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := ErrNotImplemented{ + Message: tt.fields.Message, + } + if got := s.StatusCode(); got != tt.want { + t.Errorf("ErrNotImplemented.StatusCode() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/cas/stepcas/stepcas.go b/cas/stepcas/stepcas.go index 81ef5a7e..6a20468f 100644 --- a/cas/stepcas/stepcas.go +++ b/cas/stepcas/stepcas.go @@ -63,6 +63,8 @@ func New(ctx context.Context, opts apiv1.Options) (*StepCAS, error) { }, nil } +// 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) { switch { case req.CSR == nil: @@ -82,23 +84,10 @@ func (s *StepCAS) CreateCertificate(req *apiv1.CreateCertificateRequest) (*apiv1 }, nil } +// RenewCertificate will always return a non-implemented error as mTLS renewals +// are not supported yet. func (s *StepCAS) RenewCertificate(req *apiv1.RenewCertificateRequest) (*apiv1.RenewCertificateResponse, error) { - switch { - case req.CSR == nil: - return nil, errors.New("renewCertificateRequest `template` cannot be nil") - case req.Lifetime == 0: - return nil, errors.New("renewCertificateRequest `lifetime` cannot be 0") - } - - cert, chain, err := s.createCertificate(req.CSR, req.Lifetime) - if err != nil { - return nil, err - } - - return &apiv1.RenewCertificateResponse{ - Certificate: cert, - CertificateChain: chain, - }, nil + return nil, apiv1.ErrNotImplemented{Message: "stepCAS does not support mTLS renewals"} } func (s *StepCAS) RevokeCertificate(req *apiv1.RevokeCertificateRequest) (*apiv1.RevokeCertificateResponse, error) { diff --git a/cas/stepcas/stepcas_test.go b/cas/stepcas/stepcas_test.go index 998b574e..b4989478 100644 --- a/cas/stepcas/stepcas_test.go +++ b/cas/stepcas/stepcas_test.go @@ -497,28 +497,9 @@ func TestStepCAS_RenewCertificate(t *testing.T) { want *apiv1.RenewCertificateResponse wantErr bool }{ - {"ok", fields{x5c, client, testRootFingerprint}, args{&apiv1.RenewCertificateRequest{ + {"not implemented", fields{x5c, client, testRootFingerprint}, args{&apiv1.RenewCertificateRequest{ CSR: testCR, Lifetime: time.Hour, - }}, &apiv1.RenewCertificateResponse{ - Certificate: testCrt, - CertificateChain: []*x509.Certificate{testIssCrt}, - }, false}, - {"fail CSR", fields{x5c, client, testRootFingerprint}, args{&apiv1.RenewCertificateRequest{ - CSR: nil, - Lifetime: time.Hour, - }}, nil, true}, - {"fail lifetime", fields{x5c, client, testRootFingerprint}, args{&apiv1.RenewCertificateRequest{ - CSR: testCR, - Lifetime: 0, - }}, nil, true}, - {"fail sign token", fields{nil, client, testRootFingerprint}, args{&apiv1.RenewCertificateRequest{ - CSR: testCR, - Lifetime: time.Hour, - }}, nil, true}, - {"fail client sign", fields{x5c, client, testRootFingerprint}, args{&apiv1.RenewCertificateRequest{ - CSR: testFailCR, - Lifetime: time.Hour, }}, nil, true}, } for _, tt := range tests {