Sfoglia il codice sorgente

fix(aws): detach replicated regions before deleting AWS SecretsManager secret (#6687)

* fix(aws/secretsmanager): detach replicated regions before deleting secret

Signed-off-by: Charles Moscofian <charlesmoscofian@hotmail.com>

* test(aws/secretsmanager): address code-rabbit suggestion

Signed-off-by: Charles Moscofian <charlesmoscofian@hotmail.com>

* chore(aws/secretsmanager): remove unnecessary log.info

Signed-off-by: Charles Moscofian <charlesmoscofian@hotmail.com>

---------

Signed-off-by: Charles Moscofian <charlesmoscofian@hotmail.com>
Co-authored-by: Jean-Philippe Evrard <jean-philippe.evrard+rochepub@external.roche.com>
Co-authored-by: Gergely Bräutigam <gergely.brautigam@sap.com>
Charles Moscofian 3 settimane fa
parent
commit
7a7600fe6a

+ 9 - 0
providers/v1/aws/secretsmanager/secretsmanager.go

@@ -199,6 +199,15 @@ func (sm *SecretsManager) DeleteSecret(ctx context.Context, remoteRef esv1.PushS
 	if !isManagedByESO(data) {
 	if !isManagedByESO(data) {
 		return nil
 		return nil
 	}
 	}
+	if len(data.ReplicationStatus) > 0 {
+		regions := make([]string, 0, len(data.ReplicationStatus))
+		for _, replicationStatus := range data.ReplicationStatus {
+			regions = append(regions, aws.ToString(replicationStatus.Region))
+		}
+		if err := sm.removeRegionsFromReplication(ctx, aws.String(secretName), regions); err != nil {
+			return err
+		}
+	}
 	deleteInput := &awssm.DeleteSecretInput{
 	deleteInput := &awssm.DeleteSecretInput{
 		SecretId: awsSecret.ARN,
 		SecretId: awsSecret.ARN,
 	}
 	}

+ 58 - 0
providers/v1/aws/secretsmanager/secretsmanager_test.go

@@ -1813,6 +1813,64 @@ func TestDeleteSecret(t *testing.T) {
 			},
 			},
 			reason: "",
 			reason: "",
 		},
 		},
+		"Delete a secret with replicated regions attached successfully": {
+			args: args{
+				client: fakesm.Client{
+					RemoveRegionsFromReplicationFn: func(ctx context.Context, input *awssm.RemoveRegionsFromReplicationInput, opts ...func(*awssm.Options)) (*awssm.RemoveRegionsFromReplicationOutput, error) {
+						// Validate that there is a replication region and the it's the one being removed.
+						if len(input.RemoveReplicaRegions) > 0 && input.RemoveReplicaRegions[0] == "eu-north-1" {
+							return &awssm.RemoveRegionsFromReplicationOutput{}, nil
+						}
+						return nil, errors.New("invalid remove regions from replication input")
+					},
+				},
+				config: esv1.SecretsManager{
+					ForceDeleteWithoutRecovery: true,
+				},
+				getSecretOutput: &awssm.GetSecretValueOutput{},
+				describeSecretOutput: &awssm.DescribeSecretOutput{
+					Tags:              []types.Tag{secretTag},
+					ReplicationStatus: []types.ReplicationStatusType{{Region: aws.String("eu-north-1")}},
+				},
+				deleteSecretOutput: &awssm.DeleteSecretOutput{
+					DeletionDate: aws.Time(time.Now()),
+				},
+				getSecretErr:      nil,
+				describeSecretErr: nil,
+				deleteSecretErr:   nil,
+			},
+			want: want{
+				err: nil,
+			},
+			reason: "",
+		},
+		"Fails to delete a secret with replicated regions attached if replication removal fails": {
+			args: args{
+				client: fakesm.Client{
+					RemoveRegionsFromReplicationFn: func(ctx context.Context, input *awssm.RemoveRegionsFromReplicationInput, opts ...func(*awssm.Options)) (*awssm.RemoveRegionsFromReplicationOutput, error) {
+						return nil, &types.InternalServiceError{Message: aws.String("The secret is scheduled for deletion")}
+					},
+				},
+				config: esv1.SecretsManager{
+					ForceDeleteWithoutRecovery: true,
+				},
+				getSecretOutput: &awssm.GetSecretValueOutput{},
+				describeSecretOutput: &awssm.DescribeSecretOutput{
+					Tags:              []types.Tag{secretTag},
+					ReplicationStatus: []types.ReplicationStatusType{{Region: aws.String("eu-north-1")}},
+				},
+				deleteSecretOutput: &awssm.DeleteSecretOutput{
+					DeletionDate: aws.Time(time.Now()),
+				},
+				getSecretErr:      nil,
+				describeSecretErr: nil,
+				deleteSecretErr:   nil,
+			},
+			want: want{
+				err: errors.New("failed to remove regions from secret replication: InternalServiceError: The secret is scheduled for deletion"),
+			},
+			reason: "Secret deletion depends on removing secret replication first when existing",
+		},
 		"Invalid Recovery Window": {
 		"Invalid Recovery Window": {
 			args: args{
 			args: args{