Skip to content

Commit

Permalink
feat: support immutable secrets (#574)
Browse files Browse the repository at this point in the history
* add spec.template.immutable field to the SealedSecrets CRD
* enable controller to unseal immutable secrets
* enable kubeseal to seal immutable secrets

Signed-off-by: Gavin Lam <[email protected]>
  • Loading branch information
gavinkflam committed Dec 1, 2023
1 parent 7b789fd commit 71591eb
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 3 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ In particular, the annotations and labels of a `SealedSecret` resource are not t

To capture this distinction, the `SealedSecret` object has a `template` section which encodes all the fields you want the controller to put in the unsealed `Secret`.

This includes metadata such as labels or annotations, but also things like the `type` of the secret.
This includes metadata such as labels or annotations, but also things like `type` and `immutable` fields of the secret.

```yaml
apiVersion: bitnami.com/v1alpha1
Expand All @@ -131,6 +131,7 @@ spec:
.dockerconfigjson: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq.....
template:
type: kubernetes.io/dockerconfigjson
immutable: true
# this is an example of labels and annotations that will be added to the output secret
metadata:
labels:
Expand Down Expand Up @@ -158,6 +159,7 @@ metadata:
name: mysecret
uid: 5caff6a0-c9ac-11e9-881e-42010aac003e
type: kubernetes.io/dockerconfigjson
immutable: true
data:
.dockerconfigjson: ewogICJjcmVk...
```
Expand Down
4 changes: 4 additions & 0 deletions helm/sealed-secrets/crds/bitnami.com_sealedsecrets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ spec:
description: Used to facilitate programmatic handling of secret
data.
type: string
immutable:
description: 'Immutable, if set to true, ensures that data stored in the Secret cannot be updated (only object metadata can be modified).
If not set to true, the field can be modified at any time. Defaulted to nil.'
type: boolean
type: object
required:
- encryptedData
Expand Down
11 changes: 10 additions & 1 deletion integration/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ func getSecretType(s *v1.Secret) v1.SecretType {
return s.Type
}

func getSecretImmutable(s *v1.Secret) bool {
return *s.Immutable
}

func fetchKeys(ctx context.Context, c corev1.SecretsGetter) (map[string]*rsa.PrivateKey, []*x509.Certificate, error) {
list, err := c.Secrets(*controllerNs).List(ctx, metav1.ListOptions{
LabelSelector: keySelector,
Expand Down Expand Up @@ -555,7 +559,7 @@ var _ = Describe("create", func() {
})
})

Describe("Custom Secret Type", func() {
Describe("Custom template fields", func() {
BeforeEach(func() {
label := fmt.Sprintf("%s/%s", s.Namespace, s.Name)
ciphertext, err := crypto.HybridEncrypt(rand.Reader, pubKey, []byte("{\"auths\": {\"https://index.docker.io/v1/\": {\"auth\": \"c3R...zE2\"}}}"), []byte(label))
Expand All @@ -564,6 +568,8 @@ var _ = Describe("create", func() {
ss.Spec.EncryptedData[".dockerconfigjson"] = base64.StdEncoding.EncodeToString(ciphertext)
delete(ss.Spec.EncryptedData, "foo")
ss.Spec.Template.Type = "kubernetes.io/dockerconfigjson"
ss.Spec.Template.Immutable = new(bool)
*ss.Spec.Template.Immutable = true
})
It("should produce expected Secret", func() {
expected := map[string][]byte{
Expand All @@ -577,6 +583,9 @@ var _ = Describe("create", func() {
Eventually(func() (*v1.Secret, error) {
return c.Secrets(ns).Get(ctx, secretName, metav1.GetOptions{})
}, Timeout, PollingInterval).Should(WithTransform(getSecretType, Equal(expectedType)))
Eventually(func() (*v1.Secret, error) {
return c.Secrets(ns).Get(ctx, secretName, metav1.GetOptions{})
}, Timeout, PollingInterval).Should(WithTransform(getSecretImmutable, Equal(true)))
Eventually(func() (*ssv1alpha1.SealedSecret, error) {
return ssc.BitnamiV1alpha1().SealedSecrets(ns).Get(context.Background(), secretName, metav1.GetOptions{})
}, Timeout, PollingInterval).ShouldNot(WithTransform(getStatus, BeNil()))
Expand Down
4 changes: 3 additions & 1 deletion pkg/apis/sealedsecrets/v1alpha1/sealedsecret_expansion.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,8 @@ func NewSealedSecret(codecs runtimeserializer.CodecFactory, pubKey *rsa.PublicKe
Spec: SealedSecretSpec{
Template: SecretTemplateSpec{
// ObjectMeta copied below
Type: secret.Type,
Type: secret.Type,
Immutable: secret.Immutable,
},
EncryptedData: map[string]string{},
},
Expand Down Expand Up @@ -266,6 +267,7 @@ func (s *SealedSecret) Unseal(codecs runtimeserializer.CodecFactory, privKeys ma
if s.Spec.Data == nil {
s.Spec.Template.ObjectMeta.DeepCopyInto(&secret.ObjectMeta)
secret.Type = s.Spec.Template.Type
secret.Immutable = s.Spec.Template.Immutable

secret.Data = map[string][]byte{}
data := map[string]string{}
Expand Down
7 changes: 7 additions & 0 deletions pkg/apis/sealedsecrets/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ type SecretTemplateSpec struct {
// +optional
Type apiv1.SecretType `json:"type,omitempty" protobuf:"bytes,3,opt,name=type,casttype=SecretType"`

// Immutable, if set to true, ensures that data stored in the Secret cannot
// be updated (only object metadata can be modified).
// If not set to true, the field can be modified at any time.
// Defaulted to nil.
// +optional
Immutable *bool `json:"immutable,omitempty" protobuf:"varint,5,opt,name=immutable"`

// Keys that should be templated using decrypted data.
// +optional
// +nullable
Expand Down
3 changes: 3 additions & 0 deletions schema-v1alpha1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ openAPIV3Schema:
type:
description: Used to facilitate programmatic handling of secret data.
type: string
immutable:
description: 'Immutable, if set to true, ensures that data stored in the Secret cannot be updated (only object metadata can be modified). If not set to true, the field can be modified at any time. Defaulted to nil.'
type: boolean
type: object
required:
- encryptedData
Expand Down

0 comments on commit 71591eb

Please sign in to comment.