Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ability to template arbitrary data keys within resulting secrets #445

Closed
evq opened this issue Aug 16, 2020 · 6 comments
Closed

add ability to template arbitrary data keys within resulting secrets #445

evq opened this issue Aug 16, 2020 · 6 comments
Milestone

Comments

@evq
Copy link
Contributor

evq commented Aug 16, 2020

sometimes when deploying services on k8s you end up needing to create a secret which contains a entire config file. in such cases you often only have a small amount of data that is actually secret, the rest of the config file could be safely kept in plaintext. in such cases sealed-secrets could offer a large usability win by allowing arbitrary keys within the resulting secrets to be created from a plaintext template which uses the decrypted data keys as inputs.

while there is a docs example showing how this can be achieved with an init container, having this capability within sealed-secrets is more flexible and reduces integration complexity in certain situations

sealed-secrets already has the concept of secret "templating", perhaps a Data field could be added to the SecretTemplateSpec to enable this.


Example (extended from the README):

--- 
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata: 
  annotation: 
    kubectl.kubernetes.io/last-applied-configuration: "...."
  name: mysecret
  namespace: mynamespace
spec: 
  encryptedData: 
    dockerAuth: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq.....
  template: 
    metadata: 
      annotations: 
        jenkins.io/credentials-description: "credentials from Kubernetes"
      labels: 
        jenkins.io/credentials-type: usernamePassword
    data: 
      .dockercfg: |-
          {
            "auths": {
              "https://index.docker.io/v1/": {
                "auth": "{{index .Data "dockerAuth"}}"
              }
            },
            "HttpHeaders": {
              "User-Agent": "Docker-Client/19.03.9-ce (linux)"
            }
          }

would result in a secret like:

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
  namespace: mynamespace
  labels:
    "jenkins.io/credentials-type": usernamePassword
  annotations:
    "jenkins.io/credentials-description": credentials from Kubernetes
  ownerReferences:
  - apiVersion: bitnami.com/v1alpha1
    controller: true
    kind: SealedSecret
    name: mysecret
    uid: 5caff6a0-c9ac-11e9-881e-42010aac003e
type: kubernetes.io/dockercfg
data:
  dockerAuth: ewogICJjcmVk...
  .dockercfg: ewoJImF1dGh...

where the decoded .dockercfg looks like:

{
	"auths": {
		"https://index.docker.io/v1/": {
			"auth": "hello world..."
		}
	},
	"HttpHeaders": {
		"User-Agent": "Docker-Client/19.03.9-ce (linux)"
	}
}
@musabmasood
Copy link

+1

We have a similar usecase with ArgoCD, the cluster secret should look like this:

apiVersion: v1
kind: Secret
metadata:
  name: mycluster-secret
  labels:
    argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
  name: mycluster.com
  server: https://mycluster.com
  config: |
    {
      "bearerToken": "<authentication token>",
      "tlsClientConfig": {
        "insecure": false,
        "caData": "<base64 encoded certificate>"
      }
    }

In the secret above, name and server are not really secrets and I don't want the devs to encrypt them uselessly. So there is no way for me to create a SealedSecret from it with just the bearerToken and caData that should be encrypted.

A simple solution that SS could be implement is to support data key, which can take the usual b64 values:

apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  creationTimestamp: null
  name: mysecret
  namespace: myns
spec:
  encryptedData:
    foo: <ss-encoded-value>
  data:
    bar: <regular-b64-encoded-value>

@evq
Copy link
Contributor Author

evq commented Aug 18, 2020

@musabmasood I think the templating support I implemented would meet your use case, can you help confirm?

I updated the config file templating example as part of my PR: https://github.com/bitnami-labs/sealed-secrets/pull/446/files#diff-a311653b9191ca8296fee028d97e41feR16

I think you could just add additional "template" data keys that didn't have any variable substitution. e.g. alongside myconfig.json in the example you could add name: mycluster.com and server: https://mycluster.com. They wouldn't be base64 encoded - but if you're planning to check these files into git it might be more obvious to have them in a non encoded string form. Curious what you think!

@mkmik
Copy link
Collaborator

mkmik commented Aug 18, 2020

Yeah. It seems a very practical thing to have. I'll take a look soon

@mkmik
Copy link
Collaborator

mkmik commented Aug 19, 2020

For I long time I wanted to convince myself that k8s Secrets are meant to store actual secrets and as soon as you stuff complex "configs" in them you're "doing something wrong".

One key rationale for that point of view, is that the more developers need to look at secrets (inspect, dump, log, ...) the higher the chances are that secrets will be leaked. The "bigger" a secret is the more likely it is you eventually need to take a peek, or treat it as a "pet". The "correct" approach was to force people to design apps where config are loaded as config maps and secrets get injected as env variables or files and have the application know how to read secrets separately from the config.

However, turns out that in practice you cannot force everybody to write applications in that way.

A templating approach like the one you propose is a pragmatic middle ground. Since you can look at the template in clear, you don't often need to see the template being expanded. It's not perfect, because when things don't work, you may be tempted to look at the expanded template just to be sure the template output is not borked. That said, this can be mitigated, perhaps by rendering the template with some dummy secret values and put it in the .status field of the SealedSecret object.

@lapwingcloud
Copy link

This is a nice thing to have, as the jenkins secret example showing in the readme, the username field is definitely not secret.

@mkmik
Copy link
Collaborator

mkmik commented May 10, 2021

Merged in #580!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants