aboutsummaryrefslogtreecommitdiffstats
path: root/certServiceK8sExternalProvider
diff options
context:
space:
mode:
authorRemigiusz Janeczek <remigiusz.janeczek@nokia.com>2020-10-16 11:08:09 +0200
committerRemigiusz Janeczek <remigiusz.janeczek@nokia.com>2020-10-20 13:21:33 +0200
commitf85be7d76bf73d59dd4d70ffd07f1e34dfd1a2ef (patch)
treedc877e4ed72e9eaf86c94659cd34332e147c3d8b /certServiceK8sExternalProvider
parent311cb14d51f5f9b81c5761d815d5d7a5f9b63817 (diff)
[OOM-K8S-CERT-EXTERNAL-PROVIDER] Provide certs to CMPv2 Issuer
Format code Issue-ID: OOM-2559 Signed-off-by: Remigiusz Janeczek <remigiusz.janeczek@nokia.com> Change-Id: I88346b96657606b010aa8d7da0f8b86d1844f9d7
Diffstat (limited to 'certServiceK8sExternalProvider')
-rw-r--r--certServiceK8sExternalProvider/README.md10
-rw-r--r--certServiceK8sExternalProvider/deploy/configuration.yaml11
-rw-r--r--certServiceK8sExternalProvider/deploy/crd.yaml36
-rw-r--r--certServiceK8sExternalProvider/main.go12
-rw-r--r--certServiceK8sExternalProvider/main_test.go9
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2api/cmpv2_groupversion_info.go1
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2api/cmpv2_groupversion_info_test.go2
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2api/cmpv2_issuer_crd_deepcopy.go2
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2api/cmpv2_issuer_crd_schema.go15
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2controller/certificate_request_controller.go10
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2controller/certificate_request_controller_test.go6
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller.go54
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller_test.go67
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_status_updater.go2
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2controller/status_reason.go6
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner.go23
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory.go55
-rw-r--r--certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory_test.go120
-rw-r--r--certServiceK8sExternalProvider/src/exit_code.go6
-rw-r--r--certServiceK8sExternalProvider/src/exit_code_test.go1
20 files changed, 341 insertions, 107 deletions
diff --git a/certServiceK8sExternalProvider/README.md b/certServiceK8sExternalProvider/README.md
index 57ca5930..3fc00f90 100644
--- a/certServiceK8sExternalProvider/README.md
+++ b/certServiceK8sExternalProvider/README.md
@@ -9,13 +9,21 @@ There are two methods for building the project:
### Installation
+Create secret with certificates for communication between CMPv2Issuer and Cert Service API:
+```
+kubectl create secret generic -n onap cmpv2-issuer-secret --from-file=<project-base-dir>/certs/cmpv2Issuer-key.pem
+ --from-file=<project-base-dir>/certs/cmpv2Issuer-cert.pem --from-file=<project-base-dir>/certs/cacert.pem
+```
+
Apply k8s files from 'deploy' directory in following order:
- crd.yaml
- roles.yaml
- deployment.yaml
- - configuration.yaml
+ - configuration.yaml (certRef, keyRef and cacertRef should match file names if secret was created with command listed
+ above)
+**Note:** Files and installation are currently examples, which should be used as a guide for OOM Helm Charts implementation
### Usage
diff --git a/certServiceK8sExternalProvider/deploy/configuration.yaml b/certServiceK8sExternalProvider/deploy/configuration.yaml
index 95c38d75..4a0f2dc6 100644
--- a/certServiceK8sExternalProvider/deploy/configuration.yaml
+++ b/certServiceK8sExternalProvider/deploy/configuration.yaml
@@ -28,7 +28,10 @@ metadata:
name: cmpv2-issuer
namespace: onap
spec:
- url: https://certservice.default.svc.cluster.local
- keyRef:
- name: certservice-key
- key: key
+ url: https://oom-cert-service:8443/v1/certificate/
+ caName: RA
+ certSecretRef:
+ name: cmpv2-issuer-secret
+ certRef: cmpv2Issuer-cert.pem
+ keyRef: cmpv2Issuer-key.pem
+ cacertRef: cacert.pem
diff --git a/certServiceK8sExternalProvider/deploy/crd.yaml b/certServiceK8sExternalProvider/deploy/crd.yaml
index 1d45b0c9..cc884388 100644
--- a/certServiceK8sExternalProvider/deploy/crd.yaml
+++ b/certServiceK8sExternalProvider/deploy/crd.yaml
@@ -58,27 +58,41 @@ spec:
description: CMPv2IssuerSpec defines the desired state of CMPv2Issuer
properties:
url:
- description: URL is the base URL for the certservice certificates instance.
+ description: URL to CertService API.
type: string
- keyRef:
- description: keyRef is a reference to a Secret containing the
- cmpv2provisioner password used to decrypt the cmpv2provisioner private key.
+ caName:
+ description: Name of the external CA server configured on CertService API side.
+ type: string
+ certSecretRef:
+ description: Reference to K8s secret which contains certificate, private key and CA certificate
+ needed to connect to CertService API (which requires client certificate authentication)
properties:
- key:
- description: The key of the secret to select from. Must be a
+ name:
+ description: The name of K8s secret to select certificates from. Secret must be in the same
+ namespace as CMPv2Issuer.
+ type: string
+ keyRef:
+ description: The key of the secret to select private key from. Must be a
valid secret key.
type: string
- name:
- description: The name of the secret in the pod's namespace to
- select from.
+ certRef:
+ description: The key of the secret to select cert from. Must be a
+ valid secret key.
+ type: string
+ cacertRef:
+ description: The key of the secret to select cacert from. Must be a
+ valid secret key.
type: string
required:
- name
- - key
+ - keyRef
+ - certRef
+ - cacertRef
type: object
required:
- url
- - keyRef
+ - caName
+ - certSecretRef
type: object
status:
description: CMPv2IssuerStatus defines the observed state of CMPv2Issuer
diff --git a/certServiceK8sExternalProvider/main.go b/certServiceK8sExternalProvider/main.go
index 8e5d36cb..57058e9e 100644
--- a/certServiceK8sExternalProvider/main.go
+++ b/certServiceK8sExternalProvider/main.go
@@ -28,18 +28,20 @@ package main
import (
"flag"
"fmt"
+ "os"
+
certmanager "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"k8s.io/utils/clock"
- app "onap.org/oom-certservice/k8s-external-provider/src"
- certserviceapi "onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
- controllers "onap.org/oom-certservice/k8s-external-provider/src/cmpv2controller"
- "os"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/controller-runtime/pkg/manager"
+
+ app "onap.org/oom-certservice/k8s-external-provider/src"
+ certserviceapi "onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
+ controllers "onap.org/oom-certservice/k8s-external-provider/src/cmpv2controller"
)
var (
@@ -107,7 +109,7 @@ func createControllerManager(metricsAddr string, enableLeaderElection bool) mana
return manager
}
-func registerCMPv2IssuerController(manager manager.Manager) {
+func registerCMPv2IssuerController(manager manager.Manager) {
setupLog.Info("Registering CMPv2IssuerController...")
err := (&controllers.CMPv2IssuerController{
diff --git a/certServiceK8sExternalProvider/main_test.go b/certServiceK8sExternalProvider/main_test.go
index d74fe0d3..0ad70246 100644
--- a/certServiceK8sExternalProvider/main_test.go
+++ b/certServiceK8sExternalProvider/main_test.go
@@ -21,14 +21,15 @@
package main
import (
+ "flag"
"os"
"testing"
+
"github.com/stretchr/testify/assert"
- "flag"
)
func Test_shouldParseArguments_defaultValues(t *testing.T) {
- os.Args = []string {
+ os.Args = []string{
"first-arg-is-omitted-by-method-parse-arguments-so-this-only-a-placeholder"}
flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError)
@@ -39,10 +40,10 @@ func Test_shouldParseArguments_defaultValues(t *testing.T) {
}
func Test_shouldParseArguments_valuesFromCLI(t *testing.T) {
- os.Args = []string {
+ os.Args = []string{
"first-arg-is-omitted-by-method-parse-arguments-so-this-only-a-placeholder",
"--metrics-addr=127.0.0.1:555",
- "--enable-leader-election=true" }
+ "--enable-leader-election=true"}
flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError)
metricsAddr, enableLeaderElection := parseInputArguments()
diff --git a/certServiceK8sExternalProvider/src/cmpv2api/cmpv2_groupversion_info.go b/certServiceK8sExternalProvider/src/cmpv2api/cmpv2_groupversion_info.go
index 996cf21a..ec4d6835 100644
--- a/certServiceK8sExternalProvider/src/cmpv2api/cmpv2_groupversion_info.go
+++ b/certServiceK8sExternalProvider/src/cmpv2api/cmpv2_groupversion_info.go
@@ -42,4 +42,3 @@ var (
)
const CMPv2IssuerKind = "CMPv2Issuer"
-
diff --git a/certServiceK8sExternalProvider/src/cmpv2api/cmpv2_groupversion_info_test.go b/certServiceK8sExternalProvider/src/cmpv2api/cmpv2_groupversion_info_test.go
index b95bded5..eae6a2c8 100644
--- a/certServiceK8sExternalProvider/src/cmpv2api/cmpv2_groupversion_info_test.go
+++ b/certServiceK8sExternalProvider/src/cmpv2api/cmpv2_groupversion_info_test.go
@@ -22,6 +22,7 @@ package cmpv2api
import (
"testing"
+
"github.com/stretchr/testify/assert"
)
@@ -33,4 +34,3 @@ func Test_shouldHaveRightGroupVersion(t *testing.T) {
func Test_shouldRightIssuerKind(t *testing.T) {
assert.Equal(t, "CMPv2Issuer", CMPv2IssuerKind)
}
-
diff --git a/certServiceK8sExternalProvider/src/cmpv2api/cmpv2_issuer_crd_deepcopy.go b/certServiceK8sExternalProvider/src/cmpv2api/cmpv2_issuer_crd_deepcopy.go
index 68e79ce1..83785ab9 100644
--- a/certServiceK8sExternalProvider/src/cmpv2api/cmpv2_issuer_crd_deepcopy.go
+++ b/certServiceK8sExternalProvider/src/cmpv2api/cmpv2_issuer_crd_deepcopy.go
@@ -125,7 +125,7 @@ func (inputIssuerList *CMPv2IssuerList) DeepCopyObject() runtime.Object {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (inputIssuerSpec *CMPv2IssuerSpec) DeepCopyInto(outIssuerSpec *CMPv2IssuerSpec) {
*outIssuerSpec = *inputIssuerSpec
- outIssuerSpec.KeyRef = inputIssuerSpec.KeyRef
+ outIssuerSpec.CertSecretRef = inputIssuerSpec.CertSecretRef
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CMPv2IssuerSpec.
diff --git a/certServiceK8sExternalProvider/src/cmpv2api/cmpv2_issuer_crd_schema.go b/certServiceK8sExternalProvider/src/cmpv2api/cmpv2_issuer_crd_schema.go
index f2482657..f26dc876 100644
--- a/certServiceK8sExternalProvider/src/cmpv2api/cmpv2_issuer_crd_schema.go
+++ b/certServiceK8sExternalProvider/src/cmpv2api/cmpv2_issuer_crd_schema.go
@@ -37,10 +37,10 @@ func init() {
type CMPv2IssuerSpec struct {
// URL is the base URL for the CertService certificates instance.
URL string `json:"url"`
-
+ // CaName is the name of the external CA server
+ CaName string `json:"caName"`
// KeyRef is a reference to a Secret containing the provisioner
- // password used to decrypt the provisioner private key.
- KeyRef SecretKeySelector `json:"keyRef"`
+ CertSecretRef SecretKeySelector `json:"certSecretRef"`
}
// CMPv2IssuerStatus defines the observed state of CMPv2Issuer
@@ -72,9 +72,12 @@ type SecretKeySelector struct {
// The name of the secret in the pod's namespace to select from.
Name string `json:"name"`
- // The key of the secret to select from. Must be a valid secret key.
- // +optional
- Key string `json:"key,omitempty"`
+ // The key of the secret to select private key from. Must be a valid secret key.
+ KeyRef string `json:"keyRef,omitempty"`
+ // The key of the secret to select cert from. Must be a valid secret key.
+ CertRef string `json:"certRef,omitempty"`
+ // The key of the secret to select cacert from. Must be a valid secret key.
+ CacertRef string `json:"cacertRef,omitempty"`
}
// ConditionType represents a CMPv2Issuer condition type.
diff --git a/certServiceK8sExternalProvider/src/cmpv2controller/certificate_request_controller.go b/certServiceK8sExternalProvider/src/cmpv2controller/certificate_request_controller.go
index 38b5cdf3..54b4b103 100644
--- a/certServiceK8sExternalProvider/src/cmpv2controller/certificate_request_controller.go
+++ b/certServiceK8sExternalProvider/src/cmpv2controller/certificate_request_controller.go
@@ -28,8 +28,6 @@ package cmpv2controller
import (
"context"
"fmt"
- "onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
- provisioners "onap.org/oom-certservice/k8s-external-provider/src/cmpv2provisioner"
"github.com/go-logr/logr"
apiutil "github.com/jetstack/cert-manager/pkg/api/util"
@@ -41,6 +39,9 @@ import (
"k8s.io/client-go/tools/record"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
+
+ "onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
+ provisioners "onap.org/oom-certservice/k8s-external-provider/src/cmpv2provisioner"
)
// CertificateRequestController reconciles a CMPv2Issuer object.
@@ -144,7 +145,6 @@ func (controller *CertificateRequestController) setStatus(ctx context.Context, c
return controller.Client.Status().Update(ctx, certificateRequest)
}
-
func isCMPv2IssuerReady(issuer cmpv2api.CMPv2Issuer) bool {
condition := cmpv2api.CMPv2IssuerCondition{Type: cmpv2api.ConditionReady, Status: cmpv2api.ConditionTrue}
return hasCondition(issuer, condition)
@@ -183,12 +183,12 @@ func (controller *CertificateRequestController) handleErrorCMPv2IssuerIsNotReady
return err
}
-func (controller *CertificateRequestController) handleErrorGettingCMPv2Issuer(ctx context.Context, log logr.Logger, err error, certificateRequest *cmapi.CertificateRequest, issuerNamespaceName types.NamespacedName, req ctrl.Request) {
+func (controller *CertificateRequestController) handleErrorGettingCMPv2Issuer(ctx context.Context, log logr.Logger, err error, certificateRequest *cmapi.CertificateRequest, issuerNamespaceName types.NamespacedName, req ctrl.Request) {
log.Error(err, "Failed to retrieve CMPv2Issuer resource", "namespace", req.Namespace, "name", certificateRequest.Spec.IssuerRef.Name)
_ = controller.setStatus(ctx, certificateRequest, cmmeta.ConditionFalse, cmapi.CertificateRequestReasonPending, "Failed to retrieve CMPv2Issuer resource %s: %v", issuerNamespaceName, err)
}
-func (controller *CertificateRequestController) handleErrorFailedToSignCertificate(ctx context.Context, log logr.Logger, err error, certificateRequest *cmapi.CertificateRequest) {
+func (controller *CertificateRequestController) handleErrorFailedToSignCertificate(ctx context.Context, log logr.Logger, err error, certificateRequest *cmapi.CertificateRequest) {
log.Error(err, "Failed to sign certificate request")
_ = controller.setStatus(ctx, certificateRequest, cmmeta.ConditionFalse, cmapi.CertificateRequestReasonFailed, "Failed to sign certificate request: %v", err)
}
diff --git a/certServiceK8sExternalProvider/src/cmpv2controller/certificate_request_controller_test.go b/certServiceK8sExternalProvider/src/cmpv2controller/certificate_request_controller_test.go
index 7e55f36f..2c401cce 100644
--- a/certServiceK8sExternalProvider/src/cmpv2controller/certificate_request_controller_test.go
+++ b/certServiceK8sExternalProvider/src/cmpv2controller/certificate_request_controller_test.go
@@ -21,10 +21,10 @@
package cmpv2controller
import (
- cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
"testing"
- "github.com/stretchr/testify/assert"
+ cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
+ "github.com/stretchr/testify/assert"
)
const group = "certmanager.onap.org"
@@ -43,7 +43,6 @@ func Test_shouldBeInvalidCMPv2CertificateRequest_whenKindIsCertificateRequest(t
assert.False(t, isCMPv2CertificateRequest(request))
}
-
func Test_shouldBeValidCMPv2CertificateRequest_whenKindIsCMPvIssuer(t *testing.T) {
request := new(cmapi.CertificateRequest)
request.Spec.IssuerRef.Group = group
@@ -51,4 +50,3 @@ func Test_shouldBeValidCMPv2CertificateRequest_whenKindIsCMPvIssuer(t *testing.T
assert.True(t, isCMPv2CertificateRequest(request))
}
-
diff --git a/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller.go b/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller.go
index f57f5677..1b4e5312 100644
--- a/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller.go
+++ b/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller.go
@@ -28,6 +28,7 @@ package cmpv2controller
import (
"context"
"fmt"
+
"github.com/go-logr/logr"
core "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -35,10 +36,11 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/record"
"k8s.io/utils/clock"
- "onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
- provisioners "onap.org/oom-certservice/k8s-external-provider/src/cmpv2provisioner"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
+
+ "onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
+ provisioners "onap.org/oom-certservice/k8s-external-provider/src/cmpv2provisioner"
)
// CMPv2IssuerController reconciles a CMPv2Issuer object
@@ -74,21 +76,18 @@ func (controller *CMPv2IssuerController) Reconcile(req ctrl.Request) (ctrl.Resul
var secret core.Secret
secretNamespaceName := types.NamespacedName{
Namespace: req.Namespace,
- Name: issuer.Spec.KeyRef.Name,
+ Name: issuer.Spec.CertSecretRef.Name,
}
if err := controller.loadResource(ctx, secretNamespaceName, &secret); err != nil {
handleErrorInvalidSecret(ctx, log, err, statusUpdater, secretNamespaceName)
return ctrl.Result{}, err
}
- password, ok := secret.Data[issuer.Spec.KeyRef.Key]
- if !ok {
- err := handleErrorSecretNotFound(ctx, log, issuer, statusUpdater, secretNamespaceName, secret)
- return ctrl.Result{}, err
- }
// 4. Create CMPv2 provisioner and store the instance for further use
- provisioner, err := provisioners.New(issuer, password)
+ provisioner, err := provisioners.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)
handleErrorProvisionerInitialization(ctx, log, err, statusUpdater)
return ctrl.Result{}, err
}
@@ -103,7 +102,6 @@ func (controller *CMPv2IssuerController) Reconcile(req ctrl.Request) (ctrl.Resul
return ctrl.Result{}, nil
}
-
func (controller *CMPv2IssuerController) SetupWithManager(manager ctrl.Manager) error {
return ctrl.NewControllerManagedBy(manager).
For(&cmpv2api.CMPv2Issuer{}).
@@ -114,18 +112,22 @@ func (controller *CMPv2IssuerController) loadResource(ctx context.Context, key c
return controller.Client.Get(ctx, key, obj)
}
-
func validateCMPv2IssuerSpec(issuerSpec cmpv2api.CMPv2IssuerSpec, log logr.Logger) error {
switch {
- case issuerSpec.URL == "":
- return fmt.Errorf("spec.url cannot be empty")
- case issuerSpec.KeyRef.Name == "":
- return fmt.Errorf("spec.keyRef.name cannot be empty")
- case issuerSpec.KeyRef.Key == "":
- return fmt.Errorf("spec.keyRef.key cannot be empty")
- default:
- log.Info("CMPv2Issuer validated. ")
- return nil
+ case issuerSpec.URL == "":
+ return fmt.Errorf("spec.url cannot be empty")
+ case issuerSpec.CaName == "":
+ return fmt.Errorf("spec.caName cannot be empty")
+ case issuerSpec.CertSecretRef.Name == "":
+ return fmt.Errorf("spec.certSecretRef.name cannot be empty")
+ case issuerSpec.CertSecretRef.KeyRef == "":
+ return fmt.Errorf("spec.certSecretRef.keyRef cannot be empty")
+ case issuerSpec.CertSecretRef.CertRef == "":
+ return fmt.Errorf("spec.certSecretRef.certRef cannot be empty")
+ case issuerSpec.CertSecretRef.CacertRef == "":
+ return fmt.Errorf("spec.certSecretRef.cacertRef cannot be empty")
+ default:
+ return nil
}
}
@@ -134,22 +136,19 @@ func updateCMPv2IssuerStatusToVerified(statusUpdater *CMPv2IssuerStatusUpdater,
return statusUpdater.Update(ctx, cmpv2api.ConditionTrue, Verified, "CMPv2Issuer verified and ready to sign certificates")
}
-
// Error handling
func handleErrorUpdatingCMPv2IssuerStatus(log logr.Logger, err error) {
log.Error(err, "Failed to update CMPv2Issuer status")
}
-
func handleErrorLoadingCMPv2Issuer(log logr.Logger, err error) {
log.Error(err, "Failed to retrieve CMPv2Issuer resource")
}
-
func handleErrorProvisionerInitialization(ctx context.Context, log logr.Logger, err error, statusUpdater *CMPv2IssuerStatusUpdater) {
log.Error(err, "Failed to initialize provisioner")
- statusUpdater.UpdateNoError(ctx, cmpv2api.ConditionFalse, Error, "Failed initialize provisioner")
+ statusUpdater.UpdateNoError(ctx, cmpv2api.ConditionFalse, Error, "Failed to initialize provisioner: %v", err)
}
func handleErrorCMPv2IssuerValidation(ctx context.Context, log logr.Logger, err error, statusUpdater *CMPv2IssuerStatusUpdater) {
@@ -157,13 +156,6 @@ func handleErrorCMPv2IssuerValidation(ctx context.Context, log logr.Logger, err
statusUpdater.UpdateNoError(ctx, cmpv2api.ConditionFalse, ValidationFailed, "Failed to validate resource: %v", err)
}
-func handleErrorSecretNotFound(ctx context.Context, log logr.Logger, issuer *cmpv2api.CMPv2Issuer, statusUpdater *CMPv2IssuerStatusUpdater, secretNamespaceName types.NamespacedName, secret core.Secret) error {
- err := fmt.Errorf("secret %s does not contain key %s", secret.Name, issuer.Spec.KeyRef.Key)
- log.Error(err, "Failed to retrieve CMPv2Issuer provisioner secret", "namespace", secretNamespaceName.Namespace, "name", secretNamespaceName.Name)
- statusUpdater.UpdateNoError(ctx, cmpv2api.ConditionFalse, NotFound, "Failed to retrieve provisioner secret: %v", err)
- return err
-}
-
func handleErrorInvalidSecret(ctx context.Context, log logr.Logger, err error, statusUpdater *CMPv2IssuerStatusUpdater, secretNamespaceName types.NamespacedName) {
log.Error(err, "Failed to retrieve CMPv2Issuer provisioner secret", "namespace", secretNamespaceName.Namespace, "name", secretNamespaceName.Name)
if apierrors.IsNotFound(err) {
diff --git a/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller_test.go b/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller_test.go
index 8409ea78..79c78ed5 100644
--- a/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller_test.go
+++ b/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_controller_test.go
@@ -21,13 +21,22 @@
package cmpv2controller
import (
+ "testing"
+
"github.com/go-logr/logr"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
+
"onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
- "testing"
)
+func Test_shouldBeValidCMPv2IssuerSpec_whenAllFieldsAreSet(t *testing.T) {
+ spec := getValidCMPv2IssuerSpec()
+
+ err := validateCMPv2IssuerSpec(spec, &MockLogger{})
+ assert.Nil(t, err)
+}
+
func Test_shouldBeInvalidCMPv2IssuerSpec_whenSpecIsEmpty(t *testing.T) {
spec := cmpv2api.CMPv2IssuerSpec{}
err := validateCMPv2IssuerSpec(spec, nil)
@@ -35,32 +44,50 @@ func Test_shouldBeInvalidCMPv2IssuerSpec_whenSpecIsEmpty(t *testing.T) {
}
func Test_shouldBeInvalidCMPv2IssuerSpec_whenNotAllFieldsAreSet(t *testing.T) {
- spec := cmpv2api.CMPv2IssuerSpec{}
- spec.URL = "https://localhost"
- spec.KeyRef = cmpv2api.SecretKeySelector{}
- spec.KeyRef.Name = "secret-key"
+ setEmptyFieldFunctions := map[string]func(spec *cmpv2api.CMPv2IssuerSpec){
+ "emptyUrl": func(spec *cmpv2api.CMPv2IssuerSpec) { spec.URL = "" },
+ "empryCaName": func(spec *cmpv2api.CMPv2IssuerSpec) { spec.CaName = "" },
+ "emptySecretName": func(spec *cmpv2api.CMPv2IssuerSpec) { spec.CertSecretRef.Name = "" },
+ "emptySecretKeyRef": func(spec *cmpv2api.CMPv2IssuerSpec) { spec.CertSecretRef.KeyRef = "" },
+ "emptySecretCertRef": func(spec *cmpv2api.CMPv2IssuerSpec) { spec.CertSecretRef.CertRef = "" },
+ "emptySecretCaertRef": func(spec *cmpv2api.CMPv2IssuerSpec) { spec.CertSecretRef.CacertRef = "" },
+ }
- err := validateCMPv2IssuerSpec(spec, &MockLogger{})
- assert.NotNil(t, err)
+ for caseName, setEmptyFieldFunction := range setEmptyFieldFunctions {
+ t.Run(caseName, func(t *testing.T) {
+ test_shouldBeInvalidCMPv2IssuerSpec_whenFunctionApplied(t, setEmptyFieldFunction)
+ })
+ }
}
-func Test_shouldBeValidCMPv2IssuerSpec_whenAllFieldsAreSet(t *testing.T) {
- spec := cmpv2api.CMPv2IssuerSpec{}
- spec.URL = "https://localhost"
- spec.KeyRef = cmpv2api.SecretKeySelector{}
- spec.KeyRef.Name = "secret-key"
- spec.KeyRef.Key = "the-key"
+func test_shouldBeInvalidCMPv2IssuerSpec_whenFunctionApplied(t *testing.T, transformSpec func(spec *cmpv2api.CMPv2IssuerSpec)) {
+ spec := getValidCMPv2IssuerSpec()
+ transformSpec(&spec)
+ err := validateCMPv2IssuerSpec(spec, nil)
+ assert.NotNil(t, err)
+}
- err := validateCMPv2IssuerSpec(spec, &MockLogger{})
- assert.Nil(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",
+ },
+ }
+ return issuerSpec
}
type MockLogger struct {
mock.Mock
}
-func (m *MockLogger) Info(msg string, keysAndValues ...interface{}) {}
+
+func (m *MockLogger) Info(msg string, keysAndValues ...interface{}) {}
func (m *MockLogger) Error(err error, msg string, keysAndValues ...interface{}) {}
-func (m *MockLogger) Enabled() bool { return false }
-func (m *MockLogger) V(level int) logr.Logger { return m }
-func (m *MockLogger) WithValues(keysAndValues ...interface{}) logr.Logger { return m }
-func (m *MockLogger) WithName(name string) logr.Logger { return m }
+func (m *MockLogger) Enabled() bool { return false }
+func (m *MockLogger) V(level int) logr.Logger { return m }
+func (m *MockLogger) WithValues(keysAndValues ...interface{}) logr.Logger { return m }
+func (m *MockLogger) WithName(name string) logr.Logger { return m }
diff --git a/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_status_updater.go b/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_status_updater.go
index 017e36a4..f07101db 100644
--- a/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_status_updater.go
+++ b/certServiceK8sExternalProvider/src/cmpv2controller/cmpv2_issuer_status_updater.go
@@ -28,9 +28,11 @@ package cmpv2controller
import (
"context"
"fmt"
+
"github.com/go-logr/logr"
core "k8s.io/api/core/v1"
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
+
"onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
)
diff --git a/certServiceK8sExternalProvider/src/cmpv2controller/status_reason.go b/certServiceK8sExternalProvider/src/cmpv2controller/status_reason.go
index d41712d3..fc1772e9 100644
--- a/certServiceK8sExternalProvider/src/cmpv2controller/status_reason.go
+++ b/certServiceK8sExternalProvider/src/cmpv2controller/status_reason.go
@@ -21,8 +21,8 @@
package cmpv2controller
const (
- NotFound = "NotFound"
+ NotFound = "NotFound"
ValidationFailed = "ValidationFailed"
- Error = "Error"
- Verified = "Verified"
+ Error = "Error"
+ Verified = "Verified"
)
diff --git a/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner.go b/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner.go
index a51b8425..e48b527d 100644
--- a/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner.go
+++ b/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner.go
@@ -32,30 +32,39 @@ import (
"encoding/base64"
"encoding/pem"
"fmt"
+ "sync"
+
certmanager "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
"k8s.io/apimachinery/pkg/types"
- "onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
ctrl "sigs.k8s.io/controller-runtime"
- "sync"
+
+ "onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
)
var collection = new(sync.Map)
type CertServiceCA struct {
- name string
- url string
- key []byte
+ name string
+ url string
+ caName string
+ key []byte
+ cert []byte
+ cacert []byte
}
-func New(cmpv2Issuer *cmpv2api.CMPv2Issuer, key []byte) (*CertServiceCA, error) {
+func New(cmpv2Issuer *cmpv2api.CMPv2Issuer, key []byte, cert []byte, cacert []byte) (*CertServiceCA, error) {
ca := CertServiceCA{}
ca.name = cmpv2Issuer.Name
ca.url = cmpv2Issuer.Spec.URL
+ ca.caName = cmpv2Issuer.Spec.CaName
ca.key = key
+ ca.cert = cert
+ ca.cacert = cacert
log := ctrl.Log.WithName("cmpv2-provisioner")
- log.Info("Configuring CA: ", "name", ca.name, "url", ca.url, "key", ca.key)
+ log.Info("Configuring CA: ", "name", ca.name, "url", ca.url, "caName", ca.caName, "key", ca.key,
+ "cert", ca.cert, "cacert", ca.cacert)
return &ca, nil
}
diff --git a/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory.go b/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory.go
new file mode 100644
index 00000000..4a3898e7
--- /dev/null
+++ b/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory.go
@@ -0,0 +1,55 @@
+/*
+ * ============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 (
+ "fmt"
+
+ v1 "k8s.io/api/core/v1"
+
+ "onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
+)
+
+func CreateProvisioner(issuer *cmpv2api.CMPv2Issuer, secret v1.Secret) (*CertServiceCA, error) {
+ secretKeys := issuer.Spec.CertSecretRef
+ key, err := readValueFromSecret(secret, secretKeys.KeyRef)
+ if err != nil {
+ return nil, err
+ }
+ cert, err := readValueFromSecret(secret, secretKeys.CertRef)
+ if err != nil {
+ return nil, err
+ }
+ cacert, err := readValueFromSecret(secret, secretKeys.CacertRef)
+ if err != nil {
+ return nil, err
+ }
+ return New(issuer, key, cert, cacert)
+}
+
+func readValueFromSecret(secret v1.Secret, secretKey string) ([]byte, error) {
+ value, ok := secret.Data[secretKey]
+ if !ok {
+ err := fmt.Errorf("secret %s does not contain key %s", secret.Name, secretKey)
+ return nil, err
+ }
+ return value, nil
+}
diff --git a/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory_test.go b/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory_test.go
new file mode 100644
index 00000000..6ef33098
--- /dev/null
+++ b/certServiceK8sExternalProvider/src/cmpv2provisioner/cmpv2_provisioner_factory_test.go
@@ -0,0 +1,120 @@
+/*
+ * ============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 (
+ "fmt"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ v1 "k8s.io/api/core/v1"
+
+ "onap.org/oom-certservice/k8s-external-provider/src/cmpv2api"
+)
+
+const (
+ secretName = "issuer-cert-secret"
+ url = "https://oom-cert-service:8443/v1/certificate/"
+ caName = "RA"
+ keySecretKey = "cmpv2Issuer-key.pem"
+ certSecretKey = "cmpv2Issuer-cert.pem"
+ cacertSecretKey = "cacert.pem"
+)
+
+var (
+ keySecretValue = []byte("keyData")
+ certSecretValue = []byte("certData")
+ cacertSecretValue = []byte("cacertData")
+)
+
+func Test_shouldCreateProvisioner(t *testing.T) {
+ issuer, secret := getValidIssuerAndSecret()
+
+ provisioner, _ := CreateProvisioner(&issuer, secret)
+
+ assert.NotNil(t, provisioner)
+ assert.Equal(t, url, provisioner.url)
+ assert.Equal(t, caName, provisioner.caName)
+ assert.Equal(t, keySecretValue, provisioner.key)
+ assert.Equal(t, certSecretValue, provisioner.cert)
+ assert.Equal(t, cacertSecretValue, provisioner.cacert)
+}
+
+func Test_shouldReturnError_whenSecretMissingKeyRef(t *testing.T) {
+ issuer, secret := getValidIssuerAndSecret()
+ delete(secret.Data, keySecretKey)
+
+ provisioner, err := 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)
+ }
+}
+
+func Test_shouldReturnError_whenSecretMissingCertRef(t *testing.T) {
+ issuer, secret := getValidIssuerAndSecret()
+ delete(secret.Data, certSecretKey)
+
+ provisioner, err := 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)
+ }
+}
+
+func Test_shouldReturnError_whenSecretMissingCacertRef(t *testing.T) {
+ issuer, secret := getValidIssuerAndSecret()
+ delete(secret.Data, cacertSecretKey)
+
+ provisioner, err := 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)
+ }
+}
+
+func getValidIssuerAndSecret() (cmpv2api.CMPv2Issuer, v1.Secret) {
+ issuer := cmpv2api.CMPv2Issuer{
+ Spec: cmpv2api.CMPv2IssuerSpec{
+ URL: url,
+ CaName: caName,
+ CertSecretRef: cmpv2api.SecretKeySelector{
+ Name: secretName,
+ KeyRef: keySecretKey,
+ CertRef: certSecretKey,
+ CacertRef: cacertSecretKey,
+ },
+ },
+ }
+ secret := v1.Secret{
+
+ Data: map[string][]byte{
+ keySecretKey: keySecretValue,
+ certSecretKey: certSecretValue,
+ cacertSecretKey: cacertSecretValue,
+ },
+ }
+ secret.Name = secretName
+ return issuer, secret
+}
diff --git a/certServiceK8sExternalProvider/src/exit_code.go b/certServiceK8sExternalProvider/src/exit_code.go
index 7435c64f..4fb984d3 100644
--- a/certServiceK8sExternalProvider/src/exit_code.go
+++ b/certServiceK8sExternalProvider/src/exit_code.go
@@ -1,13 +1,13 @@
package app
type ExitCode struct {
- Code int
+ Code int
Message string
}
var (
- FAILED_TO_CREATE_CONTROLLER_MANAGER = ExitCode{1, "Unable to create k8s controller manager"}
+ FAILED_TO_CREATE_CONTROLLER_MANAGER = ExitCode{1, "Unable to create K8s controller manager"}
FAILED_TO_REGISTER_CMPv2_ISSUER_CONTROLLER = ExitCode{2, "Unable to register CMPv2Issuer controller"}
FAILED_TO_REGISTER_CERT_REQUEST_CONTROLLER = ExitCode{3, "Unable to register CertificateRequestController"}
- EXCEPTION_WHILE_RUNNING_CONTROLLER_MANAGER = ExitCode{4, "An exception occurs while running k8s controller manager"}
+ EXCEPTION_WHILE_RUNNING_CONTROLLER_MANAGER = ExitCode{4, "An exception occurs while running K8s controller manager"}
)
diff --git a/certServiceK8sExternalProvider/src/exit_code_test.go b/certServiceK8sExternalProvider/src/exit_code_test.go
index 8a42909a..1492036b 100644
--- a/certServiceK8sExternalProvider/src/exit_code_test.go
+++ b/certServiceK8sExternalProvider/src/exit_code_test.go
@@ -22,6 +22,7 @@ package app
import (
"testing"
+
"github.com/stretchr/testify/assert"
)