1
0
Fork 0
mirror of https://github.com/external-secrets/external-secrets.git synced 2024-12-14 11:57:59 +00:00

Merge pull request #329 from FGA-GCES/feat/immutable-secrets

Add immutable secrets
This commit is contained in:
Lucas Severo Alves 2021-10-12 18:20:23 +02:00 committed by GitHub
commit c00afc9ff7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 70 additions and 2 deletions

View file

@ -103,6 +103,10 @@ type ExternalSecretTarget struct {
// Template defines a blueprint for the created Secret resource.
// +optional
Template *ExternalSecretTemplate `json:"template,omitempty"`
// Immutable defines if the final secret will be immutable
// +optional
Immutable bool `json:"immutable,omitempty"`
}
// ExternalSecretData defines the connection between the Kubernetes Secret key (spec.data.<key>) and the Provider data.

View file

@ -132,6 +132,9 @@ spec:
description: CreationPolicy defines rules on how to create the
resulting Secret Defaults to 'Owner'
type: string
immutable:
description: Immutable defines if the final secret will be immutable
type: boolean
name:
description: Name defines the name of the Secret resource to be
managed This field is immutable Defaults to the .metadata.name

View file

@ -180,13 +180,21 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
log.V(1).Info("skipping refresh", "rv", getResourceVersion(externalSecret))
return ctrl.Result{RequeueAfter: refreshInt}, nil
}
if !shouldReconcile(externalSecret) {
log.V(1).Info("stopping reconciling", "rv", getResourceVersion(externalSecret))
return ctrl.Result{
RequeueAfter: 0,
Requeue: false,
}, nil
}
secret := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
Namespace: externalSecret.Namespace,
},
Data: make(map[string][]byte),
Immutable: &externalSecret.Spec.Target.Immutable,
Data: make(map[string][]byte),
}
mutationFunc := func() error {
@ -314,6 +322,22 @@ func shouldRefresh(es esv1alpha1.ExternalSecret) bool {
return !es.Status.RefreshTime.Add(es.Spec.RefreshInterval.Duration).After(time.Now())
}
func shouldReconcile(es esv1alpha1.ExternalSecret) bool {
if es.Spec.Target.Immutable && hasSyncedCondition(es) {
return false
}
return true
}
func hasSyncedCondition(es esv1alpha1.ExternalSecret) bool {
for _, condition := range es.Status.Conditions {
if condition.Reason == "SecretSynced" {
return true
}
}
return false
}
// isSecretValid checks if the secret exists, and it's data is consistent with the calculated hash.
func isSecretValid(existingSecret v1.Secret) bool {
// if target secret doesn't exist, or annotations as not set, we need to refresh

View file

@ -307,7 +307,7 @@ var _ = Describe("ExternalSecret controller", func() {
Expect(hasFieldOwnership(
secret.ObjectMeta,
"external-secrets",
fmt.Sprintf("{\"f:data\":{\"f:targetProperty\":{}},\"f:metadata\":{\"f:annotations\":{\"f:%s\":{}}}}", esv1alpha1.AnnotationDataHash)),
fmt.Sprintf("{\"f:data\":{\"f:targetProperty\":{}},\"f:immutable\":{},\"f:metadata\":{\"f:annotations\":{\"f:%s\":{}}}}", esv1alpha1.AnnotationDataHash)),
).To(BeTrue())
Expect(hasFieldOwnership(secret.ObjectMeta, "fake.manager", "{\"f:data\":{\".\":{},\"f:pre-existing-key\":{}},\"f:type\":{}}")).To(BeTrue())
}
@ -1138,6 +1138,43 @@ var _ = Describe("ExternalSecret refresh logic", func() {
})
})
var _ = Describe("Controller Reconcile logic", func() {
Context("controller reconcile", func() {
It("should reconcile when resource is not synced", func() {
Expect(shouldReconcile(esv1alpha1.ExternalSecret{
Status: esv1alpha1.ExternalSecretStatus{
SyncedResourceVersion: "some resource version",
Conditions: []esv1alpha1.ExternalSecretStatusCondition{{Reason: "NotASecretSynced"}},
},
})).To(BeTrue())
})
It("should reconcile when secret isn't immutable", func() {
Expect(shouldReconcile(esv1alpha1.ExternalSecret{
Spec: esv1alpha1.ExternalSecretSpec{
Target: esv1alpha1.ExternalSecretTarget{
Immutable: false,
},
},
})).To(BeTrue())
})
It("should not reconcile if secret is immutable and has synced condition", func() {
Expect(shouldReconcile(esv1alpha1.ExternalSecret{
Spec: esv1alpha1.ExternalSecretSpec{
Target: esv1alpha1.ExternalSecretTarget{
Immutable: true,
},
},
Status: esv1alpha1.ExternalSecretStatus{
SyncedResourceVersion: "some resource version",
Conditions: []esv1alpha1.ExternalSecretStatusCondition{{Reason: "SecretSynced"}},
},
})).To(BeFalse())
})
})
})
// CreateNamespace creates a new namespace in the cluster.
func CreateNamespace(baseName string, c client.Client) (string, error) {
genName := fmt.Sprintf("ctrl-test-%v", baseName)