Request CSR approvals via /subresource level 07/113207/2
authorIgor D.C <igor.duarte.cardoso@intel.com>
Sat, 26 Sep 2020 02:54:02 +0000 (02:54 +0000)
committerIgor D.C <igor.duarte.cardoso@intel.com>
Mon, 28 Sep 2020 23:29:09 +0000 (23:29 +0000)
Make use of the new /subresource level (under a resource) to
request rsync to process approvals (a K8s subresource) for CSRs.

Generic usage of instructions (order, dependency) for consistency.

This also introduces a 'subresources' package in 'appcontext' with
the first member being the approval subresource. Since subresources
aren't necessarily created with yaml, this package will allow
developers to specify what should be the "interface" in appcontext
for each type of subresource when the different services need to
exchange this data (e.g. DCM and rsync).

Issue-ID: MULTICLOUD-1143
Change-Id: I8c85b4ee8c5654036a1c7ebb39d111ba4518b468
Signed-off-by: Igor D.C <igor.duarte.cardoso@intel.com>
src/dcm/go.mod
src/dcm/pkg/module/apply.go
src/orchestrator/pkg/appcontext/subresources/approval.go [new file with mode: 0644]

index 35f64d8..1f04ac1 100644 (file)
@@ -8,6 +8,8 @@ require (
        github.com/russross/blackfriday/v2 v2.0.1
        github.com/stretchr/testify v1.5.1
        gopkg.in/yaml.v2 v2.2.8
+       k8s.io/api v0.18.2
+       k8s.io/apimachinery v0.18.2
        k8s.io/kubernetes v1.16.9
 )
 
index 8cf73d3..a866934 100644 (file)
@@ -28,12 +28,15 @@ import (
        "strings"
 
        "github.com/onap/multicloud-k8s/src/orchestrator/pkg/appcontext"
+       "github.com/onap/multicloud-k8s/src/orchestrator/pkg/appcontext/subresources"
        "github.com/onap/multicloud-k8s/src/orchestrator/pkg/grpc/installappclient"
        "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/db"
        log "github.com/onap/multicloud-k8s/src/orchestrator/pkg/infra/logutils"
        "github.com/onap/multicloud-k8s/src/orchestrator/pkg/module/controller"
        pkgerrors "github.com/pkg/errors"
        "gopkg.in/yaml.v2"
+       certificatesv1beta1 "k8s.io/api/certificates/v1beta1"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
 // rsyncName denotes the name of the rsync controller
@@ -232,6 +235,17 @@ func createUserCSR(logicalcloud LogicalCloud) (string, string, error) {
        return string(csrData), string(keyData), nil
 }
 
+func createApprovalSubresource(logicalcloud LogicalCloud) (string, error) {
+       subresource := subresources.ApprovalSubresource{
+               Message:        "Approved for Logical Cloud authentication",
+               Reason:         "LogicalCloud",
+               Type:           string(certificatesv1beta1.CertificateApproved),
+               LastUpdateTime: metav1.Now().Format("2006-01-02T15:04:05Z"),
+       }
+       csrData, err := json.Marshal(subresource)
+       return string(csrData), err
+}
+
 /*
 queryDBAndSetRsyncInfo queries the MCO db to find the record the sync controller
 and then sets the RsyncInfo global variable.
@@ -331,6 +345,8 @@ func CreateEtcdContext(logicalcloud LogicalCloud, clusterList []Cluster,
                return pkgerrors.Wrap(err, "Error Creating User CSR and Key for logical cloud")
        }
 
+       approval, err := createApprovalSubresource(logicalcloud)
+
        context := appcontext.AppContext{}
        ctxVal, err := context.InitAppContext()
        if err != nil {
@@ -387,7 +403,7 @@ func CreateEtcdContext(logicalcloud LogicalCloud, clusterList []Cluster,
                }
 
                // Add csr resource to each cluster
-               _, err = context.AddResource(clusterHandle, csrName, csr)
+               csrHandle, err := context.AddResource(clusterHandle, csrName, csr)
                if err != nil {
                        cleanuperr := context.DeleteCompositeApp()
                        if cleanuperr != nil {
@@ -400,6 +416,20 @@ func CreateEtcdContext(logicalcloud LogicalCloud, clusterList []Cluster,
                        return pkgerrors.Wrap(err, "Error adding CSR Resource to AppContext")
                }
 
+               // Add csr approval as a subresource of csr:
+               _, err = context.AddLevelValue(csrHandle, "subresource/approval", approval)
+               if err != nil {
+                       cleanuperr := context.DeleteCompositeApp()
+                       if cleanuperr != nil {
+                               log.Warn("Error cleaning AppContext after add CSR approval failure", log.Fields{
+                                       "cluster-provider": cluster.Specification.ClusterProvider,
+                                       "cluster":          cluster.Specification.ClusterName,
+                                       "logical-cloud":    logicalCloudName,
+                               })
+                       }
+                       return pkgerrors.Wrap(err, "Error approving CSR via AppContext")
+               }
+
                // Add private key to MongoDB
                lckey := LogicalCloudKey{
                        LogicalCloudName: logicalcloud.MetaData.LogicalCloudName,
@@ -458,6 +488,13 @@ func CreateEtcdContext(logicalcloud LogicalCloud, clusterList []Cluster,
                        return pkgerrors.Wrap(err, "Error adding quota Resource to AppContext")
                }
 
+               // Add Subresource Order and Subresource Dependency
+               subresOrder, err := json.Marshal(map[string][]string{"subresorder": []string{"approval"}})
+               if err != nil {
+                       return pkgerrors.Wrap(err, "Error creating subresource order JSON")
+               }
+               subresDependency, err := json.Marshal(map[string]map[string]string{"subresdependency": map[string]string{"approval": "go"}})
+
                // Add Resource Order and Resource Dependency
                resOrder, err := json.Marshal(map[string][]string{"resorder": []string{namespaceName, quotaName, csrName, roleName, roleBindingName}})
                if err != nil {
@@ -504,6 +541,32 @@ func CreateEtcdContext(logicalcloud LogicalCloud, clusterList []Cluster,
                        return pkgerrors.Wrap(err, "Error adding instruction dependency to AppContext")
                }
 
+               _, err = context.AddInstruction(csrHandle, "subresource", "order", string(subresOrder))
+               if err != nil {
+                       cleanuperr := context.DeleteCompositeApp()
+                       if cleanuperr != nil {
+                               log.Warn("Error cleaning AppContext after add instruction  failure", log.Fields{
+                                       "cluster-provider": cluster.Specification.ClusterProvider,
+                                       "cluster":          cluster.Specification.ClusterName,
+                                       "logical-cloud":    logicalCloudName,
+                               })
+                       }
+                       return pkgerrors.Wrap(err, "Error adding instruction order to AppContext")
+               }
+
+               _, err = context.AddInstruction(csrHandle, "subresource", "dependency", string(subresDependency))
+               if err != nil {
+                       cleanuperr := context.DeleteCompositeApp()
+                       if cleanuperr != nil {
+                               log.Warn("Error cleaning AppContext after add instruction  failure", log.Fields{
+                                       "cluster-provider": cluster.Specification.ClusterProvider,
+                                       "cluster":          cluster.Specification.ClusterName,
+                                       "logical-cloud":    logicalCloudName,
+                               })
+                       }
+                       return pkgerrors.Wrap(err, "Error adding instruction dependency to AppContext")
+               }
+
                // Add App-level Order and Dependency
                _, err = context.AddInstruction(handle, "app", "order", string(appOrder))
                _, err = context.AddInstruction(handle, "app", "dependency", string(appDependency))
diff --git a/src/orchestrator/pkg/appcontext/subresources/approval.go b/src/orchestrator/pkg/appcontext/subresources/approval.go
new file mode 100644 (file)
index 0000000..9f3a1e1
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2020 Intel Corporation, Inc
+ *
+ * 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.
+ */
+
+package subresources
+
+// The ApprovalSubresource type defines the 4 necessary parameters
+// that the "approval" subresource of a CertificateSigningRequest in K8s
+// requires, in a forma tto be exchanged over AppContext
+type ApprovalSubresource struct {
+       LastUpdateTime string `json:"lastUpdateTime,omitempty"`
+       Message        string `json:"message,omitempty"`
+       Reason         string `json:"reason,omitempty"`
+       Type           string `json:"type,omitempty"`
+}