From 8e3e686c5442581704539e5f644b76b1fb74413b Mon Sep 17 00:00:00 2001 From: David VIEJO Date: Mon, 2 Dec 2024 14:56:16 +0100 Subject: [PATCH] Add revocation list support to FabricFollowerChannel and improve requeue logic in chaincode controllers - Introduced a new `revocationList` field in `FabricFollowerChannelSpec` to manage certificate revocation lists. - Enhanced the `updateCRStatusOrFailReconcile` method in chaincode controllers to requeue failed updates after 10 seconds and handle running status without requeuing. - Implemented CRL parsing utility to support revocation list processing in the follower channel controller. - Updated related CRD and deepcopy functions to accommodate the new revocation list feature. Signed-off-by: David VIEJO --- ...gfusoftware.es_fabricfollowerchannels.yaml | 6 ++++ .../approve/chaincode_approve_controller.go | 17 +++++++---- .../commit/chaincode_commit_controller.go | 16 ++++++++--- .../install/chaincode_install_controller.go | 18 ++++++++++-- .../followerchannel_controller.go | 28 ++++++++++++++++++- .../mainchannel/mainchannel_controller.go | 6 ++-- controllers/utils/crl.go | 22 +++++++++++++++ .../v1alpha1/hlf_types.go | 6 ++++ .../v1alpha1/zz_generated.deepcopy.go | 5 ++++ 9 files changed, 110 insertions(+), 14 deletions(-) create mode 100644 controllers/utils/crl.go diff --git a/config/crd/bases/hlf.kungfusoftware.es_fabricfollowerchannels.yaml b/config/crd/bases/hlf.kungfusoftware.es_fabricfollowerchannels.yaml index d92eae60..f9b5e469 100644 --- a/config/crd/bases/hlf.kungfusoftware.es_fabricfollowerchannels.yaml +++ b/config/crd/bases/hlf.kungfusoftware.es_fabricfollowerchannels.yaml @@ -101,6 +101,12 @@ spec: - namespace type: object type: array + revocationList: + default: [] + items: + type: string + nullable: true + type: array required: - anchorPeers - externalPeersToJoin diff --git a/controllers/chaincode/approve/chaincode_approve_controller.go b/controllers/chaincode/approve/chaincode_approve_controller.go index 23a38c8b..547b6b16 100644 --- a/controllers/chaincode/approve/chaincode_approve_controller.go +++ b/controllers/chaincode/approve/chaincode_approve_controller.go @@ -315,19 +315,26 @@ func (r *FabricChaincodeApproveReconciler) updateCRStatusOrFailReconcile(ctx con if err := r.Status().Update(ctx, p); err != nil { log.Error(err, fmt.Sprintf("%v failed to update the application status", ErrClientK8s)) return reconcile.Result{ - Requeue: false, - RequeueAfter: 0, + Requeue: true, + RequeueAfter: time.Second * 10, }, nil } + + // If status is failed, requeue after 1 minute if p.Status.Status == hlfv1alpha1.FailedStatus { return reconcile.Result{ RequeueAfter: 1 * time.Minute, }, nil } - r.Log.Info(fmt.Sprintf("Requeueing after 1 minute for %s", p.Name)) + + // If status is running/success, don't requeue + if p.Status.Status == hlfv1alpha1.RunningStatus { + return reconcile.Result{}, nil + } + + // For any other status, requeue after 1 minute return reconcile.Result{ - Requeue: false, - RequeueAfter: 0, + RequeueAfter: 1 * time.Minute, }, nil } diff --git a/controllers/chaincode/commit/chaincode_commit_controller.go b/controllers/chaincode/commit/chaincode_commit_controller.go index 7e208711..4686de31 100644 --- a/controllers/chaincode/commit/chaincode_commit_controller.go +++ b/controllers/chaincode/commit/chaincode_commit_controller.go @@ -241,16 +241,24 @@ func (r *FabricChaincodeCommitReconciler) updateCRStatusOrFailReconcile(ctx cont if err := r.Status().Update(ctx, p); err != nil { log.Error(err, fmt.Sprintf("%v failed to update the application status", ErrClientK8s)) return reconcile.Result{ - Requeue: false, - RequeueAfter: 0, - }, err + Requeue: true, + RequeueAfter: time.Second * 10, + }, nil } + if p.Status.Status == hlfv1alpha1.FailedStatus { return reconcile.Result{ RequeueAfter: 1 * time.Minute, }, nil } - return reconcile.Result{}, nil + + if p.Status.Status == hlfv1alpha1.RunningStatus { + return reconcile.Result{}, nil + } + + return reconcile.Result{ + RequeueAfter: 1 * time.Minute, + }, nil } func (r *FabricChaincodeCommitReconciler) SetupWithManager(mgr ctrl.Manager) error { diff --git a/controllers/chaincode/install/chaincode_install_controller.go b/controllers/chaincode/install/chaincode_install_controller.go index 9aa6c5fc..33cfc66a 100644 --- a/controllers/chaincode/install/chaincode_install_controller.go +++ b/controllers/chaincode/install/chaincode_install_controller.go @@ -459,14 +459,28 @@ func (r *FabricChaincodeInstallReconciler) updateCRStatusOrFailReconcile(ctx con reconcile.Result, error) { if err := r.Status().Update(ctx, p); err != nil { log.Error(err, fmt.Sprintf("%v failed to update the application status", ErrClientK8s)) - return reconcile.Result{}, err + return reconcile.Result{ + Requeue: true, + RequeueAfter: time.Second * 10, + }, nil } + + // If status is failed, requeue after 1 minute if p.Status.Status == hlfv1alpha1.FailedStatus { return reconcile.Result{ RequeueAfter: 1 * time.Minute, }, nil } - return reconcile.Result{}, nil + + // If status is running/success, don't requeue + if p.Status.Status == hlfv1alpha1.RunningStatus { + return reconcile.Result{}, nil + } + + // For any other status, requeue after 1 minute + return reconcile.Result{ + RequeueAfter: 1 * time.Minute, + }, nil } func (r *FabricChaincodeInstallReconciler) SetupWithManager(mgr ctrl.Manager) error { diff --git a/controllers/followerchannel/followerchannel_controller.go b/controllers/followerchannel/followerchannel_controller.go index 4e0c5ab4..5afef2a1 100644 --- a/controllers/followerchannel/followerchannel_controller.go +++ b/controllers/followerchannel/followerchannel_controller.go @@ -3,6 +3,7 @@ package followerchannel import ( "bytes" "context" + "crypto/x509/pkix" "fmt" "strings" "time" @@ -279,7 +280,6 @@ func (r *FabricFollowerChannelReconciler) Reconcile(ctx context.Context, req ctr reqLogger.Info(fmt.Sprintf("Removed anchor peer %v", anchorPeer)) } r.Log.Info(fmt.Sprintf("New anchor peers %v", anchorPeers)) - for _, anchorPeer := range fabricFollowerChannel.Spec.AnchorPeers { err = app.AddAnchorPeer(configtx.Address{ Host: anchorPeer.Host, @@ -291,6 +291,32 @@ func (r *FabricFollowerChannelReconciler) Reconcile(ctx context.Context, req ctr return r.updateCRStatusOrFailReconcile(ctx, r.Log, fabricFollowerChannel) } } + + r.Log.Info("Setting CRL configuration") + + msp := app.MSP() + mspConf, err := msp.Configuration() + if err != nil { + r.setConditionStatus(ctx, fabricFollowerChannel, hlfv1alpha1.FailedStatus, false, err, false) + return r.updateCRStatusOrFailReconcile(ctx, r.Log, fabricFollowerChannel) + } + var revocationList []*pkix.CertificateList + for _, revocation := range fabricFollowerChannel.Spec.RevocationList { + crl, err := utils.ParseCRL([]byte(revocation)) + if err != nil { + r.setConditionStatus(ctx, fabricFollowerChannel, hlfv1alpha1.FailedStatus, false, err, false) + return r.updateCRStatusOrFailReconcile(ctx, r.Log, fabricFollowerChannel) + } + revocationList = append(revocationList, crl) + } + mspConf.RevocationList = revocationList + err = app.SetMSP(mspConf) + if err != nil { + r.setConditionStatus(ctx, fabricFollowerChannel, hlfv1alpha1.FailedStatus, false, err, false) + return r.updateCRStatusOrFailReconcile(ctx, r.Log, fabricFollowerChannel) + } + r.Log.Info("CRL configuration set") + r.Log.Info("Updating channel configuration") configUpdateBytes, err := cftxGen.ComputeMarshaledUpdate(fabricFollowerChannel.Spec.Name) if err != nil { if !strings.Contains(err.Error(), "no differences detected between original and updated config") { diff --git a/controllers/mainchannel/mainchannel_controller.go b/controllers/mainchannel/mainchannel_controller.go index ca8c282d..de72420a 100644 --- a/controllers/mainchannel/mainchannel_controller.go +++ b/controllers/mainchannel/mainchannel_controller.go @@ -660,7 +660,7 @@ func (r *FabricMainChannelReconciler) saveChannelConfig(ctx context.Context, fab configMapName := fmt.Sprintf("%s-config", fabricMainChannel.ObjectMeta.Name) configMapNamespace := "default" - + r.Log.Info("Saving channel config into configmap", "configmap", configMapName) return r.createOrUpdateConfigMap(ctx, configMapName, configMapNamespace, buf.String()) } @@ -893,6 +893,9 @@ func (r *FabricMainChannelReconciler) mapToConfigTX(channel *hlfv1alpha1.FabricM consenters := []orderer.Consenter{} var smartBFTOptions *sb.Options if channel.Spec.ChannelConfig.Orderer.OrdererType == hlfv1alpha1.OrdererConsensusBFT { + if len(channel.Spec.ChannelConfig.Orderer.ConsenterMapping) <= 4 { + return configtx.Channel{}, fmt.Errorf("consenter mapping needs to be at least 4") + } ordererType = string(orderer.ConsensusTypeBFT) for _, consenterItem := range channel.Spec.ChannelConfig.Orderer.ConsenterMapping { identityCert, err := utils.ParseX509Certificate([]byte(consenterItem.Identity)) @@ -1373,7 +1376,6 @@ func updateChannelConfigTx(currentConfigTX configtx.ConfigTx, newConfigTx config } func updateOrdererChannelConfigTx(currentConfigTX configtx.ConfigTx, newConfigTx configtx.Channel) error { - ord, err := currentConfigTX.Orderer().Configuration() if err != nil { return errors.Wrapf(err, "failed to get application configuration") diff --git a/controllers/utils/crl.go b/controllers/utils/crl.go new file mode 100644 index 00000000..42bc77a2 --- /dev/null +++ b/controllers/utils/crl.go @@ -0,0 +1,22 @@ +package utils + +import ( + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" +) + +func ParseCRL(crlBytes []byte) (*pkix.CertificateList, error) { + block, _ := pem.Decode(crlBytes) + if block == nil { + return nil, fmt.Errorf("failed to decode PEM block containing CRL") + } + + crl, err := x509.ParseCRL(block.Bytes) + if err != nil { + return nil, fmt.Errorf("failed to parse CRL: %v", err) + } + + return crl, nil +} diff --git a/pkg/apis/hlf.kungfusoftware.es/v1alpha1/hlf_types.go b/pkg/apis/hlf.kungfusoftware.es/v1alpha1/hlf_types.go index 399d641d..e4073925 100644 --- a/pkg/apis/hlf.kungfusoftware.es/v1alpha1/hlf_types.go +++ b/pkg/apis/hlf.kungfusoftware.es/v1alpha1/hlf_types.go @@ -1602,6 +1602,7 @@ type FabricNetworkConfigOrgPeer struct { type FabricNetworkConfigOrganization struct { Peers []FabricNetworkConfigOrgPeer `json:"peers"` } + type FabricNetworkConfigCA struct { Name string `json:"name"` Namespace string `json:"namespace"` @@ -2758,6 +2759,11 @@ type FabricFollowerChannelSpec struct { AnchorPeers []FabricFollowerChannelAnchorPeer `json:"anchorPeers"` // Identity to use to interact with the peers and the orderers HLFIdentity HLFIdentity `json:"hlfIdentity"` + // +nullable + // +optional + // +kubebuilder:validation:Optional + // +kubebuilder:default:={} + RevocationList []string `json:"revocationList"` } type FabricFollowerChannelAnchorPeer struct { diff --git a/pkg/apis/hlf.kungfusoftware.es/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/hlf.kungfusoftware.es/v1alpha1/zz_generated.deepcopy.go index 25986534..cbbf729b 100644 --- a/pkg/apis/hlf.kungfusoftware.es/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/hlf.kungfusoftware.es/v1alpha1/zz_generated.deepcopy.go @@ -2053,6 +2053,11 @@ func (in *FabricFollowerChannelSpec) DeepCopyInto(out *FabricFollowerChannelSpec copy(*out, *in) } out.HLFIdentity = in.HLFIdentity + if in.RevocationList != nil { + in, out := &in.RevocationList, &out.RevocationList + *out = make([]string, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FabricFollowerChannelSpec.