Git Product home page Git Product logo

kubernetes-secret-generator's Introduction

Automatically generated secrets for Kubernetes

This repository contains a custom Kubernetes controller that can automatically create random secret values. This may be used for auto-generating random credentials for applications run on Kubernetes.

Security note

Older versions (<= 1.0.0) of this controller used the math/rand package for generating secrets, which is deterministic and not cryptographically secure (see #1 for more information). If you're already running this controller and want to regenerate all potentially compromised secrets, start the controller with the -regenerate-insecure flag (note that you will need to manually re-create any Pods using these secrets, though). When using the kubectl apply command from below, the new flag will be added to your Deployment automatically.

License

Copyright 2023 Mittwald CM Service GmbH & Co. KG and contributors

This project is licensed under the Apache License, Version 2.0.

Deployment

Helm

The controller can be deployed using Helm.

You might want to take a look a the values.yaml to adjust the operator to your needs:

  • secretLength defines the length of the generated secret values.

  • watchNamespace defines, which namespaces should be watched for secret objects.

  • useMetricsService toggles whether the operator should provide a service for metrics monitoring by Prometheus. If this is set to true, the operator will start with additional permissions, namely get permissions for replicasets and deployments in the apiGroup apps, as well as create permissions for services and create the needed services during startup.

    To watch a single namespace, set it to the desired namespace name. Multiple namespaces are supported and can be set as a comma-separated list: ns1,ns2.

    If watchNamespace is set to the empty string value "", all namespaces will be watched.

  • rbac.create controls if rbac resources are deployed.

  • rbac.clusterRole controls if secrets generator has permission to watch secrets in namespaces other than where it has been deployed.

    rbac.clusterRole=false & watchNamespace="" will result in watchNamespace being set to the current namespace as this is all the permissions will allow access to.

Afterwards, deploy the operator using:

  1. Add the Mittwald Charts Repo:

    $ helm repo add mittwald https://helm.mittwald.de
    "mittwald" has been added to your repositories
    
    $ helm repo update
    Hang tight while we grab the latest from your chart repositories...
    ...Successfully got an update from the "mittwald" chart repository
    Update Complete. ⎈ Happy Helming!⎈
  2. Upgrade or install kubernetes-secret-generator:

    $ helm upgrade --install kubernetes-secret-generator mittwald/kubernetes-secret-generator

Manually

If you don't want to use Helm (why wouldn't you?), the required .yaml files can also be applied manually using kubectl apply:

$ make install

To uninstall, use:

$ make uninstall

Usage

This operator is capable of generating secure random strings and ssh keypair secrets.

It supports two ways of secret generation, annotation-based and cr-based.

Annotation-based generation

For annotation based generation, the type of secret to be generated can be specified by the secret-generator.v1.mittwald.de/type annotation. This annotation can be added to any Kubernetes secret object in the operators watchNamespace.

The encoding of the secret can be specified by the secret-generator.v1.mittwald.de/encoding annotation. Available encodings are base64, base64url, base32, hex and raw, with raw returning the unencoded byte sequence that was generated. base64 will be used, if the annotation was not used.

The length of the generated secret can be specified by the secret-generator.v1.mittwald.de/length annotation. By default, this length refers to the length of the generated string, and not the length of the byte sequence encoded by it. The suffix B or b can be used to indicate that the provided value should refer to the encoded byte sequence instead.

Secure Random Strings

By default, the operator will generate secure random strings. If the type annotation is not present, it will be added after the first reconciliation loop and its value will be set to string.

To actually generate random string secrets, the secret-generator.v1.mittwald.de/autogenerate annotation is required as well. The value of the annotation can be a field name (or comma separated list of field names) within the secret; the SecretGeneratorController will pick up this annotation and add a field [or fields] (password in the example below) to the secret with a randomly generated string value.

apiVersion: v1
kind: Secret
metadata:
  name: string-secret
  annotations:
    secret-generator.v1.mittwald.de/autogenerate: password
data:
  username: c29tZXVzZXI=

after reconciliation:

apiVersion: v1
kind: Secret
metadata:
  name: string-secret
  annotations:
    secret-generator.v1.mittwald.de/type: string
    secret-generator.v1.mittwald.de/secure: "yes"
    secret-generator.v1.mittwald.de/autogenerate: password
    secret-generator.v1.mittwald.de/autogenerate-generated-at: "2020-04-03T14:07:47+02:00"
type: Opaque
data:
  username: c29tZXVzZXI=
  password: TWVwSU83L2huNXBralNTMHFwU3VKSkkwNmN4NmRpNTBBcVpuVDlLOQ==

SSH Key Pairs

To generate SSH Key Pairs, the secret-generator.v1.mittwald.de/type annotation has to be present on the kubernetes secret object.

The operator will then add two keys to the secret object, ssh-publickey and ssh-privatekey, each containing the respective key.

The Private Key will be PEM encoded, the Public Key will have the authorized-keys format.

apiVersion: v1
kind: Secret
metadata:
  annotations:
    secret-generator.v1.mittwald.de/type: ssh-keypair
data: {}

after reconciliation:

apiVersion: v1
kind: Secret
metadata:
  annotations:
    secret-generator.v1.mittwald.de/type: ssh-keypair
    secret-generator.v1.mittwald.de/autogenerate-generated-at: "2020-04-03T14:07:47+02:00"
type: Opaque
data:
  ssh-publickey: c3NoLXJzYSBBQUFBQ...
  ssh-privatekey: LS0tLS1CRUdJTi...

Ingress Basic Auth

To generate Ingress Basic Auth credentials, the secret-generator.v1.mittwald.de/type annotation has to be present on the kubernetes secret object.

The operator will then add three keys to the secret object. The ingress will interpret the auth key as a htpasswd entry. This entry contains the username, and the hashed generated password for the user. The operator also stores the username and cleartext password in the username and password keys.

If a username other than admin is desired, it can be specified using the secret-generator.v1.mittwald.de/basic-auth-username annotation.

apiVersion: v1
kind: Secret
metadata:
  annotations:
    secret-generator.v1.mittwald.de/type: basic-auth
data: {}

after reconciliation:

apiVersion: v1
kind: Secret
metadata:
  annotations:
    secret-generator.v1.mittwald.de/type: basic-auth
    secret-generator.v1.mittwald.de/autogenerate-generated-at: "2020-04-03T14:07:47+02:00"
type: Opaque
data:
  username: admin
  password: test123
  auth: "admin:PASSWORD_HASH"

CR-based generation

The operator supports three kinds of custom resources: StringSecret, SSHKeyPair and BasicAuth. These crs can be used to trigger creation, update and deletion of desired secrets. All crs support the field spec.type which can be used to define the kubernetes type of the generated Secret, e.g. "Opaque"

Secure Random Strings via StringSecret-CR

A StringSecret resource can be used to generate secure random strings similar to the ones offered by the annotation approach. Desired Fields to be randomly generated can be supplied via the spec.fields property, which can be used to specify a list of fields with individual encoding and length values, e.g. a hex-encoded string of length 15 and a base64-encoded string of length 40 can be defined in the same secret object. The spec.data property can be used to specify arbitrary data entries the generated secret's data property should be populated with. Finally, the spec.forceRegenerate property can be used to control regeneration of secret fields.

Example:

apiVersion: "secretgenerator.mittwald.de/v1alpha1"
kind: "StringSecret"
metadata:
  name: "example-pw"
  namespace: "default"
spec:
  forceRegenerate: false
  data:
    username: "testuser"
  fields:
    - fieldName: "test"
      encoding: "hex"
      length: "15"

Upon creation of the cr, the controller will attempt to create a Secret resource matching the specifications. If successful, the new resource will have its owner set as the StringSecret used to create it, providing automated deletion/updating of the secret if the creating cr is deleted/updated. The StringSecret will store an object reference to the created Secret in its status field. During updating, any new fields in spec.data and spec.fields will be added, while existing fields will only be overwritten/regenerated if spec.forceRegenerate is set to true. If the target Secret already exists and is not owned by a StringSecret resource, no changes will be made to ìt.

SSH Key Pair via SSHKeyPair-CR

A SSHKeyPair resource can be used to generate an ssh key pair. It supports spec.length, spec.data and spec.forceRegenerate similar to StringSecret resources. The field spec.privateKey can be used to specify a private key, which will be used during runtime to regenerate a matching public key. Updating is handled similar to StringSecret resources, unowned Secrets are not modified, and existing fields are only updated if regeneration is forced. However, should the public key be missing, the operator will attempt to regenerate it.

apiVersion: "secretgenerator.mittwald.de/v1alpha1"
kind: "SSHKeyPair"
metadata:
  name: "example-ssh"
  namespace: "default"
spec:
  length: "40"
  forceRegenerate: false
  data:
    example: "data"

Ingress Basic Auth via BasicAuth-CR

A BasicAuth resource can be used to generate Ingress Basic Auth credentials. Supported properties are spec.length, spec.encoding, spec.data and spec.forceRegenerate. To specify a username, use spec.username. If no username is provided, the operator will use admin. Updates follow the same rules as for the other crs, existing secrets will only be updated if owned by a BasicAuth resource and if spec.forceRegenerate is set to true. The exception to this are new spec.data entries, which are added even if forceRegenerate is false, and cases where the auth field in the Secret is empty.

apiVersion: "secretgenerator.mittwald.de/v1alpha1"
kind: "BasicAuth"
metadata:
  name: "example-auth"
  namespace: "default"
spec:
  length: "40"
  username: "testuser"
  encoding: "base64"
  forceRegenerate: false
  data:
    example: "data"

Operational tasks

  • Regenerate all automatically generated secrets:

    $ kubectl annotate secrets --all secret-generator.v1.mittwald.de/regenerate=true
    
  • Regenerate only certain fields, in case the secret is of the password type:

    $ kubectl annotate secrets --all secret-generator.v1.mittwald.de/regenerate=password1,password2
    

kubernetes-secret-generator's People

Contributors

aiceball avatar day1118 avatar elenz97 avatar frankkkkk avatar gilles-gosuin avatar gysi avatar hensur avatar hermsi1337 avatar jamct avatar jkmw avatar johannes- avatar martin-helmich avatar mattmattox avatar michaelfeinbier avatar mittwald-machine avatar nicolas-geniteau avatar ptcar2009 avatar u8sand avatar yannikbramkamp avatar yinzara avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kubernetes-secret-generator's Issues

Go Versioning

Describe the bug

Because the project is tagged v3 and has a go.mod file, Go expects the module path to include the major version:

I can appreciate that you ship this project as Helm + Docker images, but I'd like to incorporate the Go API into my deploy process, which involves starting with go get

To Reproduce

⮀ go get github.com/mittwald/kubernetes-secret-generator/pkg/apis/secretgenerator/[email protected]
go: github.com/mittwald/kubernetes-secret-generator/pkg/apis/secretgenerator/[email protected]: github.com/mittwald/[email protected]: invalid version: module contains a go.mod file, so module path must match major version ("github.com/mittwald/kubernetes-secret-generator/v3")

List on OperatorHub.io?

I've found OperatorHub.io to be quite useful for having a "package manager" for operators, without going down the whole Helm path. I had a shot at generating a definition for what this would look like on the site, but didn't want to publish it if I wasn't the owner!

secret-generator.package.yaml

packageName: secret-generator
channels:
  - name: stable
    currentCSV: secret-generator.v2.1.1

secret-generator.v2.1.1.clusterserviceversion.yaml

apiVersion: operators.coreos.com/v1alpha1
kind: ClusterServiceVersion
metadata:
  name: secret-generator.v2.1.1
  namespace: placeholder
  annotations:
    alm-examples: '[]'
    categories: 'Security, Developer Tools'
    certified: 'false'
    createdAt: ''
    description: >-
      A controller that can automatically create random secret values. This may
      be used for auto-generating random credentials for applications run on
      Kubernetes.
    containerImage: ''
    support: ''
    capabilities: Basic Install
    repository: ''
spec:
  displayName: Secret Generator
  description: >+
    This operator generates random secret values, such as passwords. It also
    provides functionality to regenerate these values easily.

    ## Operator Usage


    Add the annotation `secret-generator.v1.mittwald.de/autogenerate` to any
    Kubernetes secret object. The value of the annotation can be a field name
    (or comma separated list of field names) within the secret; the
    SecretGeneratorController will pick up this annotation and add a field \[or
    fields] (password in the example below) to the secret with a randomly
    generated string value.


    ```

    apiVersion: v1

    kind: Secret

    metadata:
      annotations:
        secret-generator.v1.mittwald.de/autogenerate: password
    data:
      username: c29tZXVzZXI=
    ```


    Operational tasks:

    * Regenerate all automatically generator passwords:

      `$ kubectl annotate secrets --all secret-generator.v1.mittwald.de/regenerate=true`
    * Regenerate only certain fields:

      `$ kubectl annotate secrets --all secret-generator.v1.mittwald.de/regenerate=password1,password2`

  maturity: stable
  version: 2.1.1
  replaces: ''
  minKubeVersion: ''
  keywords:
    - secrets
  maintainers:
    - name: ''
      email: ''
  provider:
    name: Mittwald CM Service
  labels: {}
  selector:
    matchLabels: {}
  links:
    - name: Repo
      url: 'https://github.com/mittwald/kubernetes-secret-generator'
  icon:
    - base64data: ''
      mediatype: ''
  customresourcedefinitions:
    owned: []
    required: []
  install:
    strategy: deployment
    spec:
      permissions: []
      clusterPermissions:
        - serviceAccountName: secret-generator
          rules:
            - apiGroups: '""'
              resources:
                - secrets
              verbs:
                - get
                - watch
                - list
                - update
      deployments:
        - name: secret-generator-deployment
          spec:
            replicas: 1
            selector:
              matchLabels:
                app: secret-generator
            template:
              metadata:
                labels:
                  app: secret-generator
              spec:
                serviceAccountName: secret-generator
                containers:
                  - name: secret-generator
                    image: 'quay.io/mittwald/kubernetes-secret-generator:latest'
                    command:
                      - /kubernetes-secret-generator
                    args:
                      - '-logtostderr'
                      - '-all-namespaces'
                      - '-regenerate-insecure'
  installModes:
    - type: OwnNamespace
      supported: false
    - type: SingleNamespace
      supported: false
    - type: MultiNamespace
      supported: false
    - type: AllNamespaces
      supported: true

Allow Customization of ssh-privatekey and ssh-publickey for SSHKeyPair

Is your feature request related to a problem? Please describe.

For compatibility with using deploy keys with ArgoCD it is necessary to be able to generate SSH keypair secrets with data sshPrivateKey rather than the default ssh-privatekey.

Other use cases may also require the SSH public and private keys to use custom data names.

Describe the solution you'd like

Perhaps add spec.sshPrivateKeyDataName and spec.sshPublicKeyDataName to SSHKeyPair custom resource to allow overriding the defaults?

Describe alternatives you've considered

I've been unable to come up with a reasonable alternative.

Additional context

n/a

Add support for replacement of secret values

Is your feature request related to a problem? Please describe.

Software like matrix-synapse expects a yaml file for the postgres configuration.
The generated secret should be both consumable by postgres (reading from an environment variable) as well as from matrix-synapse.

Describe the solution you'd like

One of the easiest versions to support this would be by something on the lines of templating, aka sed aka helm alike:

apiVersion: v1
kind: Secret
metadata:
  name: string-secret
  annotations:
    secret-generator.v1.mittwald.de/replace: PASSWORD
stringData:
  dbconfig: |
    database:
      name: psycopg2
      args:
        user: synapse_user
        password: PASSWORD
  POSTGRES_PW: PASSWORD

Describe alternatives you've considered

Not sure which other ways are there to support one value that needs to be formatted differently.

Additional context

The main problem is that different software is bound, but uses different formatting. Matrix Synapse and postgresql is a good example, but the new libpq feature for managing passwords, which is now used in Django 4.0 is another one:

The secret should contain:

hostname:port:database:username:password

as a value.
The username and password might be generated by the generator, whereas hostname/port/database is likely coming from something like helm/argocd/etc.

However, that file needs to be generated and above solution could solve this, too:

apiVersion: v1
kind: Secret
metadata:
  name: string-secret
  annotations:
    secret-generator.v1.mittwald.de/replace: PASSWORD, USERNAME
stringData:
  pgpass: |
    hostname:port:database:USERNAME:PASSWORD
  POSTGRES_PW: PASSWORD
  POSTGRES_USER: USERNAME

The lower two can be injected into the postgres container, pgpass can be injected into the client (f.i. django) container.

See also:

Allow passing custom annotations to CR-generated secrets

Is your feature request related to a problem? Please describe.
When using secrets generated by CR definitions I am unable to add custom annotations at deployment time.
Custom annotations on generated secrets are useful when using something like reflector.

On old-format (annotation-based) secrets that was not a problem, however CR-based secrets are much cleaner for GitOps diffing.

Describe the solution you'd like
Allow passing annotations from CR definitions to generated secrets, something like:

apiVersion: "secretgenerator.mittwald.de/v1alpha1"
kind: "StringSecret"
metadata:
  name: "example-pw"
  namespace: "default"
spec:
  annotations:
    <insert your custom annotations for the created secret here>
  forceRegenerate: false
  data:
    username: "testuser"
  fields:
    - fieldName: "test"
      encoding: "hex"
      length: "15"

Describe alternatives you've considered
Falling back onto annotation-based secret generation, but inconvenient when using GitOps, as the diffs are detected as out of sync.

Cut a release

Could anyone please cut a release to generate a new image tag with the latest fixes?

Feature Request: Enhancing SSHKeyPair Generation with Customizable Algorithms and Options

First of all, I would like to extend my deepest gratitude and respect for your incredible work on the mittwald/kubernetes-secret-generator project. Your efforts have significantly contributed to the Kubernetes community, making secret management more secure and convenient.

Is your feature request related to a problem? Please describe.

Yes, the current limitation is the lack of customization in the SSHKeyPair generation within the mittwald/kubernetes-secret-generator project. The inability to specify a preferred encryption algorithm and key options restricts users who have specific security, compliance, or performance requirements. This limitation can be frustrating for users who need to adhere to strict security policies or who wish to optimize their SSH keys for specific environments.

Describe the solution you'd like
A clear and concise description of what you want to happen.

I would like the project to include a feature that allows users to customize the SSHKeyPair generation process. Specifically, the ability to choose the encryption algorithm (e.g., RSA, ECDSA, Ed25519) and set relevant options like key size. This feature would empower users to generate keys that meet their specific security and performance requirements, ensuring compliance with various standards and enhancing the overall utility of the tool.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

An alternative could be to use external tools to generate SSH keys according to the desired specifications and then manually integrate them into the Kubernetes environment. However, this approach is less efficient and could lead to inconsistencies or errors in key management.

Additional context
Add any other context or screenshots about the feature request here.

Adding this feature would align the project with best practices in security and infrastructure management, catering to a broader range of user needs and compliance requirements.

Secrets generated from custom resources don't use the default controller's encoding

Describe the bug
When kubernetes-secret-generator controller is explicitly configured to use some encoding different from base64 then the secrets generated from custom resources with no encoding field specified are still created with base64 encoding.

To Reproduce

  1. Deploy kubernetes-secret-generator controller with the parameter to use e.g. hex encoding by default.
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kubernetes-secret-generator
  namespace: kube-system
  labels:
    app: kubernetes-secret-generator
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: kubernetes-secret-generator
  template:
    metadata:
      labels:
        app: kubernetes-secret-generator
    spec:
      serviceAccountName: kubernetes-secret-generator
      containers:
      - name: kubernetes-secret-generator
        image: quay.io/mittwald/kubernetes-secret-generator:v3.3.4
        command:
        - kubernetes-secret-generator
        ports:
        - containerPort: 8080
          name: http
        env:
        - name: WATCH_NAMESPACE
          value: ''
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: OPERATOR_NAME
          value: kubernetes-secret-generator
        - name: SECRET_ENCODING
          value: hex
  1. Create a custom resource for string secret with no encoding specified.
apiVersion: secretgenerator.mittwald.de/v1alpha1
kind: StringSecret
metadata:
  name: the-secret-crd
spec:
  fields:
  - fieldName: password
  1. Check the encoding of the generated secret (it is not the hex encoding which is configured for controller):
$ kubectl get secret the-secret-crd -o jsonpath='{.data.password}' | base64 --decode
wjjH7N8AJqOSL4UXIo46sYJHuy9pPYYd+j4evnoe

Expected behavior
The expected behaviour is similar to the secrets which items are generated with the annotations - the default encoding is used if no secret-generator.v1.mittwald.de/encoding annotation is specified. E.g. this is the password generated in the secret generated with annotations:

$ kubectl describe secret the-secret
Name:         the-secret
Namespace:    default
Labels:       <none>
Annotations:  secret-generator.v1.mittwald.de/autogenerate: password
              secret-generator.v1.mittwald.de/autogenerate-generated-at: 2021-11-23T13:25:22Z
              secret-generator.v1.mittwald.de/secure: yes
              secret-generator.v1.mittwald.de/type: string

Type:  Opaque

Data
====
password:  40 bytes

$ kubectl get secret the-secret -o jsonpath='{.data.password}' | base64 --decode
a9838164a615daa23a2731aedc36ece46021e6da

Environment:

  • Kubernetes version: 1.20.12
  • kubernetes-secret-generator version: v3.3.4

Unable to perform a rolling upgrade

Describe the bug
Unable to perform a rolling upgrade: new pods are never marked ready because the liveness probe fails continuously.

To Reproduce

  1. Install with helm helm upgrade --install kubernetes-secret-generator mittwald/kubernetes-secret-generator --version 3.3.2
  2. Try to perform any upgrade, e.g. by changing a value helm upgrade --install kubernetes-secret-generator mittwald/kubernetes-secret-generator --version 3.3.2 --set secretLength=50

The deployment will try to create a new pod, but the container will enter a crash loop and never become ready:

$ kubectl get po
NAME                                           READY   STATUS             RESTARTS   AGE
kubernetes-secret-generator-6f79f56667-v8n7l   0/1     CrashLoopBackOff   6          4m41s
kubernetes-secret-generator-b55758744-hts96    1/1     Running            0          6m32s
$ kubectl describe po kubernetes-secret-generator-6f79f56667-v8n7l
Name:         kubernetes-secret-generator-6f79f56667-v8n7l
(...)
Events:
  Type     Reason     Age                From               Message
  ----     ------     ----               ----               -------
  Normal   Scheduled  55s                default-scheduler  Successfully assigned default/kubernetes-secret-generator-6f79f56667-v8n7l to docker-desktop
  Normal   Pulled     52s                kubelet            Successfully pulled image "quay.io/mittwald/kubernetes-secret-generator:v3.3.2" in 1.3045537s
  Normal   Started    41s (x2 over 52s)  kubelet            Started container kubernetes-secret-generator
  Normal   Pulled     41s                kubelet            Successfully pulled image "quay.io/mittwald/kubernetes-secret-generator:v3.3.2" in 1.3209008s
  Normal   Pulling    31s (x3 over 54s)  kubelet            Pulling image "quay.io/mittwald/kubernetes-secret-generator:v3.3.2"
  Warning  Unhealthy  31s (x6 over 49s)  kubelet            Liveness probe failed: Get "http://10.1.0.11:8080/healthz": dial tcp 10.1.0.11:8080: connect: connection refused
  Warning  Unhealthy  31s (x6 over 49s)  kubelet            Readiness probe failed: Get "http://10.1.0.11:8080/readyz": dial tcp 10.1.0.11:8080: connect: connection refused
  Normal   Killing    31s (x2 over 43s)  kubelet            Container kubernetes-secret-generator failed liveness probe, will be restarted
  Normal   Pulled     30s                kubelet            Successfully pulled image "quay.io/mittwald/kubernetes-secret-generator:v3.3.2" in 1.2851037s
  Normal   Created    29s (x3 over 52s)  kubelet            Created container kubernetes-secret-generator

Container logs:

$ kubectl logs kubernetes-secret-generator-6f79f56667-v8n7l
{"level":"info","ts":1629819473.2746468,"logger":"cmd","msg":"Operator Version: 0.0.1"}
{"level":"info","ts":1629819473.2746885,"logger":"cmd","msg":"Go Version: go1.15.14"}
{"level":"info","ts":1629819473.2746935,"logger":"cmd","msg":"Go OS/Arch: linux/amd64"}
{"level":"info","ts":1629819473.2746956,"logger":"cmd","msg":"Version of operator-sdk: v0.16.0"}
{"level":"info","ts":1629819473.276408,"logger":"leader","msg":"Trying to become the leader."}
{"level":"info","ts":1629819473.8457088,"logger":"leader","msg":"Found existing lock","LockOwner":"kubernetes-secret-generator-b55758744-hts96"}
{"level":"info","ts":1629819473.8563178,"logger":"leader","msg":"Not the leader. Waiting."}
{"level":"info","ts":1629819474.994521,"logger":"leader","msg":"Not the leader. Waiting."}
{"level":"info","ts":1629819477.3851807,"logger":"leader","msg":"Not the leader. Waiting."}
{"level":"info","ts":1629819481.9319456,"logger":"leader","msg":"Not the leader. Waiting."}

If I manually kill the old instance, the new pod is able to become the leader and to start successfully.

Add CRDs as alternative to annotations.

Is your feature request related to a problem? Please describe.
We use ArgoCD for our Deployments. The problem with the Annotations approach is, that we have to ignore diffs for the generated secrets which is not ideal. Also, with every sync, the password is being regenerated, because ArgoCD applies the Annotation stanza, which causes the secret to be regenerated, because the annotation contains the status.

Describe the solution you'd like
I think it would be ideal if secret generator would offer CRDs similar to this project: https://github.com/vmware-tanzu/carvel-secretgen-controller.

Describe alternatives you've considered
I didn't consider any alternatives yet. I think for this particular issue, using CRD's is the only way. We need to store the output of the reconciler in a status field rather than the annotation.

Additional context
Add any other context or screenshots about the feature request here.

Make secret key for basic-auth string customizable

Is your feature request related to a problem? Please describe.
I would like to use the secret generator for generating a basic auth secret, but I am using Traefik as an ingress controller. Traefik requires the secret key for the basic auth string to be users, so I cannot use a generated secret from the controller.

Describe the solution you'd like
I would like an annotation that allows me to adjust the secret key, so I could have users: instead of the current default auth: key. Probably something like secret-generator.v1.mittwald.de/httpwd-secretkey.

Describe alternatives you've considered
Right now I am copying the content of the generated secret manually to another secret.

Additional context
The feature could probably be implemented similar to the optional username other than admin that can be provided via the annotation.

Add support for wireguard keys

Is your feature request related to a problem? Please describe.

If one wants to run Wireguard VPN servers, they need keys generated by wg genkey.

Describe the solution you'd like

A new annotation to support wireguard keys

Describe alternatives you've considered

Using a normal password and feeding it as a seed to wg genkey, however wg genkey does not support any parameters.

Additional context

This is very similar to ssh keys as the application is also pub/private key.
For the format/verification see my last message on https://lists.zx2c4.com/pipermail/wireguard/2020-December/006221.html

Operator pod stuck in CrashLoopBackOff state

Describe the bug
Pod rebooted several times.

kubernetes-secret-generator-599bf5594b-kpsmq     0/1     CrashLoopBackOff    5444       10d

Seeing following log,

kubectl logs -n mav-plat kubernetes-secret-generator-599bf5594b-kpsmq -p
{"level":"info","ts":1609194615.0869522,"logger":"cmd","msg":"Operator Version: 0.0.1"}
{"level":"info","ts":1609194615.0871677,"logger":"cmd","msg":"Go Version: go1.15"}
{"level":"info","ts":1609194615.0871954,"logger":"cmd","msg":"Go OS/Arch: linux/amd64"}
{"level":"info","ts":1609194615.0872138,"logger":"cmd","msg":"Version of operator-sdk: v0.16.0"}
{"level":"info","ts":1609194615.087869,"logger":"leader","msg":"Trying to become the leader."}
{"level":"info","ts":1609194619.8139384,"logger":"leader","msg":"Found existing lock with my name. I was likely restarted."}
{"level":"info","ts":1609194619.8140037,"logger":"leader","msg":"Continuing as the leader."}
{"level":"info","ts":1609194624.5210364,"logger":"controller-runtime.metrics","msg":"metrics server is starting to listen","addr":"0.0.0.0:8383"}
{"level":"info","ts":1609194624.5222325,"logger":"cmd","msg":"Registering Components."}

To Reproduce
The issue seems intermittent. Not sure what is triggering this. Recreating the pod fixes the issue.

Environment:

  • Kubernetes version: [e.g. 1.18]
kubectl version
Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.9", GitCommit:"4fb7ed12476d57b8437ada90b4f93b17ffaeed99", GitTreeState:"clean", BuildDate:"2020-07-15T16:18:16Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.9", GitCommit:"4fb7ed12476d57b8437ada90b4f93b17ffaeed99", GitTreeState:"clean", BuildDate:"2020-07-15T16:10:45Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
  • kubernetes-secret-generator version: [e.g. v0.2.2]
kubernetes-secret-generator:v3.1.0

Additional context
As per my analysis, It seems like operator-sdk should be upgraded to v.0.18.0

Configurable encoding / byte-oriented units for length of encoded data

Is your feature request related to a problem? Please describe.

I have an application I want to generate a SHARED_SECRET for (Pomerium). Pomerium specifically needs a 256-bit key for this, and it expects that the value of the secret it reads will be a Base64-encoded string representing 32 bytes.

With secret-generator as it is currently constituted, I can't generate this key: either I set a length of "40" and Pomerium fails to start while complaining that 30 bytes is too short, I set a length of "44" and Pomerium fails to start while complaining that 33 bytes is too long, or I set a length between the two and Pomerium fails to start while complaining that Base64 is malformed.

Describe the solution you'd like

The main shortcoming of the current system underlying this problem is that the length always refers to the length of the generated string, not the length of the byte sequence encoded by that string. Even in situations where the underlying binary data of the secret doesn't matter, it can helpful to calculate strength in terms of bits of randomness.

To meet these needs, I propose recognizing a B suffix for the (yet-to-be-documented) secret-generator.v1.mittwald.de/length annotation to specify the length of the random secret in bytes, similar to how other resources can be specified in Kubernetes with a distinguishing suffix to change their meaning (such as the m suffix on CPU requests/limits, which specifies the CPU quota in terms of millicores).

That resolves my current use case: however, there are many other applications for Secrets, and many of them expect their random secret data to be encoded in another form than a Base64 string (which is, itself, encoded into Base64 again in the data field of the Secret). As such, I also propose a secret-generator.v1.mittwald.de/encoding annotation, which can generate secrets for all of these applications:

  • Systems that take key material directly from a file could use an encoding type of raw (as they are still encoded as Base64 internally by Kubernetes).
  • Other encodings, many of which are already included in Go's core encoding routines, could be specified to use different representations for the underlying random bits, while also serving as a shorthand for the character set, if looking to just generate a random string (by specifying a non-B-suffixed length):
    • base10 (digits)
    • hex / base16 (hexadecimal)
    • base32 (homograph-avoidant lowercase alphanumeric set)
    • base36 (full lower-case alphanumeric set)
    • base62 (full alphanumeric set, a la Sprig's randAlphaNum)
    • base64url (URL-safe characters)
    • ascii85 (full ASCII, a la Sprig's randAscii)

Describe alternatives you've considered

The most flexible form of encoding would be to let the user specify their own "alphabet" for converting binary values to arbitrary digit systems. However, this much fine-tuned control over a random secret, at this level of the cluster, would most likely be the wrong solution to the wrong problem: even the most sensitive of differences can generally be solved with one of the encodings, or a common variation thereof (ie. Douglas Crockford's version of Base32).

For lengths, I originally considered a separate unit annotation that could be either bytes or digits. However, not only would the former be a lot of annotation bloat for a pretty trivial change, it would also result in a false compatibility: if a document needing a 32-byte base64-encoded string were deployed to a cluster where an older version of the secret-generator were deployed, rather than failing to generate the secret (as it wouldn't recognize the length) and potentially leaving that up to a different component of the system (ie. one that tries to unseal secrets that couldn't be randomly generated), it would misinterpret the length value, and generate a secret of the wrong size (which may even result in the secret being unparseable).

I also considered an alternative bytes annotation that would be mutually exclusive to length. However, on top of this also being a certain amount of annotation bloat (with a confusing distinction between the two annotations), this has no clear way to extend the annotation values if the value of autogenerate is a comma-separated list, where each key may have a different encoding or length. With the proposed design, both encoding and length could potentially be extended out to comma-separated lists in the future as well, where the first length or encoding refers to the first key of autogenerate, the second describing the second key, etc. (If this extension were implemented, their behavior when the lists are not the same length would need to be defined: such consideration is out of scope for this proposal.)

Support generating self-signed TLS Secrets

Is your feature request related to a problem? Please describe.
It would be convenient to be able to generate kubernetes.io/tls secrets, for self-signed TLS on ingress controllers.

Describe the solution you'd like
I'd like to be able to specify my TLS secret alike:

apiVersion: v1
kind: Secret
metadata:
  name: tls-cert
  annotations:
    secret-generator.v1.mittwald.de/type: tls
    secret-generator.v1.mittwald.de/duration: 365
    secret-generator.v1.mittwald.de/common_name: example.org
    secret-generator.v1.mittwald.de/organisation: example.org
    ...
data: {}

With the resulting secret being equivalent to running:

$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ${KEY_FILE} -out ${CERT_FILE} -subj "/CN=example.org/O=example.org"
$ kubectl create secret tls tls-cert --key ${KEY_FILE} --cert ${CERT_FILE}

Describe alternatives you've considered
Using Let's Encrypt whenever available, however sometimes the ingress is not internet-facing, or the DNS is local, and thus Let's Encrypt via the Ingress is not an option either.

Running the above two lines to generate secrets by hand.

Password Policy?

Can you add the option to configure the exclusion of custom characters?

Thank you!

ARM64 Image

Currently we run a mixture of AMD64 and ARM64 nodes in our clusters, and are slowly moving more workloads to AWS ARM based Graviton nodes due to to the lower running costs.

The secret generator is incredibly useful to us and we run it in all of our clusters. Please would you consider building a multi-arch image including support for ARM64. This would aid us in our plan to run ARM64 only clusters in future.

The secrets are not generated on Raspberry PI cluster

I followed the usage instructions with a few modifications because my K3S is accessible as root user as installed:

$ sudo helm repo add mittwald https://helm.mittwald.de
"mittwald" already exists with the same configuration, skipping

$  sudo helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "mittwald" chart repository
Update Complete. ⎈Happy Helming!⎈

$ sudo helm upgrade --kubeconfig /etc/rancher/k3s/k3s.yaml --install kubernetes-secret-generator mittwald/kubernetes-secret-generator
Release "kubernetes-secret-generator" does not exist. Installing it now.
NAME: kubernetes-secret-generator
LAST DEPLOYED: Wed Jun  1 07:45:07 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

$ cat mysecret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
  annotations:
    secret-generator.v1.mittwald.de/type: string
    secret-generator.v1.mittwald.de/autogenerate: password
#spec:
#  forceRegenerate: false
data:
  username: UGxlYXNlQWNjZXB0Cg==

$ sudo kubectl apply -f mysecret.yaml
secret/mysecret created

$ sudo kubectl describe secret mysecret
Name:         mysecret
Namespace:    default
Labels:       <none>
Annotations:  secret-generator.v1.mittwald.de/autogenerate: password
              secret-generator.v1.mittwald.de/type: string

Type:  Opaque

Data
====
username:  13 bytes

$ sudo kubectl get secret mysecret -o jsonpath='{.data}'
{"username":"UGxlYXNlQWNjZXB0Cg=="}

From above output, it appears the secret only contains the predefined element "username" and that the password is not generated. Further, if I uncomment a couple of lines from mysecret.yaml, it complains:

$ sudo kubectl apply -f mysecret.yaml
error: error validating "mysecret.yaml": error validating data: ValidationError(Secret): unknown field "spec" in io.k8s.api.core.v1.Secret; if you choose to ignore these errors, turn validation off with --validate=false

Then I noticed the pod failing:

$ sudo kubectl get pods -n default
NAME                                          READY   STATUS             RESTARTS      AGE
kubernetes-secret-generator-9b7946ff5-znxfz   0/1     CrashLoopBackOff   5 (88s ago)   5m15s

$ sudo kubectl logs kubernetes-secret-generator-9b7946ff5-znxfz
standard_init_linux.go:228: exec user process caused: exec format error

From what I can see, the underlying image is for x84_64 architecture. Can we have one for ARM64?

Documentation of fieldName and add encoding to Values.yaml for CRD Secret String instantiation

Is your feature request related to a problem? Please describe.
Using the annotation you only need to provide the user and secret name. However the CR requires 'fields' to be added. one of these fields is 'encoding' However, this does not seem to be a field we can set in the values.yaml. I was also unsure what 'fieldName' was used for looking at the existing documentation.

Describe the solution you'd like
Better documentation for the use of "fieldName", possibly using the 'password' value to match the annotation example in the readme.

Setting the default operator deployment values for encryption, similar to length

Describe alternatives you've considered
Leave it as is and still document 'fieldName'

Missing helm chart version 3.3.3

Describe the bug
Version 3.3.3 has been released but not the corresponding helm chart

To Reproduce

$ helm repo update
...
$ helm search repo mittwald/kubernetes-secret-generator
NAME                                    CHART VERSION   APP VERSION     DESCRIPTION                                       
mittwald/kubernetes-secret-generator    3.3.2           v3.3.2          Controller for automatically creating random se...

Expected behavior
v3.3.3

Additional context
https://github.com/mittwald/kubernetes-secret-generator/runs/3652117205?check_suite_focus=true

Thanks !!

Generator panics when `data` is not set at all

E1206 16:43:02.460508       1 runtime.go:66] Observed a panic: "assignment to entry in nil map" (assignment to entry in nil map)
/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/pkg/util/runtime/runtime.go:72
/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/pkg/util/runtime/runtime.go:65
/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/pkg/util/runtime/runtime.go:51
/usr/local/go/src/runtime/asm_amd64.s:514
/usr/local/go/src/runtime/panic.go:489
/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/pkg/util/runtime/runtime.go:58
/usr/local/go/src/runtime/asm_amd64.s:514
/usr/local/go/src/runtime/panic.go:489
/usr/local/go/src/runtime/hashmap.go:487
/go/src/github.com/mittwald/kubernetes-secret-generator/main.go:157
/go/src/github.com/mittwald/kubernetes-secret-generator/main.go:97
/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache/controller.go:173
<autogenerated>:50
/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache/controller.go:251
/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache/delta_fifo.go:420
/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache/controller.go:131
/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache/controller.go:102
/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/pkg/util/wait/wait.go:96
/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/pkg/util/wait/wait.go:97
/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/pkg/util/wait/wait.go:52
/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache/controller.go:102
/go/src/github.com/mittwald/kubernetes-secret-generator/main.go:105
/usr/local/go/src/runtime/proc.go:185
/usr/local/go/src/runtime/asm_amd64.s:2197
panic: assignment to entry in nil map [recovered]
	panic: assignment to entry in nil map [recovered]
	panic: assignment to entry in nil map

goroutine 1 [running]:
github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/pkg/util/runtime.HandleCrash(0x0, 0x0, 0x0)
	/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/pkg/util/runtime/runtime.go:58 +0x126
panic(0x131bd80, 0xc420482ac0)
	/usr/local/go/src/runtime/panic.go:489 +0x2cf
github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/pkg/util/runtime.HandleCrash(0x0, 0x0, 0x0)
	/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/pkg/util/runtime/runtime.go:58 +0x126
panic(0x131bd80, 0xc420482ac0)
	/usr/local/go/src/runtime/panic.go:489 +0x2cf
main.(*GeneratorController).SecretAdded(0xc4201799a0, 0x145b9c0, 0xc42051a480)
	/go/src/github.com/mittwald/kubernetes-secret-generator/main.go:157 +0x512
main.(*GeneratorController).SecretAdded-fm(0x145b9c0, 0xc42051a480)
	/go/src/github.com/mittwald/kubernetes-secret-generator/main.go:97 +0x3e
github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache.ResourceEventHandlerFuncs.OnAdd(0xc4204829b0, 0xc4204829c0, 0x14e4a08, 0x145b9c0, 0xc42051a480)
	/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache/controller.go:173 +0x49
github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache.(*ResourceEventHandlerFuncs).OnAdd(0xc4201799c0, 0x145b9c0, 0xc42051a480)
	<autogenerated>:50 +0x73
github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache.NewInformer.func1(0x1334a80, 0xc420281260, 0x1334a80, 0xc420281260)
	/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache/controller.go:251 +0x24d
github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache.(*DeltaFIFO).Pop(0xc420084420, 0xc4203824b0, 0x0, 0x0, 0x0, 0x0)
	/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache/delta_fifo.go:420 +0x218
github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache.(*Controller).processLoop(0xc4202e85b0)
	/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache/controller.go:131 +0x3c
github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache.(*Controller).(github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache.processLoop)-fm()
	/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache/controller.go:102 +0x2a
github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/pkg/util/wait.JitterUntil.func1(0xc420571ea0)
	/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/pkg/util/wait/wait.go:96 +0x5e
github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/pkg/util/wait.JitterUntil(0xc42064fea0, 0x3b9aca00, 0x0, 0x129a901, 0xc4200a53e0)
	/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/pkg/util/wait/wait.go:97 +0xad
github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/pkg/util/wait.Until(0xc420571ea0, 0x3b9aca00, 0xc4200a53e0)
	/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/pkg/util/wait/wait.go:52 +0x4d
github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache.(*Controller).Run(0xc4202e85b0, 0xc4200a53e0)
	/go/src/github.com/mittwald/kubernetes-secret-generator/vendor/k8s.io/client-go/tools/cache/controller.go:102 +0x1c7
main.main()
	/go/src/github.com/mittwald/kubernetes-secret-generator/main.go:105 +0x490

Allow arbitrary labels & annotaitons for Secrets generated from custom resources

Is your feature request related to a problem? Please describe.
I want to use kubernetes-replicator with this secret generator but cannot since the StringSecret object does not allow me to set the correct annotations.

Describe the solution you'd like
A new field to the CRD, perhaps called metadata, allowing me to set labels and annotations.

Describe alternatives you've considered
Using annotations on an empty Secret, but Flux will attempt to manage the contents of it, removing the generated values. Using the custom resources allows for a clean GitOps flow.

Additional context
This is similar to #73 but also includes labels in the list.

I saw in the code that labels are inherited but I don't necessarily want to copy every label or annotation onto the generated Secret.

Pod startup failure

Describe the bug
The pod is not able to start up during the initial deployment using the latest v3.4.0 helm chart. Is it possible this is related to the Kubernetes version?

Events:
  Type     Reason     Age                    From               Message
  ----     ------     ----                   ----               -------
.....
  Normal   Created    3m7s (x2 over 3m19s)   kubelet            Created container kubernetes-secret-generator
  Normal   Started    3m7s (x2 over 3m19s)   kubelet            Started container kubernetes-secret-generator
  Normal   Pulled     3m7s                   kubelet            Successfully pulled image "quay.io/mittwald/kubernetes-secret-generator:latest" in 74.165988ms (74.182482ms including waiting)
  Warning  Unhealthy  2m55s (x8 over 3m13s)  kubelet            Readiness probe failed: Get "http://10.8.11.223:8080/readyz": dial tcp 10.8.11.223:8080: connect: connection refused
  Warning  Unhealthy  2m55s (x6 over 3m13s)  kubelet            Liveness probe failed: Get "http://10.8.11.223:8080/healthz": dial tcp 10.8.11.223:8080: connect: connection refused
  Normal   Killing    2m55s (x2 over 3m7s)   kubelet            Container kubernetes-secret-generator failed liveness probe, will be restarted
  Normal   Pulling    2m54s (x3 over 3m19s)  kubelet            Pulling image "quay.io/mittwald/kubernetes-secret-generator:latest"

Those are the only logs available in pods:

{"level":"info","ts":1681322039.958661,"logger":"cmd","msg":"Operator Version: 0.0.1"}
{"level":"info","ts":1681322039.9587452,"logger":"cmd","msg":"Go Version: go1.15.15"}
{"level":"info","ts":1681322039.9587672,"logger":"cmd","msg":"Go OS/Arch: linux/amd64"}
{"level":"info","ts":1681322039.9587784,"logger":"cmd","msg":"Version of operator-sdk: v0.16.0"}
{"level":"info","ts":1681322039.9592156,"logger":"leader","msg":"Trying to become the leader."}
{"level":"info","ts":1681322049.27793,"logger":"leader","msg":"Found existing lock with my name. I was likely restarted."}
{"level":"info","ts":1681322049.2779632,"logger":"leader","msg":"Continuing as the leader."}

To Reproduce
Just a basic installation using helm.

values.yaml:

installCRDs: true
useMetricsService: true

Environment:

  • Kubernetes version: EKS 1.25
  • kubernetes-secret-generator version: v3.1.0, v.3.4.0, latest.
kubectl version
Client Version: version.Info{Major:"1", Minor:"25", GitVersion:"v1.25.0", GitCommit:"a866cbe2e5bbaa01cfd5e969aa3e033f3282a8a2", GitTreeState:"clean", BuildDate:"2022-08-23T17:36:43Z", GoVersion:"go1.19", Compiler:"gc", Platform:"darwin/amd64"}
Kustomize Version: v4.5.7
Server Version: version.Info{Major:"1", Minor:"25+", GitVersion:"v1.25.6-eks-48e63af", GitCommit:"9f22d4ae876173884749c0701f01340879ab3f95", GitTreeState:"clean", BuildDate:"2023-01-24T19:19:02Z", GoVersion:"go1.19.5", Compiler:"gc", Platform:"linux/amd64"}

Permissions for OwnerReferencesPermissionEnforcement plugin

Describe the bug
In OKD OwnerReferencesPermissionEnforcement plugin enabled by default.
I got follow error after attempt to create Secret by StringSecret CRD:

{"level":"info","ts":1685956649.2009747,"logger":"controller_string_secret","msg":"Reconciling StringSecret","Request.Namespace":"test","Request.Name":"test"}
{"level":"error","ts":1685956649.2061837,"logger":"controller-runtime.controller","msg":"Reconciler error","controller":"stringsecret-controller","request":"test/test","error":"secrets \"test\" is forbidden: cannot set blockOwnerDeletion if an ownerReference refers to a resource you can't set finalizers on: , <nil>","stacktrace":"github.com/go-logr/zapr.(*zapLogger).Error\n\t/home/runner/go/pkg/mod/github.com/go-logr/[email protected]/zapr.go:128\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler\n\t/home/runner/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:258\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\t/home/runner/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:232\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).worker\n\t/home/runner/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:211\nk8s.io/apimachinery/pkg/util/wait.JitterUntil.func1\n\t/home/runner/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:152\nk8s.io/apimachinery/pkg/util/wait.JitterUntil\n\t/home/runner/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:153\nk8s.io/apimachinery/pkg/util/wait.Until\n\t/home/runner/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:88"}

This is error like this in Operator SDK

Environment:

  • Kubernetes version: v1.24.0-2568+56584349e9412b-dirty
  • OKD: 4.11.0
  • kubernetes-secret-generator version: 3.4.0

Additional context
I have fixed this error for me by patch:

+   - apiGroups:
+         - secretgenerator.mittwald.de
+     resources:
+       - basicauths/finalizers
+       - sshkeypairs/finalizers
+       - stringsecrets/finalizers
+     verbs:
+       - update

Periodic secret regeneration

Is your feature request related to a problem? Please describe.

In certain conditions secret values must be periodically updated.

Describe the solution you'd like

Annotation+CRD field to specify cronjob-like pattern for regeneration schedule.

Describe alternatives you've considered

Currently (if I understand it correctly) cluster operator would need to create a controller/cronjob to annotate generated secrets to trigger a regeneration.

Additional context

None.

Invalid characters when using base64url

I was under the impression that base64url shouldn't include URL-specific characters like + and /. However, sometimes I still get those characters. Not sure if I am using it the wrong way?

I use this file:
root@ip-10-202-13-165:~$ cat test.yaml
apiVersion: v1
kind: Secret
metadata:
name: celery-rabbitmq8
annotations:
secret-generator.v1.mittwald.de/autogenerate: rabbitmq-password
secret-generator.v1.mittwald.de/encoding: base64url

I wrote a script that every second recreates the secrete and checks the value:
splunker@ip-10-202-13-165:~$ while true ; do sudo microk8s kubectl delete -f test.yaml ; sudo microk8s kubectl apply -f test.yaml ; sudo microk8s kubectl get secret celery-rabbitmq8 -o yaml | sed -e 's/[ ]+//g' | grep "^rabbitmq-password" | cut -d: -f2 | base64 -d | cut -d: -f2 ; sleep 1; done
secret "celery-rabbitmq8" deleted
secret/celery-rabbitmq8 created
KX5uhl/J1ItmsKPvTQ08a6TBkA3D6eCLSqI1UgO6
secret "celery-rabbitmq8" deleted
secret/celery-rabbitmq8 created
iLUvzFWSQhDW4MfDv2WD3bnsiPX0sRN7ZvJ7N07e
secret "celery-rabbitmq8" deleted
secret/celery-rabbitmq8 created
JK+kDWEW6MO8eo3/VugU2zX++k3jG1YW1V9zYjfE
secret "celery-rabbitmq8" deleted
secret/celery-rabbitmq8 created
fMVnFYj5BQtbnbfGTYo6500ecxiLHgL5kMgI2Bm2
secret "celery-rabbitmq8" deleted
secret/celery-rabbitmq8 created
tDxKy2Vkd3iC5w8lDJOWSFSKzJNp3qDfYLs2mTBm
secret "celery-rabbitmq8" deleted
secret/celery-rabbitmq8 created
1LkQBFUz74IR5UqxDbQ/nrvumnYumnHpNpR+xVV8
secret "celery-rabbitmq8" deleted
secret/celery-rabbitmq8 created
0apehqCOxmJx2IS6I5oHjG0f+PdAA1xG6PdK+fhr
secret "celery-rabbitmq8" deleted
secret/celery-rabbitmq8 created
puDlNmtK5t2/j8A/sMOOV9qJTVS9y7rB5pb38qZu
secret "celery-rabbitmq8" deleted
secret/celery-rabbitmq8 created
UrwYUWDOpvv6P8xKZyQUm/feDUnb1U/AoiBrAlWK

As you can see, sometimes "/" and "+" are still used. Am I doing something wrong?

Allow annotations to be added per generated value

Is your feature request related to a problem? Please describe.
I would like to generate a single secret with two generated values (which is supported), but I would like them to have different lengths. Specifically, I also need to use the hex encoding also. The values are intrinsically related, so I would like them to share a single secret.

Describe the solution you'd like
Allow the annotations to include the generated field name:

apiVersion: v1
kind: Secret
metadata:
  name: credentials
  annotations:
    secret-generator.v1.mittwald.de/autogenerate: id,password
    secret-generator.v1.mittwald.de/length/id: '8b'
    secret-generator.v1.mittwald.de/encoding/id: 'hex'
    secret-generator.v1.mittwald.de/length/password: '16b'
    secret-generator.v1.mittwald.de/encoding/password: 'hex'

For backwards compatibility, secret-generator.v1.mittwald.de/encoding and secret-generator.v1.mittwald.de/length would be maintained as the default, and providing an annotation with the key in the path would override for only that key.

Describe alternatives you've considered
Using two secrets, one for each value does work, but results in more secrets and does not make it as clear the values are related.

Additional context
This could potentially be handled as part of #34

Ability to specify the kubernetes secret type

The generated secrets are always of type: Opaque.

It would be nice if the generated secret is of appropriate type, especially for BasicAuth (type: kubernetes.io/basic-auth) and SSHKeyPair (type: kubernetes.io/ssh-auth). See https://kubernetes.io/docs/concepts/configuration/secret/#secret-types for the list of built-in types.

Ideally, the secret type should be fully configurable through annotation/CR spec.

Some third party tools require the Kubernetes secrets to be of a specific type, preventing the use of this generator in that case.

Secrets out of sync

Describe the bug
As you can see in the screenshot, I modified a StringSecret a while back to include an extra field, and the change is present on the cluster. Nonetheless, the generated secret is still missing that field. I am baffled as to what is going on here.
image

To Reproduce
The secret is defined here: https://open.greenhost.net/xeruf/stackspout/-/blob/main/apps/do/vikunja-secrets/vikunja-variables.yaml?ref_type=heads

Expected behavior
The secret is updated.

Environment:

  • Kubernetes version: v1.28.2+k3s1
  • kubernetes-secret-generator version: 3.4.0

Support for other password hashes than bcrypt

Is your feature request related to a problem? Please describe.
Sometimes bcrypt is not supported and you cannot use directly auth part with bcrypt password hash from basicauth secret.

Describe the solution you'd like
As bcrypt is the defult now (and only option), it would be nice to steer the choice of hashing by annotation for example? with a choice like SHA-512 and MD5 ?

Describe alternatives you've considered
As alternative I need to generate basic auth secret in other way to be able to use it and mount directly.

Support global custom image registries for private clusters on the helm chart

Is your feature request related to a problem? Please describe.
The chart does note support using a global override for image registries

Describe the solution you'd like
Add conditions on the template for global custom image registries and image pull secrets matching other charts.

Describe alternatives you've considered

Additional context

The secret-generator pod occasionally fails to start after the pod is being deleted

Describe the bug
The secret-generator container sometime restarts after the pod is being replaced.

To Reproduce

  1. Deploy the secret-generator with the manifests supplied in this repo.
  2. After the pod is up, delete it.
  3. The new single container in the new pod will sometime restart due to the wait period when it tries to be the leader.

Expected behavior
A new pod will start and be ready immediately.

Environment:

  • Kubernetes version: 1.18.16
  • kubernetes-secret-generator version: 3.2.0

Additional context
The generator logs:

kubernetes-secret-generator-68d6f67df7-dghwg kubernetes-secret-generator {"level":"info","ts":1617644831.4539402,"logger":"cmd","msg":"Operator Version: 0.0.1"}
kubernetes-secret-generator-68d6f67df7-dghwg kubernetes-secret-generator {"level":"info","ts":1617644831.4539738,"logger":"cmd","msg":"Go Version: go1.15.5"}
kubernetes-secret-generator-68d6f67df7-dghwg kubernetes-secret-generator {"level":"info","ts":1617644831.4539793,"logger":"cmd","msg":"Go OS/Arch: linux/amd64"}
kubernetes-secret-generator-68d6f67df7-dghwg kubernetes-secret-generator {"level":"info","ts":1617644831.453984,"logger":"cmd","msg":"Version of operator-sdk: v0.16.0"}
kubernetes-secret-generator-68d6f67df7-dghwg kubernetes-secret-generator {"level":"info","ts":1617644831.4541202,"logger":"leader","msg":"Trying to become the leader."}
kubernetes-secret-generator-68d6f67df7-dghwg kubernetes-secret-generator {"level":"info","ts":1617644832.172396,"logger":"leader","msg":"Found existing lock","LockOwner":"kubernetes-secret-generator-68d6f67df7-bs2lj"}
kubernetes-secret-generator-68d6f67df7-dghwg kubernetes-secret-generator {"level":"info","ts":1617644832.1823065,"logger":"leader","msg":"Not the leader. Waiting."}
kubernetes-secret-generator-68d6f67df7-dghwg kubernetes-secret-generator {"level":"info","ts":1617644833.3122263,"logger":"leader","msg":"Not the leader. Waiting."}
kubernetes-secret-generator-68d6f67df7-dghwg kubernetes-secret-generator {"level":"info","ts":1617644835.699852,"logger":"leader","msg":"Not the leader. Waiting."}
kubernetes-secret-generator-68d6f67df7-dghwg kubernetes-secret-generator {"level":"info","ts":1617644840.244563,"logger":"leader","msg":"Not the leader. Waiting."}
- kubernetes-secret-generator-68d6f67df7-dghwg › kubernetes-secret-generator
+ kubernetes-secret-generator-68d6f67df7-dghwg › kubernetes-secret-generator
kubernetes-secret-generator-68d6f67df7-dghwg kubernetes-secret-generator {"level":"info","ts":1617644841.9950554,"logger":"cmd","msg":"Operator Version: 0.0.1"}
kubernetes-secret-generator-68d6f67df7-dghwg kubernetes-secret-generator {"level":"info","ts":1617644841.9950805,"logger":"cmd","msg":"Go Version: go1.15.5"}
kubernetes-secret-generator-68d6f67df7-dghwg kubernetes-secret-generator {"level":"info","ts":1617644841.9950848,"logger":"cmd","msg":"Go OS/Arch: linux/amd64"}
kubernetes-secret-generator-68d6f67df7-dghwg kubernetes-secret-generator {"level":"info","ts":1617644841.9950886,"logger":"cmd","msg":"Version of operator-sdk: v0.16.0"}
kubernetes-secret-generator-68d6f67df7-dghwg kubernetes-secret-generator {"level":"info","ts":1617644841.9952486,"logger":"leader","msg":"Trying to become the leader."}
kubernetes-secret-generator-68d6f67df7-dghwg kubernetes-secret-generator {"level":"info","ts":1617644842.7113423,"logger":"leader","msg":"Found existing lock","LockOwner":"kubernetes-secret-generator-68d6f67df7-bs2lj"}
kubernetes-secret-generator-68d6f67df7-dghwg kubernetes-secret-generator {"level":"info","ts":1617644842.723332,"logger":"leader","msg":"Not the leader. Waiting."}
kubernetes-secret-generator-68d6f67df7-dghwg kubernetes-secret-generator {"level":"info","ts":1617644843.855035,"logger":"leader","msg":"Leader pod has been deleted, waiting for garbage collection do remove the lock."}
kubernetes-secret-generator-68d6f67df7-dghwg kubernetes-secret-generator {"level":"info","ts":1617644846.2358556,"logger":"leader","msg":"Became the leader."}

Make cluster role creation optional

Is your feature request related to a problem? Please describe.
I want to limit the scope of secrets-generator to a single namespace & remove the need to create a cluster role

Describe the solution you'd like
Add a variable such as rbac.create & rbac.clusterRole which disable the role and clusterRole respectively. Both would default to true for backwards compatibility.

If rbac.clusterRole is false, then watchNamespace should default to {{ .Release.Namespace }} as the generator will not have permissions to access other namespaces.

Describe alternatives you've considered
WATCH_NAMESPACE could be updated to include the tpl function so that it can be set to {{ .Release.Namespace }} via the values file, but this doesn't remove the clusterRole

env:
  - name: WATCH_NAMESPACE
    value: {{ tpl .Values.watchNamespace . }}

Additional context
I can raise a PR for these changes if you are happy with the variable names.
Concept modelled from bitnami/external-dns

modify liveness probes from values.yaml

hello,
we have openshift and its api is very slow (its a known issue for long..)
the pod enters crashloops because of the slow startup.

could you please add feature to the helm chart so we could increase the readiness and liveness probes timeouts from values.yaml?

Backwards compatibility broken because of CRDs

Describe the bug
Previously, the deployment would work with just tag based secret injection, but after the CRDs were introduced, it's impossible to use it without CRDs installed.

To Reproduce
Deploy the helm-chart with the flag skip-crds and try to inject a secret.
Expected behavior
The pod would detect or at least there would be a configuration which would make the deployment work.

Environment:

  • Kubernetes version: v1.21.5
  • kubernetes-secret-generator version: >=v3.3.3

The role is missing permissions to access the CRD

Describe the bug
While the ClusterRole is set up properly, the standard Role doesn't have permissions to access the CRD. Thus setting rbac.clusterRole: "false" results in permission errors:

E0313 00:46:07.142403       1 reflector.go:123] pkg/mod/k8s.io/[email protected]/tools/cache/reflector.go:96: Failed to list *v1alpha1.BasicAuth: basicauths.secretgenerator.mittwald.de is forbidden: User "system:serviceaccount:defaultkubernetes-secret-generator" cannot list resource "basicauths" in API group "secretgenerator.mittwald.de" in the namespace "default"

To Reproduce

helm install kubernetes-secret-generator mittwald/kubernetes-secret-generator --set rbac.clusterRole='"false"'

Expected behavior
I expect it to work when clusterRole is not enabled.

Environment:

  • Kubernetes version: 1.22.6
  • kubernetes-secret-generator version: 3.3.4

Additional context
Awesome chart 🥂

Label selector for metrics service does not match pod labels

Describe the bug
Metrics service selects by following label:
name=kubernetes-secret-generator
But pod labels selectors are:
app.kubernetes.io/name=kubernetes-secret-generator

To Reproduce
Deploy secret generator with metrics enabled

Expected behavior
Service selector labels match pod labels

Environment:

  • Kubernetes version:
Client Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.2", GitCommit:"092fbfbf53427de67cac1e9fa54aaa09a28371d7", GitTreeState:"clean", BuildDate:"2021-06-16T12:59:11Z", GoVersion:"go1.16.5", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.1", GitCommit:"b14bb200ea732d6667462a29d296d3daa511c911", GitTreeState:"clean", BuildDate:"2021-07-13T17:19:09Z", GoVersion:"go1.16.4", Compiler:"gc", Platform:"linux/amd64"}
  • kubernetes-secret-generator version: 3.3.2

Option to exclude characters from generated secrets

Is your feature request related to a problem? Please describe.
AWS RDS passwords don't allow some special characters. The secrets generator often creates a slash in the secret of type string, and this is not being taken for RDS. As the documentation states:
Constraints: At least 8 printable ASCII characters. Can't contain any of the following: / (slash), '(single quote), "(double quote) and @ (at sign).

Describe the solution you'd like
Option to create just alphanumeric secrets where you can define which characters you want to omit

Thank you in advance!

missing permissions for creating services

Describe the bug
I've deployed the secret-generator according to the example manifests given in the deploy dir in this repo, and its complaining about missing rbac permissions for creating services.
This raises 2 questions:

  1. If this permission is really needed, why is it not mentioned in the example?
  2. Why is it needed? Why does a secret-generator needs to create service object(s) in the cluster?

To Reproduce
Deploy the secret manager according to the example given in deploy dir.

Expected behavior
The container should start without any errors

Environment:

  • Kubernetes version: 1.18.16
  • kubernetes-secret-generator version: 3.2.0

Additional context

kubernetes-secret-generator {"level":"info","ts":1617775252.2373734,"logger":"cmd","msg":"Could not create metrics Service","error":"failed to create or get service for metrics: services is forbidden: User \"system:serviceaccount:kube-system:kubernetes-secret-generator\" cannot create resource \"services\" in API group \"\" in the namespace \"kube-system\""}

Option to configure the default encoding for secrets

Is your feature request related to a problem? Please describe.
I am systematically using base64url encoding to avoid any potential issues with passwords sued in connexion URIs.

Describe the solution you'd like
It would be nice to be able to configure the default encoding, in the same way we can configure the default secret length

Describe alternatives you've considered
Currently, I must add the encoding annotation on each secret.

Use MutatingWebHook for generating secrets

Is your feature request related to a problem? Please describe.

It's a feature request, to prevent potential race condition problems.
The current implementation seems to be watching secrets in certain or all namespaces.

The problem is that a secret that is created might be attached to pods using environment variables (valueFrom: ...). But, at the time of being attached, the generator might not yet generate the required secret keys.

So there is a situation where a pod could be attached to a secret before the values are actually generated.

Describe the solution you'd like

By using a MutatingWebHook, the secret keys would be generated before the secret is available to pods.

The MutatingWebHook lifecycle will be triggered before the secret could be admitted, and it would prevent this race condition altogether.

Describe alternatives you've considered

Restart the pod if the key is not present on the secret

`math/rand` is not a secure random number generator

The code uses math/rand to generate secrets:

func generateSecret(length int) (string, error) {
b := make([]rune, length)
for i := range b {
b[i] = runes[rand.Intn(len(runes))]
}
return string(b), nil
}

math/rand is a deterministic pseudo-random-number generator, suitable for monte-carlo simulations or other such applications, but not a source of secure random numbers. For that purpose you need crypto/rand.

Any secrets already generated using math/rand should be presumed compromised and should be regenerated.

(Note, in particular, that math/rand uses a fixed seed across runs, and so such secrets may contain no entropy whatsoever. Note that repeated runs of https://play.golang.org/p/MRGyYO_XC6 produced identical secrets)

Feature request: Secret length configurable via annotation

Thanks for this operator - it's very useful. What would make it even more useful, IMO, would be the opinion to specify the length of a secret via annotations.

I appreciate that this could be considered insecure as it leaks some property about the secret (ie, it's length) so there are a couple of ways one could handle this:

  1. Name the annotation something like potentiallyUnsafeLength to make it clear to users that this isn't always the best way to go about things.

  2. Allow support for a complementary maxLength annotation, so at least an observer doesn't know the exact length of the generated secret.

Thanks for your time!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.