From fb429326efdef746d4275941c71a06b9904be695 Mon Sep 17 00:00:00 2001 From: Juan Rodriguez Hortala Date: Tue, 28 Dec 2021 17:19:16 +0100 Subject: [PATCH 1/6] Generate local scanner TLS certificates in Central --- central/localscanner/certificates.go | 46 ++++++++++ central/localscanner/certificates_test.go | 101 ++++++++++++++++++++++ pkg/mtls/crypto.go | 6 +- pkg/mtls/issue_options.go | 7 ++ 4 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 central/localscanner/certificates.go create mode 100644 central/localscanner/certificates_test.go diff --git a/central/localscanner/certificates.go b/central/localscanner/certificates.go new file mode 100644 index 0000000000000..c6f9bbd5ed6e6 --- /dev/null +++ b/central/localscanner/certificates.go @@ -0,0 +1,46 @@ +package localscanner + +import ( + "github.com/pkg/errors" + "github.com/stackrox/rox/generated/storage" + "github.com/stackrox/rox/pkg/certgen" + "github.com/stackrox/rox/pkg/mtls" +) + +// secretDataMap represents data stored as part of a secret. +type secretDataMap = map[string][]byte + +func generateServiceCertificate(serviceType storage.ServiceType, namespace string, clusterId string) (*mtls.IssuedCert, error) { + if serviceType != storage.ServiceType_SCANNER_SERVICE && serviceType != storage.ServiceType_SCANNER_DB_SERVICE { + return nil, errors.Errorf("This function only generates certificates for Scanner services") + } + subject := mtls.NewSubject(clusterId, serviceType) + issueOpts := []mtls.IssueCertOption{ + mtls.WithLocalScannerProfile(), + mtls.WithNamespace(namespace), + } + scannerCert, err := mtls.IssueNewCert(subject, issueOpts...) + if err != nil { + return nil, errors.Wrap(err, "error issuing certificate") + } + return scannerCert, nil +} + +func generateServiceCertMap(serviceType storage.ServiceType, namespace string, clusterId string) (secretDataMap, error) { + numServiceCertDataEntries := 3 // cert pem + key pem + ca pem + fileMap := make(secretDataMap, numServiceCertDataEntries) + + cert, err := generateServiceCertificate(serviceType, namespace, clusterId) + if err != nil { + return fileMap, errors.Wrap(err,"error generating service certificate") + } + certgen.AddCertToFileMap(fileMap, cert, "") + + centralCA, err := mtls.CACertPEM() + if err != nil { + return fileMap, errors.Wrap(err, "could not load central CA") + } + fileMap[mtls.CACertFileName] = centralCA + + return fileMap, nil +} diff --git a/central/localscanner/certificates_test.go b/central/localscanner/certificates_test.go new file mode 100644 index 0000000000000..da4490de4e0b9 --- /dev/null +++ b/central/localscanner/certificates_test.go @@ -0,0 +1,101 @@ +package localscanner + +import ( + "fmt" + "testing" + "time" + + testutilsMTLS "github.com/stackrox/rox/central/testutils/mtls" + "github.com/stackrox/rox/generated/storage" + "github.com/stackrox/rox/pkg/testutils/envisolator" + "github.com/stretchr/testify/suite" +) + +const ( + namespace = "namespace" + clusterId = "clusterId" +) + +func TestHandler(t *testing.T) { + suite.Run(t, new(localScannerSuite)) +} + +type localScannerSuite struct { + suite.Suite + envIsolator *envisolator.EnvIsolator +} + +func (s *localScannerSuite) SetupSuite() { + s.envIsolator = envisolator.NewEnvIsolator(s.T()) +} + +func (s *localScannerSuite) TearDownTest() { + s.envIsolator.RestoreAll() +} + +func (s *localScannerSuite) SetupTest() { + err := testutilsMTLS.LoadTestMTLSCerts(s.envIsolator) + s.Require().NoError(err) +} + +func (s *localScannerSuite) TestCertMapContainsExpectedFiles() { + testCases := []struct{ + service storage.ServiceType + expectError bool + } { + {storage.ServiceType_SCANNER_SERVICE, false}, + {storage.ServiceType_SCANNER_DB_SERVICE, false}, + {storage.ServiceType_SENSOR_SERVICE, true}, + } + + for _, tc := range testCases { + certMap, err := generateServiceCertMap(tc.service, namespace, clusterId) + if tc.expectError { + s.Require().Error(err, tc.service) + continue + } else { + s.Require().NoError(err, tc.service) + } + expectedFiles := []string{"ca.pem", "cert.pem", "key.pem"} + s.Assert().Equal(len(expectedFiles), len(certMap)) + for _, key := range expectedFiles { + s.Assert().Contains(certMap, key, tc.service) + } + } +} + +func (s *localScannerSuite) TestCertificateGeneration() { + testCases := []struct{ + service storage.ServiceType + expectOU string + expectedAlternativeNames []string + } { + {storage.ServiceType_SCANNER_SERVICE, "SCANNER_SERVICE", + []string{"scanner.stackrox", "scanner.stackrox.svc", "scanner.namespace", "scanner.namespace.svc"}}, + {storage.ServiceType_SCANNER_DB_SERVICE, "SCANNER_DB_SERVICE", + []string{"scanner-db.stackrox", "scanner-db.stackrox.svc", "scanner-db.namespace", "scanner-db.namespace.svc"}}, + } + + for _, tc := range testCases { + cert, err := generateServiceCertificate(tc.service, namespace, clusterId) + + s.Require().NoError(err, tc.service) + + subject := cert.X509Cert.Subject + certOUs := subject.OrganizationalUnit + s.Assert().Equal(1, len(certOUs), tc.service) + s.Assert().Equal(tc.expectOU, certOUs[0], tc.service) + + s.Assert().Equal(fmt.Sprintf("%s: %s", tc.expectOU, clusterId), subject.CommonName, tc.service) + + certAlternativeNames := cert.X509Cert.DNSNames + s.Assert().Equal(len(tc.expectedAlternativeNames), len(certAlternativeNames), tc.service) + for _, name := range tc.expectedAlternativeNames { + s.Assert().Contains(certAlternativeNames, name, tc.service) + } + + s.Assert().Equal(cert.X509Cert.NotBefore.Add(2 * 24 * time.Hour), cert.X509Cert.NotAfter, tc.service) + } +} + + diff --git a/pkg/mtls/crypto.go b/pkg/mtls/crypto.go index 3fc2b06abe9f9..79c3d6dc83d3c 100644 --- a/pkg/mtls/crypto.go +++ b/pkg/mtls/crypto.go @@ -57,6 +57,9 @@ const ( ephemeralProfile = "ephemeral" ephemeralInitBundleCertLifetime = 3 * time.Hour + + localScannerProfile = "localScanner" + localScannerProfileCertLifetime = 2 * 24 * time.Hour ) var ( @@ -185,7 +188,8 @@ func createSigningPolicy() *config.Signing { return &config.Signing{ Default: createSigningProfile(certLifetime, beforeGracePeriod), Profiles: map[string]*config.SigningProfile{ - ephemeralProfile: createSigningProfile(ephemeralInitBundleCertLifetime, 0), + ephemeralProfile: createSigningProfile(ephemeralInitBundleCertLifetime, 0), + localScannerProfile: createSigningProfile(localScannerProfileCertLifetime, 0), }, } } diff --git a/pkg/mtls/issue_options.go b/pkg/mtls/issue_options.go index 8c430dd2f1181..5183e7112e603 100644 --- a/pkg/mtls/issue_options.go +++ b/pkg/mtls/issue_options.go @@ -28,3 +28,10 @@ func WithEphemeralValidity() IssueCertOption { o.signerProfile = ephemeralProfile } } + +// WithLocalScannerProfile requests certificates using the local scanner profile. +func WithLocalScannerProfile() IssueCertOption { + return func(o *issueOptions) { + o.signerProfile = localScannerProfile + } +} From 508453107497bd3d3b0967247bbf1b50f5532e6b Mon Sep 17 00:00:00 2001 From: Juan Rodriguez Hortala Date: Tue, 28 Dec 2021 17:45:26 +0100 Subject: [PATCH 2/6] Fix style issues --- central/localscanner/certificates.go | 12 +++++------ central/localscanner/certificates_test.go | 26 +++++++++++------------ 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/central/localscanner/certificates.go b/central/localscanner/certificates.go index c6f9bbd5ed6e6..6c8f8d21fb640 100644 --- a/central/localscanner/certificates.go +++ b/central/localscanner/certificates.go @@ -10,11 +10,11 @@ import ( // secretDataMap represents data stored as part of a secret. type secretDataMap = map[string][]byte -func generateServiceCertificate(serviceType storage.ServiceType, namespace string, clusterId string) (*mtls.IssuedCert, error) { +func generateServiceCertificate(serviceType storage.ServiceType, namespace string, clusterID string) (*mtls.IssuedCert, error) { if serviceType != storage.ServiceType_SCANNER_SERVICE && serviceType != storage.ServiceType_SCANNER_DB_SERVICE { - return nil, errors.Errorf("This function only generates certificates for Scanner services") + return nil, errors.New("can only generate certificates for Scanner services") } - subject := mtls.NewSubject(clusterId, serviceType) + subject := mtls.NewSubject(clusterID, serviceType) issueOpts := []mtls.IssueCertOption{ mtls.WithLocalScannerProfile(), mtls.WithNamespace(namespace), @@ -26,13 +26,13 @@ func generateServiceCertificate(serviceType storage.ServiceType, namespace strin return scannerCert, nil } -func generateServiceCertMap(serviceType storage.ServiceType, namespace string, clusterId string) (secretDataMap, error) { +func generateServiceCertMap(serviceType storage.ServiceType, namespace string, clusterID string) (secretDataMap, error) { numServiceCertDataEntries := 3 // cert pem + key pem + ca pem fileMap := make(secretDataMap, numServiceCertDataEntries) - cert, err := generateServiceCertificate(serviceType, namespace, clusterId) + cert, err := generateServiceCertificate(serviceType, namespace, clusterID) if err != nil { - return fileMap, errors.Wrap(err,"error generating service certificate") + return fileMap, errors.Wrap(err, "error generating service certificate") } certgen.AddCertToFileMap(fileMap, cert, "") diff --git a/central/localscanner/certificates_test.go b/central/localscanner/certificates_test.go index da4490de4e0b9..d479f22d141d4 100644 --- a/central/localscanner/certificates_test.go +++ b/central/localscanner/certificates_test.go @@ -13,7 +13,7 @@ import ( const ( namespace = "namespace" - clusterId = "clusterId" + clusterID = "clusterID" ) func TestHandler(t *testing.T) { @@ -39,17 +39,17 @@ func (s *localScannerSuite) SetupTest() { } func (s *localScannerSuite) TestCertMapContainsExpectedFiles() { - testCases := []struct{ - service storage.ServiceType + testCases := []struct { + service storage.ServiceType expectError bool - } { + }{ {storage.ServiceType_SCANNER_SERVICE, false}, {storage.ServiceType_SCANNER_DB_SERVICE, false}, {storage.ServiceType_SENSOR_SERVICE, true}, } for _, tc := range testCases { - certMap, err := generateServiceCertMap(tc.service, namespace, clusterId) + certMap, err := generateServiceCertMap(tc.service, namespace, clusterID) if tc.expectError { s.Require().Error(err, tc.service) continue @@ -65,11 +65,11 @@ func (s *localScannerSuite) TestCertMapContainsExpectedFiles() { } func (s *localScannerSuite) TestCertificateGeneration() { - testCases := []struct{ - service storage.ServiceType - expectOU string + testCases := []struct { + service storage.ServiceType + expectOU string expectedAlternativeNames []string - } { + }{ {storage.ServiceType_SCANNER_SERVICE, "SCANNER_SERVICE", []string{"scanner.stackrox", "scanner.stackrox.svc", "scanner.namespace", "scanner.namespace.svc"}}, {storage.ServiceType_SCANNER_DB_SERVICE, "SCANNER_DB_SERVICE", @@ -77,7 +77,7 @@ func (s *localScannerSuite) TestCertificateGeneration() { } for _, tc := range testCases { - cert, err := generateServiceCertificate(tc.service, namespace, clusterId) + cert, err := generateServiceCertificate(tc.service, namespace, clusterID) s.Require().NoError(err, tc.service) @@ -86,7 +86,7 @@ func (s *localScannerSuite) TestCertificateGeneration() { s.Assert().Equal(1, len(certOUs), tc.service) s.Assert().Equal(tc.expectOU, certOUs[0], tc.service) - s.Assert().Equal(fmt.Sprintf("%s: %s", tc.expectOU, clusterId), subject.CommonName, tc.service) + s.Assert().Equal(fmt.Sprintf("%s: %s", tc.expectOU, clusterID), subject.CommonName, tc.service) certAlternativeNames := cert.X509Cert.DNSNames s.Assert().Equal(len(tc.expectedAlternativeNames), len(certAlternativeNames), tc.service) @@ -94,8 +94,6 @@ func (s *localScannerSuite) TestCertificateGeneration() { s.Assert().Contains(certAlternativeNames, name, tc.service) } - s.Assert().Equal(cert.X509Cert.NotBefore.Add(2 * 24 * time.Hour), cert.X509Cert.NotAfter, tc.service) + s.Assert().Equal(cert.X509Cert.NotBefore.Add(2*24*time.Hour), cert.X509Cert.NotAfter, tc.service) } } - - From 6317492b872a18e61f911199ea0706d9bfe00ad2 Mon Sep 17 00:00:00 2001 From: Juan Rodriguez Hortala Date: Mon, 3 Jan 2022 15:30:22 +0100 Subject: [PATCH 3/6] add service type to error message --- central/localscanner/certificates.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/central/localscanner/certificates.go b/central/localscanner/certificates.go index 6c8f8d21fb640..ada6b2e19f54e 100644 --- a/central/localscanner/certificates.go +++ b/central/localscanner/certificates.go @@ -12,7 +12,8 @@ type secretDataMap = map[string][]byte func generateServiceCertificate(serviceType storage.ServiceType, namespace string, clusterID string) (*mtls.IssuedCert, error) { if serviceType != storage.ServiceType_SCANNER_SERVICE && serviceType != storage.ServiceType_SCANNER_DB_SERVICE { - return nil, errors.New("can only generate certificates for Scanner services") + return nil, errors.Errorf("can only generate certificates for Scanner services, service type %s is not supported", + serviceType) } subject := mtls.NewSubject(clusterID, serviceType) issueOpts := []mtls.IssueCertOption{ From ac68f5c06feb1d27d43dc238b5bbd48887e24c62 Mon Sep 17 00:00:00 2001 From: Juan Rodriguez Hortala Date: Mon, 3 Jan 2022 15:39:09 +0100 Subject: [PATCH 4/6] Rename ephemeral profiles to have neutral names Referring to the expiration time, instead of to components --- central/localscanner/certificates.go | 2 +- operator/pkg/central/extensions/reconcile_tls.go | 2 +- pkg/mtls/ca_test.go | 9 +++++++-- pkg/mtls/crypto.go | 12 ++++++------ pkg/mtls/issue_options.go | 12 ++++++------ 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/central/localscanner/certificates.go b/central/localscanner/certificates.go index ada6b2e19f54e..2f976d0240bd7 100644 --- a/central/localscanner/certificates.go +++ b/central/localscanner/certificates.go @@ -17,7 +17,7 @@ func generateServiceCertificate(serviceType storage.ServiceType, namespace strin } subject := mtls.NewSubject(clusterID, serviceType) issueOpts := []mtls.IssueCertOption{ - mtls.WithLocalScannerProfile(), + mtls.WithValidityExpiringInDays(), mtls.WithNamespace(namespace), } scannerCert, err := mtls.IssueNewCert(subject, issueOpts...) diff --git a/operator/pkg/central/extensions/reconcile_tls.go b/operator/pkg/central/extensions/reconcile_tls.go index 695cb2d7e0d33..2653c603643eb 100644 --- a/operator/pkg/central/extensions/reconcile_tls.go +++ b/operator/pkg/central/extensions/reconcile_tls.go @@ -180,7 +180,7 @@ func (r *createCentralTLSExtensionRun) generateInitBundleTLSData(fileNamePrefix fileMap := make(secretDataMap, numServiceCertDataEntries) bundleID := uuid.NewV4() subject := mtls.NewInitSubject(centralsensor.EphemeralInitCertClusterID, serviceType, bundleID) - if err := r.generateServiceTLSData(subject, fileNamePrefix, fileMap, mtls.WithEphemeralValidity()); err != nil { + if err := r.generateServiceTLSData(subject, fileNamePrefix, fileMap, mtls.WithValidityExpiringInHours()); err != nil { return nil, err } return fileMap, nil diff --git a/pkg/mtls/ca_test.go b/pkg/mtls/ca_test.go index dfbd16fe475c6..b12aa4a37fe3b 100644 --- a/pkg/mtls/ca_test.go +++ b/pkg/mtls/ca_test.go @@ -21,11 +21,16 @@ func Test_CA_IssueCertForSubject(t *testing.T) { minNotAfter: 364 * 24 * time.Hour, maxNotAfter: 366 * 24 * time.Hour, }, - "ephemeral cert": { - opts: []IssueCertOption{WithEphemeralValidity()}, + "ephemeral cert hourly expiration": { + opts: []IssueCertOption{WithValidityExpiringInHours()}, minNotAfter: 2 * time.Hour, maxNotAfter: 4 * time.Hour, }, + "ephemeral cert daily expiration": { + opts: []IssueCertOption{WithValidityExpiringInDays()}, + minNotAfter: (2*24 - 1) * time.Hour, + maxNotAfter: (2*24 + 1) * time.Hour, + }, } cert, _, key, err := initca.New(&csr.CertificateRequest{ diff --git a/pkg/mtls/crypto.go b/pkg/mtls/crypto.go index 79c3d6dc83d3c..0f848ad7486d5 100644 --- a/pkg/mtls/crypto.go +++ b/pkg/mtls/crypto.go @@ -55,11 +55,11 @@ const ( certLifetime = 365 * 24 * time.Hour - ephemeralProfile = "ephemeral" - ephemeralInitBundleCertLifetime = 3 * time.Hour + ephemeralProfileWithExpirationInHours = "ephemeralWithExpirationInHours" + ephemeralProfileWithExpirationInHoursCertLifetime = 3 * time.Hour - localScannerProfile = "localScanner" - localScannerProfileCertLifetime = 2 * 24 * time.Hour + ephemeralProfileWithExpirationInDays = "ephemeralWithExpirationInDays" + ephemeralProfileWithExpirationInDaysCertLifetime = 2 * 24 * time.Hour ) var ( @@ -188,8 +188,8 @@ func createSigningPolicy() *config.Signing { return &config.Signing{ Default: createSigningProfile(certLifetime, beforeGracePeriod), Profiles: map[string]*config.SigningProfile{ - ephemeralProfile: createSigningProfile(ephemeralInitBundleCertLifetime, 0), - localScannerProfile: createSigningProfile(localScannerProfileCertLifetime, 0), + ephemeralProfileWithExpirationInHours: createSigningProfile(ephemeralProfileWithExpirationInHoursCertLifetime, 0), + ephemeralProfileWithExpirationInDays: createSigningProfile(ephemeralProfileWithExpirationInDaysCertLifetime, 0), }, } } diff --git a/pkg/mtls/issue_options.go b/pkg/mtls/issue_options.go index 5183e7112e603..2666d1b42e3a8 100644 --- a/pkg/mtls/issue_options.go +++ b/pkg/mtls/issue_options.go @@ -21,17 +21,17 @@ func WithNamespace(namespace string) IssueCertOption { } } -// WithEphemeralValidity requests certificates with short validity. +// WithValidityExpiringInHours requests certificates with validity expiring in the order of hours. // This option is suitable for issuing init bundles which cannot be revoked. -func WithEphemeralValidity() IssueCertOption { +func WithValidityExpiringInHours() IssueCertOption { return func(o *issueOptions) { - o.signerProfile = ephemeralProfile + o.signerProfile = ephemeralProfileWithExpirationInHours } } -// WithLocalScannerProfile requests certificates using the local scanner profile. -func WithLocalScannerProfile() IssueCertOption { +// WithValidityExpiringInDays requests certificates with validity expiring in the order of days. +func WithValidityExpiringInDays() IssueCertOption { return func(o *issueOptions) { - o.signerProfile = localScannerProfile + o.signerProfile = ephemeralProfileWithExpirationInDays } } From ec6a96380d3e69208f693e8faa78cbecbb3879a8 Mon Sep 17 00:00:00 2001 From: Juan Rodriguez Hortala Date: Tue, 4 Jan 2022 15:28:31 +0100 Subject: [PATCH 5/6] Expose central CA as a CA instance to simplify signing --- central/localscanner/certificates.go | 32 ++++++++--------------- central/localscanner/certificates_test.go | 30 ++++++++++++++++----- pkg/mtls/crypto.go | 15 +++++++++++ 3 files changed, 50 insertions(+), 27 deletions(-) diff --git a/central/localscanner/certificates.go b/central/localscanner/certificates.go index 2f976d0240bd7..4971aa77f9d8e 100644 --- a/central/localscanner/certificates.go +++ b/central/localscanner/certificates.go @@ -10,38 +10,28 @@ import ( // secretDataMap represents data stored as part of a secret. type secretDataMap = map[string][]byte -func generateServiceCertificate(serviceType storage.ServiceType, namespace string, clusterID string) (*mtls.IssuedCert, error) { +func generateServiceCertMap(serviceType storage.ServiceType, namespace string, clusterID string) (secretDataMap, error) { if serviceType != storage.ServiceType_SCANNER_SERVICE && serviceType != storage.ServiceType_SCANNER_DB_SERVICE { return nil, errors.Errorf("can only generate certificates for Scanner services, service type %s is not supported", serviceType) } - subject := mtls.NewSubject(clusterID, serviceType) - issueOpts := []mtls.IssueCertOption{ - mtls.WithValidityExpiringInDays(), - mtls.WithNamespace(namespace), - } - scannerCert, err := mtls.IssueNewCert(subject, issueOpts...) + + ca, err := mtls.CAForSigning() if err != nil { - return nil, errors.Wrap(err, "error issuing certificate") + return nil, errors.Wrap(err, "could not load CA for signing") } - return scannerCert, nil -} -func generateServiceCertMap(serviceType storage.ServiceType, namespace string, clusterID string) (secretDataMap, error) { numServiceCertDataEntries := 3 // cert pem + key pem + ca pem fileMap := make(secretDataMap, numServiceCertDataEntries) - - cert, err := generateServiceCertificate(serviceType, namespace, clusterID) - if err != nil { - return fileMap, errors.Wrap(err, "error generating service certificate") + subject := mtls.NewSubject(clusterID, serviceType) + issueOpts := []mtls.IssueCertOption{ + mtls.WithValidityExpiringInDays(), + mtls.WithNamespace(namespace), } - certgen.AddCertToFileMap(fileMap, cert, "") - - centralCA, err := mtls.CACertPEM() - if err != nil { - return fileMap, errors.Wrap(err, "could not load central CA") + if err := certgen.IssueServiceCert(fileMap, ca, subject, "", issueOpts...); err != nil { + return nil, errors.Wrap(err, "error generating service certificate") } - fileMap[mtls.CACertFileName] = centralCA + certgen.AddCACertToFileMap(fileMap, ca) return fileMap, nil } diff --git a/central/localscanner/certificates_test.go b/central/localscanner/certificates_test.go index d479f22d141d4..69088fbddec8f 100644 --- a/central/localscanner/certificates_test.go +++ b/central/localscanner/certificates_test.go @@ -5,8 +5,11 @@ import ( "testing" "time" + "github.com/cloudflare/cfssl/helpers" testutilsMTLS "github.com/stackrox/rox/central/testutils/mtls" "github.com/stackrox/rox/generated/storage" + "github.com/stackrox/rox/pkg/certgen" + "github.com/stackrox/rox/pkg/mtls" "github.com/stackrox/rox/pkg/testutils/envisolator" "github.com/stretchr/testify/suite" ) @@ -64,6 +67,21 @@ func (s *localScannerSuite) TestCertMapContainsExpectedFiles() { } } +func (s *localScannerSuite) TestValidateServiceCertificate() { + testCases := []storage.ServiceType{ + storage.ServiceType_SCANNER_SERVICE, + storage.ServiceType_SCANNER_DB_SERVICE, + } + + for _, serviceType := range testCases { + certMap, err := generateServiceCertMap(serviceType, namespace, clusterID) + s.Require().NoError(err, serviceType) + validatingCA, err := mtls.LoadCAForValidation(certMap["ca.pem"]) + s.Require().NoError(err, serviceType) + s.Assert().NoError(certgen.VerifyServiceCert(certMap, validatingCA, serviceType, ""), serviceType) + } +} + func (s *localScannerSuite) TestCertificateGeneration() { testCases := []struct { service storage.ServiceType @@ -77,23 +95,23 @@ func (s *localScannerSuite) TestCertificateGeneration() { } for _, tc := range testCases { - cert, err := generateServiceCertificate(tc.service, namespace, clusterID) - + certMap, err := generateServiceCertMap(tc.service, namespace, clusterID) + s.Require().NoError(err, tc.service) + cert, err := helpers.ParseCertificatePEM(certMap["cert.pem"]) s.Require().NoError(err, tc.service) - subject := cert.X509Cert.Subject + subject := cert.Subject certOUs := subject.OrganizationalUnit s.Assert().Equal(1, len(certOUs), tc.service) s.Assert().Equal(tc.expectOU, certOUs[0], tc.service) s.Assert().Equal(fmt.Sprintf("%s: %s", tc.expectOU, clusterID), subject.CommonName, tc.service) - certAlternativeNames := cert.X509Cert.DNSNames + certAlternativeNames := cert.DNSNames s.Assert().Equal(len(tc.expectedAlternativeNames), len(certAlternativeNames), tc.service) for _, name := range tc.expectedAlternativeNames { s.Assert().Contains(certAlternativeNames, name, tc.service) } - - s.Assert().Equal(cert.X509Cert.NotBefore.Add(2*24*time.Hour), cert.X509Cert.NotAfter, tc.service) + s.Assert().Equal(cert.NotBefore.Add(2*24*time.Hour), cert.NotAfter, tc.service) } } diff --git a/pkg/mtls/crypto.go b/pkg/mtls/crypto.go index 0f848ad7486d5..1b484acb98740 100644 --- a/pkg/mtls/crypto.go +++ b/pkg/mtls/crypto.go @@ -180,6 +180,21 @@ func CACert() (*x509.Certificate, []byte, error) { return caCert, caCertDER, caCertErr } +// CAForSigning reads the cert and key from the local file system and returns +// a corresponding CA instance that can be used for signing +func CAForSigning() (CA, error) { + _, certPEM, _, err := readCA() + if err != nil { + return nil, errors.Wrap(err, "could not read CA cert file") + } + keyPEM, err := readCAKey() + if err != nil { + return nil, errors.Wrap(err, "could not read CA key file") + } + + return LoadCAForSigning(certPEM, keyPEM) +} + func signer() (cfsigner.Signer, error) { return local.NewSignerFromFile(caFilePathSetting.Setting(), caKeyFilePathSetting.Setting(), createSigningPolicy()) } From 278ee720b4f9145657153091fccb1be2ee967562 Mon Sep 17 00:00:00 2001 From: Juan Rodriguez Hortala Date: Tue, 4 Jan 2022 15:36:35 +0100 Subject: [PATCH 6/6] add missing dot to complete a comment --- pkg/mtls/crypto.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/mtls/crypto.go b/pkg/mtls/crypto.go index 1b484acb98740..03ff11ba901aa 100644 --- a/pkg/mtls/crypto.go +++ b/pkg/mtls/crypto.go @@ -181,7 +181,7 @@ func CACert() (*x509.Certificate, []byte, error) { } // CAForSigning reads the cert and key from the local file system and returns -// a corresponding CA instance that can be used for signing +// a corresponding CA instance that can be used for signing. func CAForSigning() (CA, error) { _, certPEM, _, err := readCA() if err != nil {