UNCLASSIFIED - NO CUI

Skip to content

#9 : Add helm test for external secrets operator

Andrew Kesterson requested to merge 9_helmtests into main

General MR

Summary

This MR adds a helm test that validates external secrets operator is functioning as expected. Some things were NOT included in the scope of this work:

  • Testing integration with AWS, GCP or any other cloud provider
  • Testing integration with Vault or any other secret provider

The only goal of this MR was to validate that the external secrets operator itself is functioning, and that given an appropriately configured secret store, that it will be able to inject secrets into pods as expected. To prove this, the test mocks up a primitive scenario using kubernetes cluster secrets.

(K8s Cluster Secrets) <----- (External Secret Operator) ------> (Pod)

Using this linkage, we can contrive a scenario where a pod requests a value from the External Secrets Operator without knowing anything about the source secret behind ESO, but getting the value we expect

(SECRET testsecret-source)
  ^-- (ESO Cluster SecretStore)
       `--> (SECRET testsecret-target)
             `--> (Pod w/ volumeMount)

The test requires some associated objects to be setup inside the cluster to facilitate the tests (specifically a role, binding, secretstore, secret and externalsecret). This is in the chart/templates/tests/ directory and is only executed when the values key bbtests.enabled = true. The actual test is executed by the pod in chart/templates/tests/eso_mount.yaml, which mounts the external secret as a volume on the filesystem, and checks the content of the secret against a known value from the config.

The configuration for the test is in the values.yaml file under the bbtests key. This was done to make it easier for us to add additional test configuration in the future if we want to add validation against vault, AWS SSM, or whatever. It could be extracted out and hardcoded into the charts/templates/tests/ files instead if we don't think it's worth having it in the values file for the user to muck with.

Relevant logs/screenshots

$ helm test external-secrets -n external-secrets                                                                                                                
NAME: external-secrets                                                                                                                                                                                    
LAST DEPLOYED: Tue May 28 14:37:03 2024                                                                                                                                                                   
NAMESPACE: external-secrets                                                                                                                                                                               
STATUS: pending-install                                                                                                                                                                                   
REVISION: 1                                                                                                                                                                                               
TEST SUITE:     external-secrets-test-secret-mount                                                                                                                                                        
Last Started:   Tue May 28 10:37:32 2024                                                                                                                                                                  
Last Completed: Tue May 28 10:37:47 2024                                                                                                                                                                  
Phase:          Succeeded                                                                                                                                                                                 
NOTES:
external-secrets has been deployed successfully in namespace external-secrets!

In order to begin using ExternalSecrets, you will need to set up a SecretStore
or ClusterSecretStore resource (for example, by creating a 'vault' SecretStore).

More information on the different types of SecretStores and how to configure them
can be found in our Github: https://github.com/external-secrets/external-secrets

The pod runs, mounts the secret, and validates it successfully:

$ kubectl describe pod -n external-secrets external-secrets-test-secret-mount                                                                                                                             
Name:             external-secrets-test-secret-mount                                                                                                                                                      
Namespace:        external-secrets                                                                                                                                                                        
Priority:         0                                                                                                                                                                                       
Service Account:  default                                                                                                                                                                                 
Node:             k3d-k3s-default-agent-2/172.20.0.5                                                                                                                                                      
Start Time:       Tue, 28 May 2024 10:37:36 -0400                                                                                                                                                         
Labels:           <none>                                                                                                                                                                                  
Annotations:      helm.sh/hook: test                                                                                                                                                                      
Status:           Succeeded                                                                                                                                                                               
IP:               10.42.2.5                                                                                                                                                                               
IPs:                                                                                                                                                                                                      
  IP:  10.42.2.5                                                                                                                                                                                          
Containers:                                                                                                                                                                                               
  external-secrets-test-secret-mount:                                                                                                                                                                     
    Container ID:  containerd://a53fbffc07e8c58f8c808034105a6d3667e9c650aa3bada0eb555f161c445a3e                                                                                                          
    Image:         busybox                                                                                                                                                                                
    Image ID:      docker.io/library/busybox@sha256:5eef5ed34e1e1ff0a4ae850395cbf665c4de6b4b83a32a0bc7bcb998e24e7bbb
    Port:          <none>
    Host Port:     <none>
    Command:
      /bin/grep
    Args:
      this is a magic value
      /tmp/externalsecrets/secretkey
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Start         False
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /tmp/externalsecrets from externalsecrets (ro)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-5879h (ro)
Conditions:
  Type                        Status
  PodReadyToStartContainers   False
  Initialized                 True
  Ready                       False
  ContainersReady             False
  PodScheduled                True
Volumes:
  externalsecrets:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  testsecret-target
    Optional:    false
  kube-api-access-5879h:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecufor 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  35m   default-scheduler  Successfully assigned external-secrets/external-secrets-test-secret-mount to k3d-k3s-default-agent-2
  Normal  Pulling    35m   kubelet            Pulling image "busybox"
  Normal  Pulled     35m   kubelet            Successfully pulled image "busybox" in 1.763s (1.763s including waiting)
  Normal  Created    35m   kubelet            Created container external-secrets-test-secret-mount
  Normal  Started    35m   kubelet            Started container external-secrets-test-secret-mount

... and we can see the external secret is created in the appropriate secret store and that the target the pod is pulling from is only the ESO frontend for the source, which proves that ESO is doing its job

$ kubectl get secretstore -n external-secrets
NAME                          AGE   STATUS   CAPABILITIES   READY
external-secrets-test-store   38m   Valid    ReadWrite      True

$ kubectl describe externalsecret -n external-secrets testsecret
Name:         testsecret
Namespace:    external-secrets
Labels:       app.kubernetes.io/managed-by=Helm
              helm.toolkit.fluxcd.io/name=external-secrets
              helm.toolkit.fluxcd.io/namespace=external-secrets
Annotations:  meta.helm.sh/release-name: external-secrets
              meta.helm.sh/release-namespace: external-secrets
API Version:  external-secrets.io/v1beta1
Kind:         ExternalSecret
Metadata:
  Creation Timestamp:  2024-05-28T14:37:07Z
  Generation:          1
  Resource Version:    1168
  UID:                 569d7e49-5cab-4f4a-94da-1b87df937988
Spec:
  Data:
    Remote Ref:
      Conversion Strategy:  Default
      Decoding Strategy:    None
      Key:                  testsecret-source
      Metadata Policy:      None
      Property:             secretkey
    Secret Key:             secretkey
  Refresh Interval:         1h
  Secret Store Ref:
    Kind:  SecretStore
    Name:  external-secrets-test-store
  Target:
    Creation Policy:  Owner
    Deletion Policy:  Retain
    Name:             testsecret-target
Status:
  Binding:
    Name:  testsecret-target
  Conditions:
    Last Transition Time:   2024-05-28T14:37:13Z
    Message:                Secret was synced
    Reason:                 SecretSynced
    Status:                 True
    Type:                   Ready
  Refresh Time:             2024-05-28T14:37:13Z
  Synced Resource Version:  1-fc08bb16d79a4d4e355bb0cf71c0aed5
Events:
  Type     Reason        Age                From              Message
  ----     ------        ----               ----              -------
  Normal   Created       39m                external-secrets  Created Secret

$ kubectl get secret -n external-secrets testsecret-source -o yaml
apiVersion: v1
data:
  secretkey: dGhpcyBpcyBhIG1hZ2ljIHZhbHVl
kind: Secret
metadata:
  annotations:
    meta.helm.sh/release-name: external-secrets
    meta.helm.sh/release-namespace: external-secrets
  creationTimestamp: "2024-05-28T14:37:07Z"
  labels:
    app.kubernetes.io/managed-by: Helm
    helm.toolkit.fluxcd.io/name: external-secrets
    helm.toolkit.fluxcd.io/namespace: external-secrets
  name: testsecret-source
  namespace: external-secrets
  resourceVersion: "1025"
  uid: 440728cc-c92d-4afc-bed2-a76eddaa5692
type: Opaque

Linked Issue

Closes #9 (closed)

Upgrade Notices

N/A

Edited by Andrew Kesterson

Merge request reports