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

Encrypted runtime config #10

Open
JoeWoodward opened this issue May 5, 2020 · 9 comments
Open

Encrypted runtime config #10

JoeWoodward opened this issue May 5, 2020 · 9 comments
Labels
enhancement New feature or request

Comments

@JoeWoodward
Copy link
Contributor

I've been scratching my head with a problem which your post on elixirforum helped me squash. https://elixirforum.com/t/loading-custom-module-in-config-exs/23232
The problem being how to use the encrypted secrets inside a config file.

I am a long time ruby developer so this also seemed intuitive to me and was what I was looking for a solution to! Surprisingly hard to google, only found that thread after reading 10s of posts on compilation.

Anyway, based on the fact that it's not a good idea to decrypt these secrets during compilation as they'll be in the build unencrypted... maybe another solution is to create a runtime config module that behaves in a similar way but is called during startup. Similar to how you've proposed in the thread.

use EncryptedCredentials.RuntimeConfig
credentials = EncryptedCredentials.read!(file, key)

config :app, config_var: credentials[:config_var]

Then in Application#start/2 call this file

EncryptedCredentials.init_config

Just thinking out loud. For now I'm probably just going to build a module to do this for myself but while it was fresh thought it was worth writing down. The readme could also do with updating on how people actually get these credentials into the app and the limitations e.g. dependencies that require compiled configs rather than runtime

@JoeWoodward
Copy link
Contributor Author

Ok, I think I have something. Looking into how Plug works and found this article http://rrrene.org/2018/04/09/flow-elixir-metaprogramming/ on using metaprogramming for flow.

@kieraneglin
Copy link
Owner

Thanks for the research here! I don't have much time these days to chase this down but I'll gladly accept a PR or any notes toward getting this implemented 👍

@kieraneglin kieraneglin added the enhancement New feature or request label May 5, 2020
@JoeWoodward
Copy link
Contributor Author

I think I have something. Will write specs for it soon and get a PR out to you if you think this DSL makes sense? The config looks like this (can change the name of the module too, not sure if RuntimeConfig is the best name

defmodule MyApp.EncryptedConfig do
  use EncryptedSecrets.RuntimeConfig

  config :flashcards, MyApp.Mailer, api_key: :mailer_api_key
end

where :mailer_api_key is the yaml key.

mailer_api_key: 'my_api_key'
some_other_key: 'testing'

Or you can pass in nested keys by using a list

  config :flashcards, MyApp.Mailer, api_key: [:mailer_provider, :api_key]
mailer_provider:
  api_key: 'my_api_key'

@kieraneglin
Copy link
Owner

I like that DSL! What you've got makes sense to me so far.

As an aside, I've been thinking about what approach is the most flexible while being the least likely to leak secret data. I'm wondering about an approach similar to dotenv but with encrypted secrets. Loading these secrets into env pre-compilation should work for normal Elixir apps as well as Distillery releases, but I'd have to look deeper into security implications (secrets in build artifacts as well as leaking ENV globally).

@chevinbrown
Copy link

Any updates on this? I'd love to use in my project; this is the blocker currently.

@JoeWoodward
Copy link
Contributor Author

Sorry I haven't completed this and sadly don't have time to continue. I'm not using elixir anymore for the time being and have been very busy with other projects.

@kieraneglin
Copy link
Owner

Now that I have more experience with releases I think that this library's approach is totally incompatible with releases (or Distillery, for that matter).

I'm thinking that instead of trying to fight against the current, perhaps this project could change direction and encrypt your *.secrets.exs for storage in VCS and add some explicit decryption step for these files which can then be consumed by your app in the conventional way.

@acrolink
Copy link

acrolink commented Jan 23, 2022

Anyway, based on the fact that it's not a good idea to decrypt these secrets during compilation as they'll be in the build unencrypted ..

Do believe this concern applies here, I am using cloak and this library to encrypt the encryption key:

defmodule MyApp.Vault do
  use Cloak.Vault, otp_app: :my_app

  @impl GenServer
  def init(config) do
    config =
      Keyword.put(config, :ciphers,
        default:
          {Cloak.Ciphers.AES.GCM,
           tag: "AES.GCM.V1", key: Base.decode64!(Application.get_env(:my_app, :secrets).enc_key)} // here I read the encryption key.
      )

    {:ok, config}
  end
end

Why would providing / decrypting them in config.exs be safer?

@aus70
Copy link

aus70 commented Feb 28, 2022

It seems that loading the secrets in config/runtime.exs solves this issue. Can anybody confirm that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants