Docs
Welcome to the documentation. The code and chart is avalible at github.com.
The purpose of this Operator is to create secrets from a CRD resource. This resource contains the encrypted secrets. As the name suggests, it uses age to decrypt secrets. The controller will create keys in the namespaces you specify. You can use these keys to encrypt your secrets, store them in Git or elsewhere, and apply them to the cluster. The controller will then check the encrypted secrets and decrypt them, creating a Kubernetes Secret from them.
The controller also exposes metrics, which can be monitored by creating a ServiceMonitor with the chart if desired. Additionally, a GUI is available that allows you to encrypt and decrypt secrets interactively. A CLI tool is also planned, which will allow users to perform encryption and decryption directly from the command line.
In addition, this Operator was created to address Bitnami’s recent licensing changes affecting Helm charts and images. Although Bitnami states that the SealSecrets Operator chart and images will remain free, it’s unclear what Broadcom might do next.
The way their Operator was built did not feel right to me. Their tools often contain multiple CVEs, and the CRDs they create are not the sole source of truth. For example, manually changing a secret can affect the CRDs, which will then report that they are no longer managed by SealSecrets. In my opinion, if you deploy CRDs, they should be the only source of truth. Any updates should be made through the CRDs themselves, not the resources created from them.
This project was initialized using Kubebuilder, a common tool used by most developers building an Operator. All code comments are generated by Kubebuilder. I initially removed the default commented-out code but later re-added it as optional features. This way, anyone who wants to fork the project can make use of these features if needed.
I also consulted AI at certain points to get ideas for implementation. Suggestions are never blindly copied. Each one is reviewed and applied if needed.
Note: I am relatively new to Go, so contributions and feedback are welcome!
Getting started
- create crd ressource
- crd has to be applied before using helm to install
kubectl apply -f https://raw.githubusercontent.com/callmewhatuwant/age-secret-operator/refs/heads/main/config/crd/bases/security.age.io_agesecrets.yaml
- install
helm repo add age-secrets-operator \
https://age-secrets.com
helm install age-secrets-operator age-secrets-operator/age-secrets \
--namespace age-system --create-namespace
- check install
- uninstall
First secret
- install age
- get key
LATEST=$(kubectl get secrets -n age-system --no-headers -o custom-columns=":metadata.name" \
| grep '^age-key-' | sort | tail -n1)
PUBLIC_KEY=$(kubectl get secret "$LATEST" -n age-system -o jsonpath='{.data.public}' | base64 --decode)
## public key:
echo "$PUBLIC_KEY"
- encrypt with ur public key
- create namespace for testing the crd
- exmaple secret crd ressource
- change password: value with your value from the age command
apiVersion: security.age.io/v1alpha1
kind: AgeSecret
metadata:
name: db-passwd
namespace: test
spec:
encryptedData:
password: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWbHhqcGhyZ0ZSbXhQZXJ1
aU1kL1NmZjYyaU9JQXlQazBuekdmMk8ySkYwCkloMGJxR0lXVG0yM2FXV3hrT3BI
OXVwdzhrYWtGU0hwTUtLTHN5dzJBTGsKLS0tIEc0V1JmTUVpWkZuNGFGWXJJV3ow
cWZpL09JTnFCVFFZbXRFQUY2QTdTbm8KdkZOvCXRqENpCw9ncrVP+qzDBTKwntfi
ihgfMGuoy3Q37Dkqsw==
-----END AGE ENCRYPTED FILE-----
# define public key used with: recipients if you want to
# the controller will try this key first
# recipients:
# - string
- verify
Helm Options
## name override
fullnameOverride: age-secret-controller
## namespaces in wich new keys will be generated
## controller will also check in them for keys to decrypt
keyNamespaces: "age-secrets,test"
## controller values
ageSecretController:
## leader election
leaderElection:
enabled: true
namespace: age-system
## replicas for ha
replicas: 3
# strategy for updating
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: "25%"
maxUnavailable: "50%"
controller:
## image
image:
repository: callmewhatuwant/age-secrets-operator
tag: 0.0.01
imagePullPolicy: IfNotPresent
## resources
resources:
limits:
cpu: 200m
memory: 128Mi
requests:
cpu: 100m
memory: 64Mi
## security
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
seccompProfile:
type: "RuntimeDefault"
runAsNonRoot: true
privileged: false
runAsUser: 65532
runAsGroup: 65532
## prometheus
metricsService:
bindAddress: 8443
secure: true
auth: false
type: ClusterIP
ports:
- port: 8443
name: metrics
targetPort: 8443
## monitor for prometheus
ServiceMonitor:
enabled: false
endpoints:
- port: metrics
scheme: https
interval: 30s
path: /metrics
tlsConfig:
insecureSkipVerify: true
serverName: localhost
## job
ageKeyRotation:
schedule: "0 0 1 * *"
## initial key
initialRun:
enabled: true
## image for cron and init job
image:
repository: callmewhatuwant/age-job
tag: "3.23.0"
pullPolicy: IfNotPresent
## gui
ageGui:
enabled: true
# replicas (ha is not tested)
replicas: 1
# strategy for updating
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: "25%"
maxUnavailable: "50%"
# image for gui
image:
repository: callmewhatuwant/age-gui
tag: "alpine3.23-perl"
pullPolicy: IfNotPresent
resources:
limits:
cpu: 200m
memory: 128Mi
requests:
cpu: 100m
memory: 64Mi
#sec context
containerSecurityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
seccompProfile:
type: "RuntimeDefault"
runAsNonRoot: true
privileged: false
runAsUser: 101
runAsGroup: 101
# service for gui
service:
type: ClusterIP
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
# ingress for gui
ingress:
enabled: false
host: age-gui.local
ingressClassName: nginx
annotations: {}
tls: []
# - hosts:
# - age-gui.local
# secretName: age-gui-tls
Enhancements
- Open a merge request if you want to contribute to the project.
- The project just started, so there’s probably a lot to improve.
- Please don’t be too harsh on me. 🙂
Issue
- Found a bug or have a feature request?
- Please open an issue on github.com.
Other projects by me
- my portfolio portfolio-nick.de
Support me if you want
BTC:
Solana: