summaryrefslogtreecommitdiffstats
path: root/certServiceK8sExternalProvider/src
diff options
context:
space:
mode:
Diffstat (limited to 'certServiceK8sExternalProvider/src')
-rw-r--r--certServiceK8sExternalProvider/src/certserviceclient/cert_service_client_mock.go33
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2controller/certificate_request_controller.go2
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller.go3
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller_test.go79
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner.go14
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory.go10
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory_mock.go43
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory_test.go87
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_test.go16
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2provisioner/csr/csr.go62
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2provisioner/csr/csr_test.go103
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2provisioner/csr/testdata/testdata.go29
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2provisioner/testdata/test_private_key.pem28
-rw-r--r--certServiceK8sExternalProvider/src/testdata/provider.go89
-rw-r--r--certServiceK8sExternalProvider/src/x509/testdata/test_data.go68
-rw-r--r--certServiceK8sExternalProvider/src/x509/x509_utils.go42
-rw-r--r--certServiceK8sExternalProvider/src/x509/x509_utils_test.go19
17 files changed, 620 insertions, 107 deletions
diff --git a/certServiceK8sExternalProvider/src/certserviceclient/cert_service_client_mock.go b/certServiceK8sExternalProvider/src/certserviceclient/cert_service_client_mock.go
new file mode 100644
index 00000000..d060a980
--- /dev/null
+++ b/certServiceK8sExternalProvider/src/certserviceclient/cert_service_client_mock.go
@@ -0,0 +1,33 @@
+/*
+ * ============LICENSE_START=======================================================
+ * oom-certservice-k8s-external-provider
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package certserviceclient
+
+type CertServiceClientMock struct {
+ GetCertificatesFunc func(csr []byte, key []byte) (*CertificatesResponse, error)
+}
+
+func (client *CertServiceClientMock) GetCertificates(csr []byte, key []byte) (*CertificatesResponse, error) {
+ return client.GetCertificatesFunc(csr, key)
+}
+
+func (client *CertServiceClientMock) CheckHealth() error {
+ return nil
+}
diff --git a/certServiceK8sExternalProvider/src/cmpv2controller/certificate_request_controller.go b/certServiceK8sExternalProvider/src/cmpv2controller/certificate_request_controller.go
index 03eef35c..e5dc4d1c 100644
--- a/certServiceK8sExternalProvider/src/cmpv2controller/certificate_request_controller.go
+++ b/certServiceK8sExternalProvider/src/cmpv2controller/certificate_request_controller.go
@@ -140,7 +140,7 @@ func (controller *CertificateRequestController) Reconcile(k8sRequest ctrl.Reques
signedPEM, trustedCAs, err := provisioner.Sign(ctx, certificateRequest, privateKeyBytes)
if err != nil {
controller.handleErrorFailedToSignCertificate(ctx, log, err, certificateRequest)
- return ctrl.Result{}, err
+ return ctrl.Result{}, nil
}
// 11. Store signed certificates in CertificateRequest
diff --git a/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller.go b/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller.go
index c6e0e1da..9bc41e7f 100644
--- a/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller.go
+++ b/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller.go
@@ -49,6 +49,7 @@ type CMPv2IssuerController struct {
Log logr.Logger
Clock clock.Clock
Recorder record.EventRecorder
+ ProvisionerFactory provisioners.ProvisionerFactory
}
// Reconcile will read and validate the CMPv2Issuer resources, it will set the
@@ -84,7 +85,7 @@ func (controller *CMPv2IssuerController) Reconcile(req ctrl.Request) (ctrl.Resul
}
// 4. Create CMPv2 provisioner
- provisioner, err := provisioners.CreateProvisioner(issuer, secret)
+ provisioner, err := controller.ProvisionerFactory.CreateProvisioner(issuer, secret)
if err != nil {
log.Error(err, "failed to initialize provisioner")
statusUpdater.UpdateNoError(ctx, cmpv2api.ConditionFalse, "Error", "Failed to initialize provisioner: %v", err)
diff --git a/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller_test.go b/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller_test.go
index 79c78ed5..88aaf5ec 100644
--- a/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller_test.go
+++ b/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller_test.go
@@ -24,14 +24,47 @@ import (
"testing"
"github.com/go-logr/logr"
+ certmanager "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
+ apiv1 "k8s.io/api/core/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/types"
+ clientgoscheme "k8s.io/client-go/kubernetes/scheme"
+ "k8s.io/client-go/tools/record"
+ "k8s.io/utils/clock"
+ ctrl "sigs.k8s.io/controller-runtime"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+ "sigs.k8s.io/controller-runtime/pkg/client/fake"
+ "sigs.k8s.io/controller-runtime/pkg/reconcile"
"onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
+ certserviceapi "onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
+ provisioners "onap.org/oom-certservice/k8s-external-provider/src/cmpv2provisioner"
+ "onap.org/oom-certservice/k8s-external-provider/src/testdata"
)
+func Test_shouldPrepareAndVerifyCMPv2Issuer_whenRequestReceived(t *testing.T) {
+ scheme := initScheme()
+ issuer, secret := testdata.GetValidIssuerWithSecret()
+ fakeClient := getFakeClient(scheme, issuer, secret)
+ fakeRequest := getFakeRequest()
+ fakeRecorder := record.NewFakeRecorder(3)
+ controller := getController(fakeRecorder, fakeClient)
+
+ res, err := controller.Reconcile(fakeRequest)
+
+ expectedProvisioner, _ := controller.ProvisionerFactory.CreateProvisioner(&issuer, secret)
+ actualProvisioner, _ := provisioners.Load(types.NamespacedName{Name: testdata.IssuerObjectName, Namespace: testdata.Namespace})
+ assert.Nil(t, err)
+ assert.NotNil(t, res)
+ assert.Equal(t, <-fakeRecorder.Events, "Normal Verified CMPv2Issuer verified and ready to sign certificates")
+ assert.NotNil(t, actualProvisioner)
+ assert.ObjectsAreEqual(expectedProvisioner, actualProvisioner)
+}
+
func Test_shouldBeValidCMPv2IssuerSpec_whenAllFieldsAreSet(t *testing.T) {
- spec := getValidCMPv2IssuerSpec()
+ spec := testdata.GetValidCMPv2IssuerSpec()
err := validateCMPv2IssuerSpec(spec, &MockLogger{})
assert.Nil(t, err)
@@ -61,24 +94,46 @@ func Test_shouldBeInvalidCMPv2IssuerSpec_whenNotAllFieldsAreSet(t *testing.T) {
}
func test_shouldBeInvalidCMPv2IssuerSpec_whenFunctionApplied(t *testing.T, transformSpec func(spec *cmpv2api.CMPv2IssuerSpec)) {
- spec := getValidCMPv2IssuerSpec()
+ spec := testdata.GetValidCMPv2IssuerSpec()
transformSpec(&spec)
err := validateCMPv2IssuerSpec(spec, nil)
assert.NotNil(t, err)
}
-func getValidCMPv2IssuerSpec() cmpv2api.CMPv2IssuerSpec {
- issuerSpec := cmpv2api.CMPv2IssuerSpec{
- URL: "https://oom-cert-service:8443/v1/certificate/",
- CaName: "RA",
- CertSecretRef: cmpv2api.SecretKeySelector{
- Name: "issuer-cert-secret",
- KeyRef: "cmpv2Issuer-key.pem",
- CertRef: "cmpv2Issuer-cert.pem",
- CacertRef: "cacert.pem",
+func getController(fakeRecorder *record.FakeRecorder, mockClient client.Client) CMPv2IssuerController {
+ controller := CMPv2IssuerController{
+ Log: ctrl.Log.WithName("controllers").WithName("CertificateRequest"),
+ Clock: clock.RealClock{},
+ Recorder: fakeRecorder,
+ Client: mockClient,
+ ProvisionerFactory: &provisioners.ProvisionerFactoryMock{},
+ }
+ return controller
+}
+
+func getFakeRequest() reconcile.Request {
+ fakeRequest := reconcile.Request{
+ NamespacedName: types.NamespacedName{
+ Namespace: testdata.Namespace,
+ Name: testdata.IssuerObjectName,
},
}
- return issuerSpec
+ return fakeRequest
+}
+
+func getFakeClient(scheme *runtime.Scheme, issuer cmpv2api.CMPv2Issuer, secret apiv1.Secret) client.Client {
+ fakeClient := func() client.Client {
+ return fake.NewFakeClientWithScheme(scheme, &issuer, &secret)
+ }()
+ return fakeClient
+}
+
+func initScheme() *runtime.Scheme {
+ scheme := runtime.NewScheme()
+ _ = clientgoscheme.AddToScheme(scheme)
+ _ = certmanager.AddToScheme(scheme)
+ _ = certserviceapi.AddToScheme(scheme)
+ return scheme
}
type MockLogger struct {
diff --git a/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner.go b/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner.go
index 60610d32..14cb228f 100644
--- a/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner.go
+++ b/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner.go
@@ -35,6 +35,7 @@ import (
"onap.org/oom-certservice/k8s-external-provider/src/certserviceclient"
"onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
+ "onap.org/oom-certservice/k8s-external-provider/src/cmpv2provisioner/csr"
)
var collection = new(sync.Map)
@@ -83,7 +84,11 @@ func Store(namespacedName types.NamespacedName, provisioner *CertServiceCA) {
collection.Store(namespacedName, provisioner)
}
-func (ca *CertServiceCA) Sign(ctx context.Context, certificateRequest *certmanager.CertificateRequest, privateKeyBytes []byte) ([]byte, []byte, error) {
+func (ca *CertServiceCA) Sign(
+ ctx context.Context,
+ certificateRequest *certmanager.CertificateRequest,
+ privateKeyBytes []byte,
+) (signedCertificateChain []byte, trustedCertificates []byte, err error) {
log := ctrl.Log.WithName("certservice-provisioner")
log.Info("Signing certificate: ", "cert-name", certificateRequest.Name)
@@ -92,7 +97,12 @@ func (ca *CertServiceCA) Sign(ctx context.Context, certificateRequest *certmanag
csrBytes := certificateRequest.Spec.Request
log.Info("Csr PEM: ", "bytes", csrBytes)
- response, err := ca.certServiceClient.GetCertificates(csrBytes, privateKeyBytes)
+ filteredCsrBytes, err := csr.FilterFieldsFromCSR(csrBytes, privateKeyBytes)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ response, err := ca.certServiceClient.GetCertificates(filteredCsrBytes, privateKeyBytes)
if err != nil {
return nil, nil, err
}
diff --git a/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory.go b/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory.go
index 27f5c108..00abd2ea 100644
--- a/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory.go
+++ b/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory.go
@@ -29,7 +29,15 @@ import (
"onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
)
-func CreateProvisioner(issuer *cmpv2api.CMPv2Issuer, secret v1.Secret) (*CertServiceCA, error) {
+
+type ProvisionerFactory interface {
+ CreateProvisioner(issuer *cmpv2api.CMPv2Issuer, secret v1.Secret) (*CertServiceCA, error)
+}
+
+type ProvisionerFactoryImpl struct {
+}
+
+func (f *ProvisionerFactoryImpl) CreateProvisioner(issuer *cmpv2api.CMPv2Issuer, secret v1.Secret) (*CertServiceCA, error) {
secretKeys := issuer.Spec.CertSecretRef
keyBase64, err := readValueFromSecret(secret, secretKeys.KeyRef)
if err != nil {
diff --git a/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory_mock.go b/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory_mock.go
new file mode 100644
index 00000000..f2ffa860
--- /dev/null
+++ b/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory_mock.go
@@ -0,0 +1,43 @@
+/*
+ * ============LICENSE_START=======================================================
+ * oom-certservice-k8s-external-provider
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package cmpv2provisioner
+
+import (
+ v1 "k8s.io/api/core/v1"
+
+ "onap.org/oom-certservice/k8s-external-provider/src/certserviceclient"
+ "onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
+ "onap.org/oom-certservice/k8s-external-provider/src/cmpv2provisioner/testdata"
+)
+
+type ProvisionerFactoryMock struct {
+ CreateProvisionerFunc func(issuer *cmpv2api.CMPv2Issuer, secret v1.Secret) (*CertServiceCA, error)
+}
+
+func (f *ProvisionerFactoryMock) CreateProvisioner(issuer *cmpv2api.CMPv2Issuer, secret v1.Secret) (*CertServiceCA, error) {
+ provisioner, err := New(issuer, &certserviceclient.CertServiceClientMock{
+ GetCertificatesFunc: func(csr []byte, pk []byte) (response *certserviceclient.CertificatesResponse, e error) {
+ return &testdata.SampleCertServiceResponse, nil
+ },
+ })
+
+ return provisioner, err
+}
diff --git a/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory_test.go b/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory_test.go
index be19bde9..a7e975a4 100644
--- a/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory_test.go
+++ b/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory_test.go
@@ -26,105 +26,70 @@ import (
"testing"
"github.com/stretchr/testify/assert"
- v1 "k8s.io/api/core/v1"
- "onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
"onap.org/oom-certservice/k8s-external-provider/src/testdata"
)
-const (
- secretName = "issuer-cert-secret"
- url = "https://oom-cert-service:8443/v1/certificate/"
- healthEndpoint = "actuator/health"
- certEndpoint = "v1/certificate"
- caName = "RA"
- keySecretKey = "cmpv2Issuer-key.pem"
- certSecretKey = "cmpv2Issuer-cert.pem"
- cacertSecretKey = "cacert.pem"
-)
-
func Test_shouldCreateProvisioner(t *testing.T) {
- issuer, secret := getValidIssuerAndSecret()
+ issuer, secret := testdata.GetValidIssuerWithSecret()
+ provisionerFactory := ProvisionerFactoryImpl{}
- provisioner, _ := CreateProvisioner(&issuer, secret)
+ provisioner, _ := provisionerFactory.CreateProvisioner(&issuer, secret)
assert.NotNil(t, provisioner)
- assert.Equal(t, url, provisioner.url)
- assert.Equal(t, caName, provisioner.caName)
- assert.Equal(t, healthEndpoint, provisioner.healthEndpoint)
- assert.Equal(t, certEndpoint, provisioner.certEndpoint)
+ assert.Equal(t, testdata.Url, provisioner.url)
+ assert.Equal(t, testdata.CaName, provisioner.caName)
+ assert.Equal(t, testdata.HealthEndpoint, provisioner.healthEndpoint)
+ assert.Equal(t, testdata.CertEndpoint, provisioner.certEndpoint)
}
func Test_shouldReturnError_whenSecretMissingKeyRef(t *testing.T) {
- issuer, secret := getValidIssuerAndSecret()
- delete(secret.Data, keySecretKey)
+ issuer, secret := testdata.GetValidIssuerWithSecret()
+ delete(secret.Data, testdata.KeySecretKey)
+ provisionerFactory := ProvisionerFactoryImpl{}
- provisioner, err := CreateProvisioner(&issuer, secret)
+ provisioner, err := provisionerFactory.CreateProvisioner(&issuer, secret)
assert.Nil(t, provisioner)
if assert.Error(t, err) {
- assert.Equal(t, fmt.Errorf("secret %s does not contain key %s", secretName, keySecretKey), err)
+ assert.Equal(t, fmt.Errorf("secret %s does not contain key %s", testdata.SecretName, testdata.KeySecretKey), err)
}
}
func Test_shouldReturnError_whenSecretMissingCertRef(t *testing.T) {
- issuer, secret := getValidIssuerAndSecret()
- delete(secret.Data, certSecretKey)
+ issuer, secret := testdata.GetValidIssuerWithSecret()
+ delete(secret.Data, testdata.CertSecretKey)
+ provisionerFactory := ProvisionerFactoryImpl{}
- provisioner, err := CreateProvisioner(&issuer, secret)
+ provisioner, err := provisionerFactory.CreateProvisioner(&issuer, secret)
assert.Nil(t, provisioner)
if assert.Error(t, err) {
- assert.Equal(t, fmt.Errorf("secret %s does not contain key %s", secretName, certSecretKey), err)
+ assert.Equal(t, fmt.Errorf("secret %s does not contain key %s", testdata.SecretName, testdata.CertSecretKey), err)
}
}
func Test_shouldReturnError_whenSecretMissingCacertRef(t *testing.T) {
- issuer, secret := getValidIssuerAndSecret()
- delete(secret.Data, cacertSecretKey)
+ issuer, secret := testdata.GetValidIssuerWithSecret()
+ delete(secret.Data, testdata.CacertSecretKey)
+ provisionerFactory := ProvisionerFactoryImpl{}
- provisioner, err := CreateProvisioner(&issuer, secret)
+ provisioner, err := provisionerFactory.CreateProvisioner(&issuer, secret)
assert.Nil(t, provisioner)
if assert.Error(t, err) {
- assert.Equal(t, fmt.Errorf("secret %s does not contain key %s", secretName, cacertSecretKey), err)
+ assert.Equal(t, fmt.Errorf("secret %s does not contain key %s", testdata.SecretName, testdata.CacertSecretKey), err)
}
}
func Test_shouldReturnError_whenCreationOfCertServiceClientReturnsError(t *testing.T) {
- issuer, secret := getValidIssuerAndSecret()
+ issuer, secret := testdata.GetValidIssuerWithSecret()
invalidKeySecretValue, _ := base64.StdEncoding.DecodeString("")
- secret.Data[keySecretKey] = invalidKeySecretValue
+ secret.Data[testdata.KeySecretKey] = invalidKeySecretValue
+ provisionerFactory := ProvisionerFactoryImpl{}
- provisioner, err := CreateProvisioner(&issuer, secret)
+ provisioner, err := provisionerFactory.CreateProvisioner(&issuer, secret)
assert.Nil(t, provisioner)
assert.Error(t, err)
}
-
-func getValidIssuerAndSecret() (cmpv2api.CMPv2Issuer, v1.Secret) {
- issuer := cmpv2api.CMPv2Issuer{
- Spec: cmpv2api.CMPv2IssuerSpec{
- URL: url,
- HealthEndpoint: healthEndpoint,
- CertEndpoint: certEndpoint,
- CaName: caName,
- CertSecretRef: cmpv2api.SecretKeySelector{
- Name: secretName,
- KeyRef: keySecretKey,
- CertRef: certSecretKey,
- CacertRef: cacertSecretKey,
- },
- },
- }
- secret := v1.Secret{
-
- Data: map[string][]byte{
- keySecretKey: testdata.KeyBytes,
- certSecretKey: testdata.CertBytes,
- cacertSecretKey: testdata.CacertBytes,
- },
- }
- secret.Name = secretName
- return issuer, secret
-}
diff --git a/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_test.go b/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_test.go
index 57e269a4..a483c72c 100644
--- a/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_test.go
+++ b/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_test.go
@@ -30,12 +30,12 @@ import (
cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
"github.com/stretchr/testify/assert"
+ apiv1 "k8s.io/api/core/v1"
apimach "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"onap.org/oom-certservice/k8s-external-provider/src/certserviceclient"
"onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
- "onap.org/oom-certservice/k8s-external-provider/src/cmpv2provisioner/testdata"
)
const ISSUER_NAME = "cmpv2-issuer"
@@ -72,11 +72,8 @@ func Test_shouldReturnCorrectSignedPemsWhenParametersAreCorrect(t *testing.T) {
const EXPECTED_TRUSTED_FILENAME = "testdata/expected_trusted.pem"
issuer := createIssuerAndCerts(ISSUER_NAME, ISSUER_URL)
- provisioner, err := New(&issuer, &certServiceClientMock{
- getCertificatesFunc: func(csr []byte, pk []byte) (response *certserviceclient.CertificatesResponse, e error) {
- return &testdata.SampleCertServiceResponse, nil
- },
- })
+ provisionerFactory := ProvisionerFactoryMock{}
+ provisioner, err := provisionerFactory.CreateProvisioner(&issuer, apiv1.Secret{})
issuerNamespaceName := createIssuerNamespaceName(ISSUER_NAMESPACE, ISSUER_NAME)
Store(issuerNamespaceName, provisioner)
@@ -87,8 +84,9 @@ func Test_shouldReturnCorrectSignedPemsWhenParametersAreCorrect(t *testing.T) {
ctx := context.Background()
request := createCertificateRequest()
+ privateKeyBytes := getPrivateKeyBytes()
- signedPEM, trustedCAs, err := provisioner.Sign(ctx, request, nil)
+ signedPEM, trustedCAs, err := provisioner.Sign(ctx, request, privateKeyBytes)
assert.Nil(t, err)
@@ -153,6 +151,10 @@ func createCertificateRequest() *cmapi.CertificateRequest {
return request
}
+func getPrivateKeyBytes() []byte {
+ return readFile("testdata/test_private_key.pem")
+}
+
func areSlicesEqual(slice1 []byte, slice2 []byte) bool {
return bytes.Compare(slice1, slice2) == 0
}
diff --git a/certServiceK8sExternalProvider/src/cmpv2provisioner/csr/csr.go b/certServiceK8sExternalProvider/src/cmpv2provisioner/csr/csr.go
new file mode 100644
index 00000000..1a86866b
--- /dev/null
+++ b/certServiceK8sExternalProvider/src/cmpv2provisioner/csr/csr.go
@@ -0,0 +1,62 @@
+/*
+ * ============LICENSE_START=======================================================
+ * oom-certservice-k8s-external-provider
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package csr
+
+import (
+ "crypto/rand"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/pem"
+
+ x509utils "onap.org/oom-certservice/k8s-external-provider/src/x509"
+)
+
+func FilterFieldsFromCSR(csrBytes []byte, privateKeyBytes []byte) ([]byte, error) {
+ csr, err := x509utils.DecodeCSR(csrBytes)
+ if err != nil {
+ return nil, err
+ }
+
+ key, err := x509utils.DecodePrivateKey(privateKeyBytes)
+ if err != nil {
+ return nil, err
+ }
+
+ filteredSubject := filterFieldsFromSubject(csr.Subject)
+
+ filteredCsr, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{
+ Subject: filteredSubject,
+ DNSNames: csr.DNSNames,
+ }, key)
+ if err != nil {
+ return nil, err
+ }
+
+ csrBytes = pem.EncodeToMemory(&pem.Block{Type: x509utils.PemCsrType, Bytes: filteredCsr})
+ return csrBytes, nil
+}
+
+func filterFieldsFromSubject(subject pkix.Name) pkix.Name {
+ subject.StreetAddress = []string{}
+ subject.SerialNumber = ""
+ subject.PostalCode = []string{}
+ return subject
+}
diff --git a/certServiceK8sExternalProvider/src/cmpv2provisioner/csr/csr_test.go b/certServiceK8sExternalProvider/src/cmpv2provisioner/csr/csr_test.go
new file mode 100644
index 00000000..08fb5538
--- /dev/null
+++ b/certServiceK8sExternalProvider/src/cmpv2provisioner/csr/csr_test.go
@@ -0,0 +1,103 @@
+/*
+ * ============LICENSE_START=======================================================
+ * oom-certservice-k8s-external-provider
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package csr
+
+import (
+ "crypto/x509"
+ "encoding/pem"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ "onap.org/oom-certservice/k8s-external-provider/src/cmpv2provisioner/csr/testdata"
+)
+
+func Test_FilterFieldsFromCSR_shouldFilterUnsupportedFields(t *testing.T) {
+ filteredCsrBytes, _ := FilterFieldsFromCSR(testdata.CsrBytesWithNotSupportedFields, testdata.PrivateKeyBytes)
+
+ assertNotFilteredFieldsNotChanged(t, testdata.CsrBytesWithNotSupportedFields, filteredCsrBytes)
+ assertFilteredFieldsEmpty(t, filteredCsrBytes)
+}
+
+func Test_FilterFieldsFromCSR_shouldNotChangeCsrWithoutNotSupportedFields(t *testing.T) {
+ filteredCsrBytes, _ := FilterFieldsFromCSR(testdata.CsrBytesWithoutNotSupportedFields, testdata.PrivateKeyBytes)
+
+ assertNotFilteredFieldsNotChanged(t, testdata.CsrBytesWithoutNotSupportedFields, filteredCsrBytes)
+ assertFilteredFieldsEmpty(t, filteredCsrBytes)
+}
+
+func Test_FilterFieldsFromCSR_shouldErrorWhenCsrPemCannotBeDecoded(t *testing.T) {
+ _, err := FilterFieldsFromCSR([]byte(""), testdata.PrivateKeyBytes)
+
+ assert.Error(t, err)
+}
+
+func Test_FilterFieldsFromCSR_shouldErrorWhenCsrCannotBeParsed(t *testing.T) {
+ //Private Key used as CSR
+ _, err := FilterFieldsFromCSR(testdata.PrivateKeyBytes, testdata.PrivateKeyBytes)
+
+ assert.Error(t, err)
+}
+
+func Test_FilterFieldsFromCSR_shouldErrorWhenPkPemCannotBeDecoded(t *testing.T) {
+ _, err := FilterFieldsFromCSR(testdata.CsrBytesWithNotSupportedFields, []byte(""))
+
+ assert.Error(t, err)
+}
+
+func Test_FilterFieldsFromCSR_shouldErrorWhenPkCannotBeParsed(t *testing.T) {
+ //CSR used as Private Key
+ _, err := FilterFieldsFromCSR(testdata.CsrBytesWithNotSupportedFields, testdata.CsrBytesWithNotSupportedFields)
+
+ assert.Error(t, err)
+}
+
+func assertNotFilteredFieldsNotChanged(t *testing.T, originalCsrBytes []byte, filteredCsrBytes []byte) {
+ originalCsr := parseCsrBytes(originalCsrBytes)
+ filteredCsr := parseCsrBytes(filteredCsrBytes)
+
+ assert.Equal(t, originalCsr.DNSNames, filteredCsr.DNSNames)
+ assert.Equal(t, originalCsr.PublicKey, filteredCsr.PublicKey)
+ assert.Equal(t, originalCsr.PublicKeyAlgorithm, filteredCsr.PublicKeyAlgorithm)
+ assert.Equal(t, originalCsr.SignatureAlgorithm, filteredCsr.SignatureAlgorithm)
+ assert.Equal(t, originalCsr.Subject.CommonName, filteredCsr.Subject.CommonName)
+ assert.Equal(t, originalCsr.Subject.Country, filteredCsr.Subject.Country)
+ assert.Equal(t, originalCsr.Subject.Locality, filteredCsr.Subject.Locality)
+ assert.Equal(t, originalCsr.Subject.Organization, filteredCsr.Subject.Organization)
+ assert.Equal(t, originalCsr.Subject.OrganizationalUnit, filteredCsr.Subject.OrganizationalUnit)
+ assert.Equal(t, originalCsr.Subject.Province, filteredCsr.Subject.Province)
+}
+
+func assertFilteredFieldsEmpty(t *testing.T, csrBytes []byte) {
+ csr := parseCsrBytes(csrBytes)
+ assert.Nil(t, csr.URIs)
+ assert.Nil(t, csr.EmailAddresses)
+ assert.Nil(t, csr.IPAddresses)
+ assert.Nil(t, csr.Subject.PostalCode)
+ assert.Equal(t, "", csr.Subject.SerialNumber)
+ assert.Nil(t, csr.Subject.StreetAddress)
+}
+
+func parseCsrBytes(csrBytes []byte) *x509.CertificateRequest {
+ decodedCsr, _ := pem.Decode(csrBytes)
+ csr, _ := x509.ParseCertificateRequest(decodedCsr.Bytes)
+ return csr
+}
diff --git a/certServiceK8sExternalProvider/src/cmpv2provisioner/csr/testdata/testdata.go b/certServiceK8sExternalProvider/src/cmpv2provisioner/csr/testdata/testdata.go
new file mode 100644
index 00000000..c79f4f79
--- /dev/null
+++ b/certServiceK8sExternalProvider/src/cmpv2provisioner/csr/testdata/testdata.go
@@ -0,0 +1,29 @@
+/*
+ * ============LICENSE_START=======================================================
+ * oom-certservice-k8s-external-provider
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package testdata
+
+import "encoding/base64"
+
+var (
+ CsrBytesWithNotSupportedFields, _ = base64.StdEncoding.DecodeString("LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJRG1EQ0NBb0FDQVFBd2dib3hDekFKQmdOVkJBWVRBbFZUTVJNd0VRWURWUVFJRXdwRFlXeHBabTl5Ym1saApNUll3RkFZRFZRUUhFdzFUWVc0dFJuSmhibU5wYzJOdk1SVXdFd1lEVlFRSkV3eHpZVzF3YkdWVGRISmxaWFF4CkR6QU5CZ05WQkJFVEJqRXlMVE0wTlRFWk1CY0dBMVVFQ2hNUVRHbHVkWGd0Um05MWJtUmhkR2x2YmpFTk1Bc0cKQTFVRUN4TUVUMDVCVURFY01Cb0dBMVVFQXhNVFkyVnlkR2x6YzNWbGNpNXZibUZ3TG05eVp6RU9NQXdHQTFVRQpCUk1GTVRJek5EVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDZUFLZVBUemEzCkI5K1E1d21qd0FtSVUxOG1Ec05taUkwMVcvblkzbndBaTVSeU9aeVUyTm02blV5cUI0NFdiK2cvMnNqejV6VmMKVkJwL2NGK2hucmJtd2I4TTRSMkltUnlqM0VtM2h1UHEwb091TXFQUDRZRzBKSkc3SXpNRHBMOHI0SHdSK21GSgpaVW8rWGlBYkhjaXJFeUdlNWNQTjY0NXhidVpUenpNZ3ZRMGV0TW4zcDdPVDRoVWM1R081WFRlQkluWXJFQU1tCktQaHcydk9qK1YvMHRvK2V1UStRS081cG9UV0szazhVT2x4L1FGVFhVWEMrQ1ZzNWFoRE5QWDZHYnc2aDl2MGsKUk9HOGJSWk80SGhrK05ueWdUNUx4OEVydE1PYWNtRkYxL3lxU1U1ZWhvTVdHaHFmY0x6ekZzaFJjd3BzWUJ3RApOcTAyVkhER1NFNVZBZ01CQUFHZ2daY3dnWlFHQ1NxR1NJYjNEUUVKRGpHQmhqQ0JnekJWQmdOVkhSRUVUakJNCmdnbHNiMk5oYkdodmMzU0NFMk5sY25ScGMzTjFaWEl1YjI1aGNDNXZjbWVCRFc5dVlYQkFiMjVoY0M1dmNtZUgKQkg4QUFBR0dGVzl1WVhBNkx5OWpiSFZ6ZEdWeUxteHZZMkZzTHpBTEJnTlZIUThFQkFNQ0FnUXdIUVlEVlIwbApCQll3RkFZSUt3WUJCUVVIQXdFR0NDc0dBUVVGQndNQ01BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQUVUeTNECmNEQ1BSSmJGbEVXWlh6NDdOWUtLMXl2QXprRTVEQlN2Qkc2bEVGU01TWXY2dDF0MzF6aU9pUm9WTXZ1WlJJZDQKZ0NNcHpwdlpXUmdwSFpNQWd1ZEI2TkRHOXBzdjJYam92KzJNOXBTS3VmS3ZIeXZ4SFR3czNOYU1ENXlQSy9JMgppVDE5TlFDbjRBZXpBclFiM3JHTVAzd2pnRFlwLzgwU0tzQTk3R3o2bkYvMEErY0dWNHprRExiYUx2RExNU2xLCkNaZmxWdFkxOFlYRXMxcUJvMVFqSlZKVFBjSTB6VkxHVlZKRExJZ1lLcmlEdldvbzFObEx5aUhnNWczaTF3NFYKc0QvOFR0UWhYaTBUWTZDdkJObGkwQTdjUDhyOHFKakxFRDlpMnFZcWxvekFvS256R1c3d2hpZ3RhYnVUTVdIRQpKWDJ2LzFGbE1lVlZ1OUMvCi0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=")
+ CsrBytesWithoutNotSupportedFields, _ = base64.StdEncoding.DecodeString("LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJREJEQ0NBZXdDQVFBd2dZSXhDekFKQmdOVkJBWVRBbFZUTVJNd0VRWURWUVFJRXdwRFlXeHBabTl5Ym1saApNUll3RkFZRFZRUUhFdzFUWVc0dFJuSmhibU5wYzJOdk1Sa3dGd1lEVlFRS0V4Qk1hVzUxZUMxR2IzVnVaR0YwCmFXOXVNUTB3Q3dZRFZRUUxFd1JQVGtGUU1Sd3dHZ1lEVlFRREV4TmpaWEowYVhOemRXVnlMbTl1WVhBdWIzSm4KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUFuZ0NuajA4MnR3ZmZrT2NKbzhBSgppRk5mSmc3RFpvaU5OVnY1Mk41OEFJdVVjam1jbE5qWnVwMU1xZ2VPRm0vb1A5ckk4K2MxWEZRYWYzQmZvWjYyCjVzRy9ET0VkaUprY285eEp0NGJqNnRLRHJqS2p6K0dCdENTUnV5TXpBNlMvSytCOEVmcGhTV1ZLUGw0Z0d4M0kKcXhNaG51WER6ZXVPY1c3bVU4OHpJTDBOSHJUSjk2ZXprK0lWSE9SanVWMDNnU0oyS3hBREppajRjTnJ6by9sZgo5TGFQbnJrUGtDanVhYUUxaXQ1UEZEcGNmMEJVMTFGd3ZnbGJPV29RelQxK2htOE9vZmI5SkVUaHZHMFdUdUI0ClpQalo4b0UrUzhmQks3VERtbkpoUmRmOHFrbE9Yb2FERmhvYW4zQzg4eGJJVVhNS2JHQWNBemF0TmxSd3hraE8KVlFJREFRQUJvRHd3T2dZSktvWklodmNOQVFrT01TMHdLekFwQmdOVkhSRUVJakFnZ2dsc2IyTmhiR2h2YzNTQwpFMk5sY25ScGMzTjFaWEl1YjI1aGNDNXZjbWN3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUQyb1RNNmVtVUVFCkZnbnBXR3dQVEZEUWtGOStkYSt5aSthWTlYYU5aU1p0UnBseldFeGdOR2l2UVVpbHFzN2pPT1kyM0ZrbjNpZnoKd2tNbXBZWFVxSEhxeXJueURCQUxHcC9pN3pteGVQMVFwSmFMcmIzVXV3ZytXZzMzam5ZMkdkTTFxVXlRVHVqZwoxMjBNK1pOUjJOMjlKVkJZNnNyRmlWZFJGYlBoMVhVK3VFMm5KOThBK0JGOUhRLzBBaC9TaURyRlRXYktRYWdBCkhmOXY5ZlZXeTVkSG8yQldWb1JkN3hDZWV2TGpyeVdYck5wMzluOHhCaitHSEp1WXl0V1R2cnhiZHJkcU9OYnEKeXlEaWRhQlllY3NqTTJSTlRGVytJazBHazdpWHZTd2l4MWZHWEdyZ1NUNytpcGhwVHM4ekNZN3FOZmo5Z1MrNQpuQ1A4TTdrbVZiND0KLS0tLS1FTkQgQ0VSVElGSUNBVEUgUkVRVUVTVC0tLS0tCg==")
+ PrivateKeyBytes, _ = base64.StdEncoding.DecodeString("LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2QUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktZd2dnU2lBZ0VBQW9JQkFRQ2VBS2VQVHphM0I5K1EKNXdtandBbUlVMThtRHNObWlJMDFXL25ZM253QWk1UnlPWnlVMk5tNm5VeXFCNDRXYitnLzJzano1elZjVkJwLwpjRitobnJibXdiOE00UjJJbVJ5ajNFbTNodVBxMG9PdU1xUFA0WUcwSkpHN0l6TURwTDhyNEh3UittRkpaVW8rClhpQWJIY2lyRXlHZTVjUE42NDV4YnVaVHp6TWd2UTBldE1uM3A3T1Q0aFVjNUdPNVhUZUJJbllyRUFNbUtQaHcKMnZPaitWLzB0bytldVErUUtPNXBvVFdLM2s4VU9seC9RRlRYVVhDK0NWczVhaEROUFg2R2J3Nmg5djBrUk9HOApiUlpPNEhoaytObnlnVDVMeDhFcnRNT2FjbUZGMS95cVNVNWVob01XR2hxZmNMenpGc2hSY3dwc1lCd0ROcTAyClZIREdTRTVWQWdNQkFBRUNnZ0VBZnZBdnJpY0o0a3BsQnRsWEdVT3paTjcyVm5FTjgxWkpmRkVFallOUlJHN2YKT0ZXb3dyemxUOVFJUDZJS09XUjJ4clpUTkFEUkVmaFB3WXJhaWRJbFI0Ym9vc1JKSWZGQTNUU2gxTngrUjY0UgpOT1ppVFNUek8zTVYwYThaMFJlT3J3V1BLREpyN3JkOXlsVjhuY3h6NTExYmFYbFdzaDFKTjBETnN3K0lHQWdICkcycHphdUYwOFNGSzVTVUNYRzBhK2lkOTI0ektpQzJrbzJwMVJGeUt1cWJYRWR1eUdhQVNCeDdwVUtnVWhVTzgKWjgyMENuSzB4Yi9KbnhqK0IwUVMrS2lHdDRORHY5eEVwYkxVQVJsd2czRXpaS2ozbzV2dUFKdXNjSTN4OWdZYgptZDZSVTl2NkVmRSs0NUMwb0FISlZFaTU0Qi9qVzhXK20vMXRmTFpTRVFLQmdRRFF6TUdVU3ZpaFZMR0tuTXgwCjdvTTAreVUyeHJ6bmljTHB2Y2R5LzI0QTg3NytweXhwMkRyR1dYV3ZJeE1PZnUwUWhva2VLZWEyeFVJWkttWksKVjBQVi9nUUEwdnZEWXJVekM0T1dGTk52MlhTOEYyWjhVRlI2QjFWb0ZPclF3VXFWZnEzUDg0KzNLZUYzb0U0NQpja2lUUUY0emI3R2srOHBrNk0vbDNIS0pCd0tCZ1FEQnVFTENiNXlKcXM1MlcvOWtLQ1gvZEVKNzY0NXFYMWxmCmdMQ0xvd25BWjlLQ004U1AxU0dlYVROU1hRMDNPTkxEYlJxN2FaRTgrVy9YSGZVNDZlcXNFYVlmTnZaczZPZkkKQ3RNcWNLSzlYMWNlV2p6QWowZTBuV1Jldjdvb1BENGZpck1scEs1RGoyK2RDcHlEVGlGcnRQR3ZtWXROL3BHTgp0TFlJSWJFaXd3S0JnQ1UwdHpIVGdpWk5UeTJoN3hUUEEzWkhZa1EyZWFiUWQzanJKa1VwbXRKMG5JNEgvL1FFClljVENZQ1FMSGZReFRkRHFDRGpsd29UQzlacENZZVBSVlBjbXdsUGJSSjEyVTA5N044RmdpS1NmblJ0L0YvWUMKNG1xMEw5WFNGRjJLYzkzYnF1RXBSMnlkKzkwekpYMDdEZytmSXFvTHR4M3MrQTJ2Sm95UkVaKzFBb0dBSmtYVgpTcnpxWEhpV21lUExMV3FSTjBzczUzYStpRjJXTnJ3aUpUUnM5TXFPV0pNSnZyRUpGMWNKZ0xoSnFDTmQ0S1pwCnBhVlJ3STQzZm5TNHdpblU1M0lGTkIyVHlpaXB3bWdCR0Yxd2lhR1FnTHFyVGhBQXhycGgzaVpiRFIvNTFobDkKRTI3Wnp4ZERvZTg2eE9abXkvVFAyeldteEI0TGU4ZThQeGNJL0NrQ2dZQU1YRERGOUF1L1hkcXRnLzcyTlJoSgpjd05hakErcU4wMDcvQ2NrdUwwaDRxNjY4NmRpOXAxQ0Z5Y1kvRFZvS3JCViszaklSbWdZUU5wQ3ovZEdUa0xrCkhJZWJaaTZJS2lodFNnWEhISE1VcENyTUp1c1VtaS9kUzMybzBvTGFBZ3QweEx2bTJZcFdnNVhvOG9IY0dGZzAKblZya0laQlRBUnpEV3dwZERma2pCQT09Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K")
+)
diff --git a/certServiceK8sExternalProvider/src/cmpv2provisioner/testdata/test_private_key.pem b/certServiceK8sExternalProvider/src/cmpv2provisioner/testdata/test_private_key.pem
new file mode 100644
index 00000000..099593f9
--- /dev/null
+++ b/certServiceK8sExternalProvider/src/cmpv2provisioner/testdata/test_private_key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCeAKePTza3B9+Q
+5wmjwAmIU18mDsNmiI01W/nY3nwAi5RyOZyU2Nm6nUyqB44Wb+g/2sjz5zVcVBp/
+cF+hnrbmwb8M4R2ImRyj3Em3huPq0oOuMqPP4YG0JJG7IzMDpL8r4HwR+mFJZUo+
+XiAbHcirEyGe5cPN645xbuZTzzMgvQ0etMn3p7OT4hUc5GO5XTeBInYrEAMmKPhw
+2vOj+V/0to+euQ+QKO5poTWK3k8UOlx/QFTXUXC+CVs5ahDNPX6Gbw6h9v0kROG8
+bRZO4Hhk+NnygT5Lx8ErtMOacmFF1/yqSU5ehoMWGhqfcLzzFshRcwpsYBwDNq02
+VHDGSE5VAgMBAAECggEAfvAvricJ4kplBtlXGUOzZN72VnEN81ZJfFEEjYNRRG7f
+OFWowrzlT9QIP6IKOWR2xrZTNADREfhPwYraidIlR4boosRJIfFA3TSh1Nx+R64R
+NOZiTSTzO3MV0a8Z0ReOrwWPKDJr7rd9ylV8ncxz511baXlWsh1JN0DNsw+IGAgH
+G2pzauF08SFK5SUCXG0a+id924zKiC2ko2p1RFyKuqbXEduyGaASBx7pUKgUhUO8
+Z820CnK0xb/Jnxj+B0QS+KiGt4NDv9xEpbLUARlwg3EzZKj3o5vuAJuscI3x9gYb
+md6RU9v6EfE+45C0oAHJVEi54B/jW8W+m/1tfLZSEQKBgQDQzMGUSvihVLGKnMx0
+7oM0+yU2xrznicLpvcdy/24A877+pyxp2DrGWXWvIxMOfu0QhokeKea2xUIZKmZK
+V0PV/gQA0vvDYrUzC4OWFNNv2XS8F2Z8UFR6B1VoFOrQwUqVfq3P84+3KeF3oE45
+ckiTQF4zb7Gk+8pk6M/l3HKJBwKBgQDBuELCb5yJqs52W/9kKCX/dEJ7645qX1lf
+gLCLownAZ9KCM8SP1SGeaTNSXQ03ONLDbRq7aZE8+W/XHfU46eqsEaYfNvZs6OfI
+CtMqcKK9X1ceWjzAj0e0nWRev7ooPD4firMlpK5Dj2+dCpyDTiFrtPGvmYtN/pGN
+tLYIIbEiwwKBgCU0tzHTgiZNTy2h7xTPA3ZHYkQ2eabQd3jrJkUpmtJ0nI4H//QE
+YcTCYCQLHfQxTdDqCDjlwoTC9ZpCYePRVPcmwlPbRJ12U097N8FgiKSfnRt/F/YC
+4mq0L9XSFF2Kc93bquEpR2yd+90zJX07Dg+fIqoLtx3s+A2vJoyREZ+1AoGAJkXV
+SrzqXHiWmePLLWqRN0ss53a+iF2WNrwiJTRs9MqOWJMJvrEJF1cJgLhJqCNd4KZp
+paVRwI43fnS4winU53IFNB2TyiipwmgBGF1wiaGQgLqrThAAxrph3iZbDR/51hl9
+E27ZzxdDoe86xOZmy/TP2zWmxB4Le8e8PxcI/CkCgYAMXDDF9Au/Xdqtg/72NRhJ
+cwNajA+qN007/CckuL0h4q6686di9p1CFycY/DVoKrBV+3jIRmgYQNpCz/dGTkLk
+HIebZi6IKihtSgXHHHMUpCrMJusUmi/dS32o0oLaAgt0xLvm2YpWg5Xo8oHcGFg0
+nVrkIZBTARzDWwpdDfkjBA==
+-----END PRIVATE KEY-----
diff --git a/certServiceK8sExternalProvider/src/testdata/provider.go b/certServiceK8sExternalProvider/src/testdata/provider.go
new file mode 100644
index 00000000..2e352cbf
--- /dev/null
+++ b/certServiceK8sExternalProvider/src/testdata/provider.go
@@ -0,0 +1,89 @@
+/*
+ * ============LICENSE_START=======================================================
+ * oom-certservice-k8s-external-provider
+ * ================================================================================
+ * Copyright (C) 2020 Nokia. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package testdata
+
+import (
+ "k8s.io/api/core/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+ "onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
+)
+
+const (
+ SecretName = "issuer-cert-secret"
+ Url = "https://oom-cert-service:8443/v1/certificate/"
+ HealthEndpoint = "actuator/health"
+ CertEndpoint = "v1/certificate"
+ CaName = "RA"
+ KeySecretKey = "cmpv2Issuer-key.pem"
+ CertSecretKey = "cmpv2Issuer-cert.pem"
+ CacertSecretKey = "cacert.pem"
+ Namespace = "default"
+ IssuerObjectName = "fakeIssuer"
+ Kind = "CMPv2Issuer"
+ APIVersion = "v1"
+)
+
+func GetValidIssuerWithSecret() (cmpv2api.CMPv2Issuer, v1.Secret) {
+ issuer := cmpv2api.CMPv2Issuer{
+
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: APIVersion,
+ Kind: Kind,
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: IssuerObjectName,
+ Namespace: Namespace,
+ },
+ Spec: GetValidCMPv2IssuerSpec(),
+ }
+ secret := v1.Secret{
+
+ Data: map[string][]byte{
+ KeySecretKey: KeyBytes,
+ CertSecretKey: CertBytes,
+ CacertSecretKey: CacertBytes,
+ },
+ ObjectMeta: metav1.ObjectMeta{
+ Name: SecretName,
+ Namespace: Namespace,
+ },
+ }
+ secret.Name = SecretName
+ return issuer, secret
+}
+
+func GetValidCMPv2IssuerSpec() cmpv2api.CMPv2IssuerSpec {
+ issuerSpec := cmpv2api.CMPv2IssuerSpec{
+ URL: Url,
+ HealthEndpoint: HealthEndpoint,
+ CertEndpoint: CertEndpoint,
+ CaName: CaName,
+ CertSecretRef: cmpv2api.SecretKeySelector{
+ Name: SecretName,
+ KeyRef: KeySecretKey,
+ CertRef: CertSecretKey,
+ CacertRef: CacertSecretKey,
+ },
+ }
+ return issuerSpec
+}
+
diff --git a/certServiceK8sExternalProvider/src/x509/testdata/test_data.go b/certServiceK8sExternalProvider/src/x509/testdata/test_data.go
index dad5d094..b45d6102 100644
--- a/certServiceK8sExternalProvider/src/x509/testdata/test_data.go
+++ b/certServiceK8sExternalProvider/src/x509/testdata/test_data.go
@@ -20,8 +20,8 @@
package testdata
-
-const ValidCertificateSignRequest = (`-----BEGIN CERTIFICATE REQUEST-----
+const (
+ ValidCertificateSignRequest = `-----BEGIN CERTIFICATE REQUEST-----
MIIDgjCCAmoCAQAwgaQxCzAJBgNVBAYTAlBMMRMwEQYDVQQIEwpEb2xueVNsYXNr
MRAwDgYDVQQHEwdXcm9jbGF3MREwDwYDVQQJEwhMb3RuaWN6YTEPMA0GA1UEERMG
MTItMzQ1MQ0wCwYDVQQKEwRPTkFQMQ0wCwYDVQQLEwRvbmFwMRwwGgYDVQQDExNj
@@ -41,9 +41,8 @@ dnjRRFio75nCNRJdLOJ9FU3wIgdDZwGaiXdn5NDQxCe0BWcbElDJSYR/xOi7V0AM
bcm17a8owa5dH9u/rmTmlrIT7PV4JHkZIogctIcSqod6xdr1mbi8G9DMFAqV+o7W
9kV7XDKhTqYoBIsXwfehNMu3lo72VuklIyVNiEVz4mVzpeZy2DgjRjCLt106yDHZ
f3nco6O4y2EyexBVKq6QRFfZDUab6YcoEVvPAio01RmFrHgnxHs=
------END CERTIFICATE REQUEST-----`)
-
-const InvalidCertificateSignRequest = (`-----BEGIN INVALID REQUEST-----
+-----END CERTIFICATE REQUEST-----`
+ InvalidCertificateSignRequest = `-----BEGIN INVALID REQUEST-----
MIIDgjCCAmoCAQAwgaQxCzAJBgNVBAYTAlBMMRMwEQYDVQQIEwpEb2xueVNsYXNr
MRAwDgYDVQQHEwdXcm9jbGF3MREwDwYDVQQJEwhMb3RuaWN6YTEPMA0GA1UEERMG
MTItMzQ1MQ0wCwYDVQQKEwRPTkFQMQ0wCwYDVQQLEwRvbmFwMRwwGgYDVQQDExNj
@@ -63,4 +62,61 @@ dnjRRFio75nCNRJdLOJ9FU3wIgdDZwGaiXdn5NDQxCe0BWcbElDJSYR/xOi7V0AM
bcm17a8owa5dH9u/rmTmlrIT7PV4JHkZIogctIcSqod6xdr1mbi8G9DMFAqV+o7W
9kV7XDKhTqYoBIsXwfehNMu3lo72VuklIyVNiEVz4mVzpeZy2DgjRjCLt106yDHZ
f3nco6O4y2EyexBVKq6QRFfZDUab6YcoEVvPAio01RmFrHgnxHs=
------END CERTIFICATE REQUEST-----`)
+-----END CERTIFICATE REQUEST-----`
+ ValidPrivateKey = `-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCeAKePTza3B9+Q
+5wmjwAmIU18mDsNmiI01W/nY3nwAi5RyOZyU2Nm6nUyqB44Wb+g/2sjz5zVcVBp/
+cF+hnrbmwb8M4R2ImRyj3Em3huPq0oOuMqPP4YG0JJG7IzMDpL8r4HwR+mFJZUo+
+XiAbHcirEyGe5cPN645xbuZTzzMgvQ0etMn3p7OT4hUc5GO5XTeBInYrEAMmKPhw
+2vOj+V/0to+euQ+QKO5poTWK3k8UOlx/QFTXUXC+CVs5ahDNPX6Gbw6h9v0kROG8
+bRZO4Hhk+NnygT5Lx8ErtMOacmFF1/yqSU5ehoMWGhqfcLzzFshRcwpsYBwDNq02
+VHDGSE5VAgMBAAECggEAfvAvricJ4kplBtlXGUOzZN72VnEN81ZJfFEEjYNRRG7f
+OFWowrzlT9QIP6IKOWR2xrZTNADREfhPwYraidIlR4boosRJIfFA3TSh1Nx+R64R
+NOZiTSTzO3MV0a8Z0ReOrwWPKDJr7rd9ylV8ncxz511baXlWsh1JN0DNsw+IGAgH
+G2pzauF08SFK5SUCXG0a+id924zKiC2ko2p1RFyKuqbXEduyGaASBx7pUKgUhUO8
+Z820CnK0xb/Jnxj+B0QS+KiGt4NDv9xEpbLUARlwg3EzZKj3o5vuAJuscI3x9gYb
+md6RU9v6EfE+45C0oAHJVEi54B/jW8W+m/1tfLZSEQKBgQDQzMGUSvihVLGKnMx0
+7oM0+yU2xrznicLpvcdy/24A877+pyxp2DrGWXWvIxMOfu0QhokeKea2xUIZKmZK
+V0PV/gQA0vvDYrUzC4OWFNNv2XS8F2Z8UFR6B1VoFOrQwUqVfq3P84+3KeF3oE45
+ckiTQF4zb7Gk+8pk6M/l3HKJBwKBgQDBuELCb5yJqs52W/9kKCX/dEJ7645qX1lf
+gLCLownAZ9KCM8SP1SGeaTNSXQ03ONLDbRq7aZE8+W/XHfU46eqsEaYfNvZs6OfI
+CtMqcKK9X1ceWjzAj0e0nWRev7ooPD4firMlpK5Dj2+dCpyDTiFrtPGvmYtN/pGN
+tLYIIbEiwwKBgCU0tzHTgiZNTy2h7xTPA3ZHYkQ2eabQd3jrJkUpmtJ0nI4H//QE
+YcTCYCQLHfQxTdDqCDjlwoTC9ZpCYePRVPcmwlPbRJ12U097N8FgiKSfnRt/F/YC
+4mq0L9XSFF2Kc93bquEpR2yd+90zJX07Dg+fIqoLtx3s+A2vJoyREZ+1AoGAJkXV
+SrzqXHiWmePLLWqRN0ss53a+iF2WNrwiJTRs9MqOWJMJvrEJF1cJgLhJqCNd4KZp
+paVRwI43fnS4winU53IFNB2TyiipwmgBGF1wiaGQgLqrThAAxrph3iZbDR/51hl9
+E27ZzxdDoe86xOZmy/TP2zWmxB4Le8e8PxcI/CkCgYAMXDDF9Au/Xdqtg/72NRhJ
+cwNajA+qN007/CckuL0h4q6686di9p1CFycY/DVoKrBV+3jIRmgYQNpCz/dGTkLk
+HIebZi6IKihtSgXHHHMUpCrMJusUmi/dS32o0oLaAgt0xLvm2YpWg5Xo8oHcGFg0
+nVrkIZBTARzDWwpdDfkjBA==
+-----END PRIVATE KEY-----`
+ InvalidPrivateKey = `-----BEGIN INVALID KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCeAKePTza3B9+Q
+5wmjwAmIU18mDsNmiI01W/nY3nwAi5RyOZyU2Nm6nUyqB44Wb+g/2sjz5zVcVBp/
+cF+hnrbmwb8M4R2ImRyj3Em3huPq0oOuMqPP4YG0JJG7IzMDpL8r4HwR+mFJZUo+
+XiAbHcirEyGe5cPN645xbuZTzzMgvQ0etMn3p7OT4hUc5GO5XTeBInYrEAMmKPhw
+2vOj+V/0to+euQ+QKO5poTWK3k8UOlx/QFTXUXC+CVs5ahDNPX6Gbw6h9v0kROG8
+bRZO4Hhk+NnygT5Lx8ErtMOacmFF1/yqSU5ehoMWGhqfcLzzFshRcwpsYBwDNq02
+VHDGSE5VAgMBAAECggEAfvAvricJ4kplBtlXGUOzZN72VnEN81ZJfFEEjYNRRG7f
+OFWowrzlT9QIP6IKOWR2xrZTNADREfhPwYraidIlR4boosRJIfFA3TSh1Nx+R64R
+NOZiTSTzO3MV0a8Z0ReOrwWPKDJr7rd9ylV8ncxz511baXlWsh1JN0DNsw+IGAgH
+G2pzauF08SFK5SUCXG0a+id924zKiC2ko2p1RFyKuqbXEduyGaASBx7pUKgUhUO8
+Z820CnK0xb/Jnxj+B0QS+KiGt4NDv9xEpbLUARlwg3EzZKj3o5vuAJuscI3x9gYb
+md6RU9v6EfE+45C0oAHJVEi54B/jW8W+m/1tfLZSEQKBgQDQzMGUSvihVLGKnMx0
+7oM0+yU2xrznicLpvcdy/24A877+pyxp2DrGWXWvIxMOfu0QhokeKea2xUIZKmZK
+V0PV/gQA0vvDYrUzC4OWFNNv2XS8F2Z8UFR6B1VoFOrQwUqVfq3P84+3KeF3oE45
+ckiTQF4zb7Gk+8pk6M/l3HKJBwKBgQDBuELCb5yJqs52W/9kKCX/dEJ7645qX1lf
+gLCLownAZ9KCM8SP1SGeaTNSXQ03ONLDbRq7aZE8+W/XHfU46eqsEaYfNvZs6OfI
+CtMqcKK9X1ceWjzAj0e0nWRev7ooPD4firMlpK5Dj2+dCpyDTiFrtPGvmYtN/pGN
+tLYIIbEiwwKBgCU0tzHTgiZNTy2h7xTPA3ZHYkQ2eabQd3jrJkUpmtJ0nI4H//QE
+YcTCYCQLHfQxTdDqCDjlwoTC9ZpCYePRVPcmwlPbRJ12U097N8FgiKSfnRt/F/YC
+4mq0L9XSFF2Kc93bquEpR2yd+90zJX07Dg+fIqoLtx3s+A2vJoyREZ+1AoGAJkXV
+SrzqXHiWmePLLWqRN0ss53a+iF2WNrwiJTRs9MqOWJMJvrEJF1cJgLhJqCNd4KZp
+paVRwI43fnS4winU53IFNB2TyiipwmgBGF1wiaGQgLqrThAAxrph3iZbDR/51hl9
+E27ZzxdDoe86xOZmy/TP2zWmxB4Le8e8PxcI/CkCgYAMXDDF9Au/Xdqtg/72NRhJ
+cwNajA+qN007/CckuL0h4q6686di9p1CFycY/DVoKrBV+3jIRmgYQNpCz/dGTkLk
+HIebZi6IKihtSgXHHHMUpCrMJusUmi/dS32o0oLaAgt0xLvm2YpWg5Xo8oHcGFg0
+nVrkIZBTARzDWwpdDfkjBA==
+-----END PRIVATE KEY-----`
+)
diff --git a/certServiceK8sExternalProvider/src/x509/x509_utils.go b/certServiceK8sExternalProvider/src/x509/x509_utils.go
index b2530132..e1e887f0 100644
--- a/certServiceK8sExternalProvider/src/x509/x509_utils.go
+++ b/certServiceK8sExternalProvider/src/x509/x509_utils.go
@@ -27,14 +27,16 @@ import (
"fmt"
)
-// decodeCSR decodes a certificate request in PEM format and returns the
+const (
+ PemCsrType = "CERTIFICATE REQUEST"
+ pemPrivateKeyType = "PRIVATE KEY"
+)
+
+// decodeCSR decodes a certificate request in PEM format
func DecodeCSR(data []byte) (*x509.CertificateRequest, error) {
- block, rest := pem.Decode(data)
- if block == nil || len(rest) > 0 {
- return nil, fmt.Errorf("unexpected CSR PEM on sign request")
- }
- if block.Type != "CERTIFICATE REQUEST" {
- return nil, fmt.Errorf("PEM is not a certificate request")
+ block, err := decodePemBlock(data, PemCsrType)
+ if err != nil {
+ return nil, fmt.Errorf("error decoding CSR PEM: %v", err)
}
csr, err := x509.ParseCertificateRequest(block.Bytes)
if err != nil {
@@ -46,16 +48,30 @@ func DecodeCSR(data []byte) (*x509.CertificateRequest, error) {
return csr, nil
}
-// encodeX509 will encode a *x509.Certificate into PEM format.
-func EncodeX509(cert *x509.Certificate) ([]byte, error) {
- caPem := bytes.NewBuffer([]byte{})
- err := pem.Encode(caPem, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})
+func DecodePrivateKey(data []byte) (interface{}, error) {
+ block, err := decodePemBlock(data, pemPrivateKeyType)
+ if err != nil {
+ return nil, fmt.Errorf("error decoding Private Key PEM: %v", err)
+ }
+ key, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("error parsing Private Key: %v", err)
}
- return caPem.Bytes(), nil
+ return key, nil
}
+func decodePemBlock(data []byte, pemType string) (*pem.Block, error) {
+ block, rest := pem.Decode(data)
+ if block == nil || len(rest) > 0 {
+ return nil, fmt.Errorf("unexpected PEM")
+ }
+ if block.Type != pemType {
+ return nil, fmt.Errorf("PEM is not: %s", pemType)
+ }
+ return block, nil
+}
+
+
func ParseCertificateArrayToBytes(certificateArray []string) ([]byte, error) {
buffer := bytes.NewBuffer([]byte{})
for _, cert := range certificateArray {
diff --git a/certServiceK8sExternalProvider/src/x509/x509_utils_test.go b/certServiceK8sExternalProvider/src/x509/x509_utils_test.go
index 2692bf4e..c867d2e8 100644
--- a/certServiceK8sExternalProvider/src/x509/x509_utils_test.go
+++ b/certServiceK8sExternalProvider/src/x509/x509_utils_test.go
@@ -28,15 +28,28 @@ import (
"onap.org/oom-certservice/k8s-external-provider/src/x509/testdata"
)
-func TestShouldDecodeCSR(t *testing.T) {
+func Test_DecodeCSR_ShouldDecodeValidCsr(t *testing.T) {
csr, err := DecodeCSR([]byte(testdata.ValidCertificateSignRequest))
assert.Nil(t, err)
assert.Equal(t, "ONAP", csr.Subject.Organization[0])
}
-func TestShouldReturnError(t *testing.T) {
+func Test_DecodeCSR_ShouldReturnErrorForInvalidCsr(t *testing.T) {
_, err := DecodeCSR([]byte(testdata.InvalidCertificateSignRequest))
- assert.NotNil(t, err)
+ assert.Error(t, err)
+}
+
+func Test_DecodePrivateKey_ShouldDecodeValidPrivateKey(t *testing.T) {
+ privateKey, err := DecodePrivateKey([]byte(testdata.ValidPrivateKey))
+
+ assert.Nil(t, err)
+ assert.NotNil(t, privateKey)
+}
+
+func Test_DecodePrivateKey_ShouldReturnErrorForInvalidPrivateKey(t *testing.T) {
+ _, err := DecodePrivateKey([]byte(testdata.InvalidPrivateKey))
+
+ assert.Error(t, err)
}