github.com/IBM-Blockchain/fabric-operator@v1.0.4/pkg/offering/common/common_test.go (about)

     1  /*
     2   * Copyright contributors to the Hyperledger Fabric Operator project
     3   *
     4   * SPDX-License-Identifier: Apache-2.0
     5   *
     6   * Licensed under the Apache License, Version 2.0 (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at:
     9   *
    10   * 	  http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing, software
    13   * distributed under the License is distributed on an "AS IS" BASIS,
    14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15   * See the License for the specific language governing permissions and
    16   * limitations under the License.
    17   */
    18  
    19  package common_test
    20  
    21  import (
    22  	"context"
    23  	"encoding/base64"
    24  	"encoding/json"
    25  	"errors"
    26  	"time"
    27  
    28  	. "github.com/onsi/ginkgo/v2"
    29  	. "github.com/onsi/gomega"
    30  	corev1 "k8s.io/api/core/v1"
    31  	k8serrors "k8s.io/apimachinery/pkg/api/errors"
    32  	"k8s.io/apimachinery/pkg/runtime"
    33  	"k8s.io/apimachinery/pkg/runtime/schema"
    34  	"k8s.io/apimachinery/pkg/types"
    35  	"sigs.k8s.io/controller-runtime/pkg/client"
    36  
    37  	current "github.com/IBM-Blockchain/fabric-operator/api/v1beta1"
    38  	"github.com/IBM-Blockchain/fabric-operator/controllers/mocks"
    39  	"github.com/IBM-Blockchain/fabric-operator/pkg/offering/common"
    40  )
    41  
    42  var _ = Describe("Common", func() {
    43  
    44  	const testcert = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNwVENDQWtxZ0F3SUJBZ0lSQU1FeVZVcDRMdlYydEFUREhlWklldDh3Q2dZSUtvWkl6ajBFQXdJd2daVXgKQ3pBSkJnTlZCQVlUQWxWVE1SY3dGUVlEVlFRSUV3NU9iM0owYUNCRFlYSnZiR2x1WVRFUE1BMEdBMVVFQnhNRwpSSFZ5YUdGdE1Rd3dDZ1lEVlFRS0V3TkpRazB4RXpBUkJnTlZCQXNUQ2tKc2IyTnJZMmhoYVc0eE9UQTNCZ05WCkJBTVRNR3BoYmpJeUxXOXlaR1Z5WlhKdmNtZGpZUzFqWVM1aGNIQnpMbkIxYldGekxtOXpMbVo1Y21VdWFXSnQKTG1OdmJUQWVGdzB5TURBeE1qSXhPREExTURCYUZ3MHpNREF4TVRreE9EQTFNREJhTUlHVk1Rc3dDUVlEVlFRRwpFd0pWVXpFWE1CVUdBMVVFQ0JNT1RtOXlkR2dnUTJGeWIyeHBibUV4RHpBTkJnTlZCQWNUQmtSMWNtaGhiVEVNCk1Bb0dBMVVFQ2hNRFNVSk5NUk13RVFZRFZRUUxFd3BDYkc5amEyTm9ZV2x1TVRrd053WURWUVFERXpCcVlXNHkKTWkxdmNtUmxjbVZ5YjNKblkyRXRZMkV1WVhCd2N5NXdkVzFoY3k1dmN5NW1lWEpsTG1saWJTNWpiMjB3V1RBVApCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFTR0lHUFkvZC9tQVhMejM4SlROR3F5bldpOTJXUVB6cnN0Cm5vdEFWZlh0dHZ5QWJXdTRNbWNUMEh6UnBTWjNDcGdxYUNXcTg1MUwyV09LcnZ6L0JPREpvM2t3ZHpCMUJnTlYKSFJFRWJqQnNnakJxWVc0eU1pMXZjbVJsY21WeWIzSm5ZMkV0WTJFdVlYQndjeTV3ZFcxaGN5NXZjeTVtZVhKbApMbWxpYlM1amIyMkNPR3BoYmpJeUxXOXlaR1Z5WlhKdmNtZGpZUzF2Y0dWeVlYUnBiMjV6TG1Gd2NITXVjSFZ0CllYTXViM011Wm5seVpTNXBZbTB1WTI5dE1Bb0dDQ3FHU000OUJBTUNBMGtBTUVZQ0lRQzM3Y1pkNFY2RThPQ1IKaDloQXEyK0dyR21FVTFQU0I1eHo5RkdEWThkODZRSWhBT1crM3Urb2d4bFNWNUoyR3ZYbHRaQmpXRkpvYnJxeApwVVQ4cW4yMDA1b0wKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo"
    45  
    46  	var (
    47  		mockKubeClient *mocks.Client
    48  		instance       *current.IBPPeer
    49  
    50  		crypto1 *current.MSP
    51  		crypto2 *current.MSP
    52  		crypto3 *current.MSP
    53  
    54  		encodedtestcert string
    55  
    56  		backupData map[string][]byte
    57  	)
    58  
    59  	BeforeEach(func() {
    60  		mockKubeClient = &mocks.Client{}
    61  
    62  		instance = &current.IBPPeer{}
    63  		instance.Name = "peer1"
    64  
    65  		crypto1 = &current.MSP{SignCerts: "signcert1"}
    66  		crypto2 = &current.MSP{SignCerts: "signcert2"}
    67  		crypto3 = &current.MSP{SignCerts: "signcert3"}
    68  
    69  		backup := &common.Backup{
    70  			List:      []*current.MSP{crypto1},
    71  			Timestamp: time.Now().String(),
    72  		}
    73  		backupBytes, err := json.Marshal(backup)
    74  		Expect(err).NotTo(HaveOccurred())
    75  
    76  		backupData = map[string][]byte{
    77  			"tls-backup.json":   backupBytes,
    78  			"ecert-backup.json": backupBytes,
    79  		}
    80  
    81  		mockKubeClient.GetStub = func(ctx context.Context, types types.NamespacedName, obj client.Object) error {
    82  			o := obj.(*corev1.Secret)
    83  			switch types.Name {
    84  			case "tls-" + instance.Name + "-signcert":
    85  				o.Name = "tls-" + instance.Name + "-signcert"
    86  				o.Namespace = instance.Namespace
    87  				o.Data = map[string][]byte{"cert.pem": []byte(testcert)}
    88  			case "tls-" + instance.Name + "-keystore":
    89  				o.Name = "tls-" + instance.Name + "-keystore"
    90  				o.Namespace = instance.Namespace
    91  				o.Data = map[string][]byte{"key.pem": []byte(testcert)}
    92  			case "tls-" + instance.Name + "-cacerts":
    93  				o.Name = "tls-" + instance.Name + "-cacerts"
    94  				o.Namespace = instance.Namespace
    95  				o.Data = map[string][]byte{"key.pem": []byte(testcert)}
    96  			case "ecert-" + instance.Name + "-signcert":
    97  				o.Name = "ecert-" + instance.Name + "-signcert"
    98  				o.Namespace = instance.Namespace
    99  				o.Data = map[string][]byte{"cert.pem": []byte(testcert)}
   100  			case "ecert-" + instance.Name + "-cacerts":
   101  				o.Name = "ecert-" + instance.Name + "-cacerts"
   102  				o.Namespace = instance.Namespace
   103  				o.Data = map[string][]byte{"cacert-0.pem": []byte(testcert)}
   104  			case "peer1-crypto-backup":
   105  				o.Name = instance.Name + "-crypto-backup"
   106  				o.Namespace = instance.Namespace
   107  				o.Data = backupData
   108  			case "ca1-ca-crypto":
   109  				o.Name = instance.Name + "-ca-crypto"
   110  				o.Namespace = instance.Namespace
   111  				o.Data = map[string][]byte{
   112  					"tls-cert.pem":        []byte(testcert),
   113  					"tls-key.pem":         []byte(testcert),
   114  					"cert.pem":            []byte(testcert),
   115  					"key.pem":             []byte(testcert),
   116  					"operations-cert.pem": []byte(testcert),
   117  					"operations-key.pem":  []byte(testcert),
   118  				}
   119  			case "ca1-crypto-backup":
   120  				o.Name = "ca1-crypto-backup"
   121  				o.Namespace = instance.Namespace
   122  				o.Data = backupData
   123  			}
   124  			return nil
   125  		}
   126  
   127  		encodedtestcert = base64.StdEncoding.EncodeToString([]byte(testcert))
   128  	})
   129  
   130  	Context("backup crypto", func() {
   131  
   132  		Context("get crypto", func() {
   133  			It("returns nil if fails to get secret", func() {
   134  				mockKubeClient.GetReturns(errors.New("get error"))
   135  				crypto := common.GetCrypto("tls", mockKubeClient, instance)
   136  				Expect(crypto).To(BeNil())
   137  			})
   138  
   139  			It("returns nil if no secrets are found", func() {
   140  				mockKubeClient.GetReturns(k8serrors.NewNotFound(schema.GroupResource{}, "not found"))
   141  				crypto := common.GetCrypto("tls", mockKubeClient, instance)
   142  				Expect(crypto).To(BeNil())
   143  			})
   144  
   145  			It("returns tls crypto", func() {
   146  				crypto := common.GetCrypto("tls", mockKubeClient, instance)
   147  				Expect(crypto).NotTo(BeNil())
   148  				Expect(crypto).To(Equal(&current.MSP{
   149  					SignCerts: encodedtestcert,
   150  					KeyStore:  encodedtestcert,
   151  					CACerts:   []string{encodedtestcert},
   152  				}))
   153  			})
   154  
   155  			It("returns ecert crypto", func() {
   156  				crypto := common.GetCrypto("ecert", mockKubeClient, instance)
   157  				Expect(crypto).NotTo(BeNil())
   158  				Expect(crypto).To(Equal(&current.MSP{
   159  					SignCerts: encodedtestcert,
   160  					CACerts:   []string{encodedtestcert},
   161  				}))
   162  			})
   163  		})
   164  
   165  		Context("udpate secret data", func() {
   166  			var (
   167  				data map[string][]byte
   168  			)
   169  
   170  			BeforeEach(func() {
   171  
   172  				backup := &common.Backup{
   173  					List:      []*current.MSP{crypto1},
   174  					Timestamp: time.Now().String(),
   175  				}
   176  				backupBytes, err := json.Marshal(backup)
   177  				Expect(err).NotTo(HaveOccurred())
   178  
   179  				data = map[string][]byte{
   180  					"tls-backup.json":   backupBytes,
   181  					"ecert-backup.json": backupBytes,
   182  				}
   183  			})
   184  
   185  			It("adds crypto to backup list", func() {
   186  				crypto := &common.Crypto{
   187  					TLS:   crypto2,
   188  					Ecert: crypto2,
   189  				}
   190  				updatedData, err := common.UpdateBackupSecretData(data, crypto)
   191  				Expect(err).NotTo(HaveOccurred())
   192  
   193  				By("updating tls backup", func() {
   194  					tlsbackup := &common.Backup{}
   195  					err = json.Unmarshal(updatedData["tls-backup.json"], tlsbackup)
   196  					Expect(err).NotTo(HaveOccurred())
   197  					Expect(tlsbackup.List).To(Equal([]*current.MSP{crypto1, crypto2}))
   198  					Expect(tlsbackup.Timestamp).NotTo(Equal(""))
   199  				})
   200  
   201  				By("updating ecert backup", func() {
   202  					ecertbackup := &common.Backup{}
   203  					err = json.Unmarshal(updatedData["ecert-backup.json"], ecertbackup)
   204  					Expect(err).NotTo(HaveOccurred())
   205  					Expect(ecertbackup.List).To(Equal([]*current.MSP{crypto1, crypto2}))
   206  					Expect(ecertbackup.Timestamp).NotTo(Equal(""))
   207  				})
   208  			})
   209  
   210  			It("removes oldest crypto from queue and inserts new crypto if list is longer than 10", func() {
   211  				backup := &common.Backup{
   212  					List:      []*current.MSP{crypto1, crypto1, crypto1, crypto1, crypto1, crypto1, crypto1, crypto1, crypto1, crypto2},
   213  					Timestamp: time.Now().String(),
   214  				}
   215  				backupBytes, err := json.Marshal(backup)
   216  				Expect(err).NotTo(HaveOccurred())
   217  
   218  				data = map[string][]byte{
   219  					"tls-backup.json":   backupBytes,
   220  					"ecert-backup.json": backupBytes,
   221  				}
   222  
   223  				crypto := &common.Crypto{
   224  					TLS:   crypto3,
   225  					Ecert: crypto3,
   226  				}
   227  				updatedData, err := common.UpdateBackupSecretData(data, crypto)
   228  				Expect(err).NotTo(HaveOccurred())
   229  
   230  				By("updating tls backup to contain 10 most recent backups", func() {
   231  					tlsbackup := &common.Backup{}
   232  					err = json.Unmarshal(updatedData["tls-backup.json"], tlsbackup)
   233  					Expect(err).NotTo(HaveOccurred())
   234  					Expect(tlsbackup.List).To(Equal([]*current.MSP{crypto1, crypto1, crypto1, crypto1, crypto1, crypto1, crypto1, crypto1, crypto2, crypto3}))
   235  					Expect(tlsbackup.Timestamp).NotTo(Equal(""))
   236  				})
   237  
   238  				By("updating ecert backup to contain 10 most recent backups", func() {
   239  					ecertbackup := &common.Backup{}
   240  					err = json.Unmarshal(updatedData["ecert-backup.json"], ecertbackup)
   241  					Expect(err).NotTo(HaveOccurred())
   242  					Expect(ecertbackup.List).To(Equal([]*current.MSP{crypto1, crypto1, crypto1, crypto1, crypto1, crypto1, crypto1, crypto1, crypto2, crypto3}))
   243  					Expect(ecertbackup.Timestamp).NotTo(Equal(""))
   244  				})
   245  			})
   246  		})
   247  
   248  		Context("backup crypto", func() {
   249  			It("returns nil if neither TLS nor ecert crypto is found", func() {
   250  				mockKubeClient.GetReturns(errors.New("get error"))
   251  				err := common.BackupCrypto(mockKubeClient, &runtime.Scheme{}, instance, map[string]string{})
   252  				Expect(err).NotTo(HaveOccurred())
   253  			})
   254  
   255  			It("returns error if fails to update backup secret", func() {
   256  				mockKubeClient.UpdateReturns(errors.New("create or update error"))
   257  				err := common.BackupCrypto(mockKubeClient, &runtime.Scheme{}, instance, map[string]string{})
   258  				Expect(err).To(HaveOccurred())
   259  				Expect(err.Error()).To(Equal("failed to update backup secret: create or update error"))
   260  			})
   261  
   262  			It("updates backup secret if one exists for instance", func() {
   263  				err := common.BackupCrypto(mockKubeClient, &runtime.Scheme{}, instance, map[string]string{})
   264  				Expect(err).NotTo(HaveOccurred())
   265  				Expect(mockKubeClient.UpdateCallCount()).To(Equal(1))
   266  
   267  				newCrypto := &current.MSP{
   268  					SignCerts: encodedtestcert,
   269  					KeyStore:  encodedtestcert,
   270  					CACerts:   []string{encodedtestcert},
   271  				}
   272  
   273  				By("updating tls backup", func() {
   274  					tlsbackup := &common.Backup{}
   275  					err = json.Unmarshal(backupData["tls-backup.json"], tlsbackup)
   276  					Expect(err).NotTo(HaveOccurred())
   277  					Expect(tlsbackup.List).To(Equal([]*current.MSP{crypto1, newCrypto}))
   278  					Expect(tlsbackup.Timestamp).NotTo(Equal(""))
   279  				})
   280  
   281  				By("updating ecert backup", func() {
   282  					newCrypto.KeyStore = ""
   283  					ecertbackup := &common.Backup{}
   284  					err = json.Unmarshal(backupData["ecert-backup.json"], ecertbackup)
   285  					Expect(err).NotTo(HaveOccurred())
   286  					Expect(ecertbackup.List).To(Equal([]*current.MSP{crypto1, newCrypto}))
   287  					Expect(ecertbackup.Timestamp).NotTo(Equal(""))
   288  				})
   289  			})
   290  		})
   291  
   292  		Context("backup CA crypto", func() {
   293  			var (
   294  				instance *current.IBPCA
   295  			)
   296  
   297  			BeforeEach(func() {
   298  				instance = &current.IBPCA{}
   299  				instance.Name = "ca1"
   300  			})
   301  
   302  			It("returns nil if CA TLS crypto is not found", func() {
   303  				mockKubeClient.GetReturns(errors.New("get error"))
   304  				err := common.BackupCACrypto(mockKubeClient, &runtime.Scheme{}, instance, map[string]string{})
   305  				Expect(err).NotTo(HaveOccurred())
   306  			})
   307  
   308  			It("updates backup secret if one exists for instance", func() {
   309  				err := common.BackupCACrypto(mockKubeClient, &runtime.Scheme{}, instance, map[string]string{})
   310  				Expect(err).NotTo(HaveOccurred())
   311  				Expect(mockKubeClient.UpdateCallCount()).To(Equal(1))
   312  
   313  				newCrypto := &current.MSP{
   314  					SignCerts: encodedtestcert,
   315  					KeyStore:  encodedtestcert,
   316  				}
   317  
   318  				By("updating tls backup", func() {
   319  					tlsbackup := &common.Backup{}
   320  					err = json.Unmarshal(backupData["tls-backup.json"], tlsbackup)
   321  					Expect(err).NotTo(HaveOccurred())
   322  					Expect(tlsbackup.List).To(Equal([]*current.MSP{crypto1, newCrypto}))
   323  					Expect(tlsbackup.Timestamp).NotTo(Equal(""))
   324  				})
   325  
   326  				By("creating operations backup", func() {
   327  					opbackup := &common.Backup{}
   328  					err = json.Unmarshal(backupData["operations-backup.json"], opbackup)
   329  					Expect(err).NotTo(HaveOccurred())
   330  					Expect(opbackup.List).To(Equal([]*current.MSP{newCrypto}))
   331  					Expect(opbackup.Timestamp).NotTo(Equal(""))
   332  				})
   333  
   334  				By("creating ca backup", func() {
   335  					cabackup := &common.Backup{}
   336  					err = json.Unmarshal(backupData["ca-backup.json"], cabackup)
   337  					Expect(err).NotTo(HaveOccurred())
   338  					Expect(cabackup.List).To(Equal([]*current.MSP{newCrypto}))
   339  					Expect(cabackup.Timestamp).NotTo(Equal(""))
   340  				})
   341  			})
   342  		})
   343  
   344  	})
   345  
   346  })