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

Feat: Allow simple Vault integration #392

Open
AndresPineros opened this issue Nov 2, 2018 · 18 comments
Open

Feat: Allow simple Vault integration #392

AndresPineros opened this issue Nov 2, 2018 · 18 comments

Comments

@AndresPineros
Copy link

AndresPineros commented Nov 2, 2018

Currently there are many users that want to integrate Vault with Kubernetes, but there are no high level tools for this. The current Kubernetes AuthMethod for Vault is too complex and coupled to the definition of the charts. This proposal could allow for a Vault integration with Kubernetes that is simple and decoupled.

This could be the structure of a helmfile integrated with Vault:

releases:
  - chart: .
    name: release-test
    version: 0.1.0
    values:
      - application:
           mysql_url: jdbc.....
           mysql_user: localtest
           mysql_password: localtest
    vault:
      active: true
      secrets:
        - vaultPath: secret-engine/my-application
          key: mysql.username
          targetVar: application.mysql_user
        - vaultPath: secret-engine/my-application
          key: mysql.password
          targetVar: application.mysql_password

Basically the project could use the VAULT_ADDR and VAULT_TOKEN environment variables to query all the secrets from Vault using the vaultPath and the key to inject them to the helm release using --set.

So, for that example the --set flags of the helm upgrade -i ... command would look like:

--set application.mysql_user=<queried-secret> --set application.mysql_password=<queried-secret>

If the vault.active field is set to false, or the vault field is not used, the release will just use the "localtest" values.

The main advantage I see for this proposal is that it allows centralization of secrets. Usually storing encrypted secrets in repositories result in secret-management-madness as there is no unique source of truth in case multiple repositories require the same secret. Vault solves this. Of course, this approach only addresses static Vault secrets (secrets in git repos are static too). For dynamic Vault secrets, I think there's no other alternative than the Kubernetes Auth Method.

There is one security issue with this proposal: Tiller has to use the --storage (Secret) backend instead of the ConfigMap backend to avoid fetching injected secrets with helm get values <release-name>. Although, I think this is also a problem for the helm-secrets pluign.

@AndresPineros
Copy link
Author

I would really like to PR this, but I don't know Golang. I just started learning it to be able to contribute, but I don't know how long it can take for me to learn and do a decent PR.

@AndresPineros AndresPineros changed the title Allow simple Vault integration Feat: Allow simple Vault integration Nov 4, 2018
@mumoshu
Copy link
Collaborator

mumoshu commented Nov 9, 2018

@AndresPineros Hey!

there is no unique source of truth in case multiple repositories require the same secret

Yeah, I believe this is definitely the thing we should consider.

A possible work-around as of today would be to use templating. That is, include something like {{ exec "./your/cmd/to/fetch/vault/secret/to/dump/yaml/or/json" (list "path.to.key") }} within a values.yaml.gotmpl under secrets: field of your helmfile.yaml.

Would it work?

@sstarcher
Copy link
Contributor

I think this would be a great feature to directly support and essentially change the secrets handling into a plug-able system.

@mumoshu
Copy link
Collaborator

mumoshu commented Jan 17, 2019

And please let me plug-in that my own use-case requires an integration with AWS Secrets Manager :)

@mumoshu
Copy link
Collaborator

mumoshu commented Jan 17, 2019

So I was wondering if it is possible to integrate a tool like gomplate to helmfile.

Relying on gomplate datasources, we can reliably add support for many backends including vault.

An example helmfile.yaml featuring the feature would look like:

releases:
  - chart: .
    name: release-test
    version: 0.1.0
    datasources:
      myvault: vault://vault.example.com:8200///secret-engine/my-application
    values:
      - application:
           mysql_url: jdbc.....
           # Note that {{` and `}} must be required to defer template execution. Otherwise it is executed on loading helmfile.yaml, which doesnt work due to that no datasources are loaded yet
           mysql_url: {{` {{ datasource "myvault" "mysql.username" }} `}}
           mysql_password: {{` {{ datasource "myvault" "mysql.password" }} `}}

@mumoshu mumoshu pinned this issue Jan 17, 2019
@osterman
Copy link
Contributor

Data sources like gomplate would be great. Before I saw this issue, today I was thinking how it would be nice to access SSM Parameter store directly.

@mumoshu
Copy link
Collaborator

mumoshu commented Jan 24, 2019

An alternative idea would be to focus on making secrets consumption from any backend declarative, while making the changes required to helmfile minimum.

That is, allow defining any secrets backend within a helmfile.yaml:

secretsProvider:
- name: vault
  command: "bin/helmfile-secrets-provider-vault"
  protocols:
  - "vault"

releases:
-  chart: .
    name: release-test
    version: 0.1.0
    secrets:
      - vault://vault.example.com:8200////secret-engine/my-application/?application.mysql_user=mysql.user,application.mysql_password=mysql.password

In the above example, bin/helmfile-vault-provider is executed like bin/helmfile-vault-provider 'vault://vault.example.com:8200////secret-engine/my-application/?...' > $temp_file_created_by_helmfile to produce a values.yaml-like file containing the secret .

The produced secrets file should be subject to caching proposed in #444

@sstarcher
Copy link
Contributor

I would think you would want to move more of the configuration for the backend out of the secrets block so you don't have to repeat it.

@mumoshu
Copy link
Collaborator

mumoshu commented Jan 25, 2019

Thanks!

That sounds good. Then my best idea would be #392 (comment).

Reimplementing gomplate datasources or integrating gomplate, along with my proposed extension to helmfile's template engine and helmfile.yaml would make the repetition minimum, while allowing flexibility to either source a single secret value or the whole YAML data.

For my point of writing any secrets provider within a helmfile.yaml, adding new gomteplate datasource(or its reimplementation)s like exec would work.

@mumoshu
Copy link
Collaborator

mumoshu commented Apr 13, 2019

I now think we can start with something simple like the below:

templates:
  vault: &vault
    exec: "vault read secrets/foo/bar/{{.key}}"
  vault: &awssecret
    exec: "aws secretmanager get ...."

releases:
- name: myapp
  chart: ./mychart
  secrets:
  - secrets.yaml #helm-secrets
  - <<: *vault
     key: myvaultsecret
  - <<: *awssecret
     key: myawssecret.key

@mumoshu
Copy link
Collaborator

mumoshu commented Apr 13, 2019

And the above should work fine with #444

@sstarcher
Copy link
Contributor

That works, but it is going to get very ugly very fast.

@red8888
Copy link

red8888 commented Aug 30, 2019

@mumoshu godaddy has something pretty cool for hydrating k8s secrets from AWS Secrets Manager: https://github.com/godaddy/kubernetes-external-secrets

BUT you gotta get AWS creds to access Secrets Manager in there to begin with somehow. It would be great if helmfile could retrieve those AWS creds from secrets manager and create k8s secrets for the external secrets manager service to use

@mumoshu
Copy link
Collaborator

mumoshu commented Aug 30, 2019

@red8888 Hey! Yeah I've even considered to add integration with my aws-secret-operator but I'm still guesting what the real benefit It provides.

For your case, are you talking about making Helmfile able to import SecretsManager secrets as Helm chart values, or something more advanced?

AWS creds from secrets manager and create k8s secrets for the external secrets manager service to use

This has nothing to do with kubernetes-external-secrets. Probably you meant to reimplement part of kubernetes-external-secrets into Helmfile so that it creates K8s secrets from SecretsManager secrets?

@red8888
Copy link

red8888 commented Sep 4, 2019

@mumoshu yeah thats what i was thinking. I was not aware of https://github.com/mumoshu/aws-secret-operator

kubernetes-external-secrets does mostly the same thing looks like.

I just meant a service used for hydrating k8s secrets from aws secrets manager needs AWS creds to access it. using kubernetes-external-secrets I have been manually scripting that part of the deployment (pulling the AWS creds from Secrets Manger and creating a k8s secret for kubernetes-external-secrets to use). After that point kubernetes-external-secrets dynamically creates k8s secrets for me from secrets manager (through the custom resources like your service does)

its not a big deal to script it myself, but would be neat if I could have helm pull the initial creds. that might be asking to much though

@mumoshu
Copy link
Collaborator

mumoshu commented Sep 6, 2019

@red8888 Thanks for clarifying! I think I understood your problem now.

Your use-case should be addressed with #745 which has AWS Secrets Manager as one of supported backends.

You can combine it with the incubator/raw Helm chart so that you can create whatever K8s resources from helmfile values.

@etiennejournet
Copy link

etiennejournet commented Jan 6, 2020

I now think we can start with something simple like the below:

templates:
  vault: &vault
    exec: "vault read secrets/foo/bar/{{.key}}"
  vault: &awssecret
    exec: "aws secretmanager get ...."

releases:
- name: myapp
  chart: ./mychart
  secrets:
  - secrets.yaml #helm-secrets
  - <<: *vault
     key: myvaultsecret
  - <<: *awssecret
     key: myawssecret.key

I haven't been able to understand or use this example, could you clarify ?
in ./helmfile.yaml: failed to read helmfile.yaml: reading document at index 1: yaml: unmarshal errors: line 12: field exec not found in type state.TemplateSpec line 24: cannot unmarshal !!map into string

EDIT ==> went further but still can't get it to work :

templates:                                                                      
  vault: &vault                                                                 
    exec: "vault kv get -field={{.key}} secrets/test"                       
                                                                                
releases:                                                                       
- name: chart                                              
  chart: chart                             
  namespace: chart                                                                                                     
  secrets:                                                                      
  - <<: *vault                                                                  
    key: root_password

Goes :

executing "stringTemplate" at <.key>: can't evaluate field key in type state.EnvironmentTemplateData

@mumoshu
Copy link
Collaborator

mumoshu commented Jan 6, 2020

@etiennejournet Hey! The feature that supports the example isn't implemented yet.
Fortunately, we now have a better alternative #906 that you can use.

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

No branches or pull requests

6 participants