如何在公共rails应用程序中存储敏感数据?

时间:2021-12-24 11:22:26

My personal rails project uses a few API's for which I store the API keys/secrets in config/environments/production.yml and development.yml as global variables. I now want to push this project to github for others to use, but I don't want them to have those bits of sensitive data. I also don't want this file in .gitignore because it's required for the app to run. I've considered putting them in the DB somewhere, but am hoping to find a better solution.

我的个人rails项目使用了一些API,我将API密钥/秘密存储在配置/环境/产品中。yml和发展。yml作为全局变量。我现在想把这个项目推到github供其他人使用,但我不想让他们拥有那些敏感数据。我也不希望这个文件在。gitignore中,因为这个应用程序需要运行。我考虑过把它们放在DB上,但我希望找到更好的解决方案。

5 个解决方案

#1


48  

TLDR: Use environment variables!

TLDR:使用环境变量!

I think @Bryce's comment offers an answer, which I'll just flush out. It seems one approach Heroku recommends is to use environment variables to store sensitive information (API key strings, database passwords). So survey your code and see in which you have sensitive data. Then create environment variables (in your .bashrc file for example) that store the sensivite data values. For example for your database:

我认为@Bryce的评论提供了一个答案,我将把它冲洗出来。Heroku推荐的一种方法是使用环境变量来存储敏感信息(API密钥字符串、数据库密码)。所以调查你的代码,看看你有哪些敏感的数据。然后创建环境变量(例如在.bashrc文件中),以存储sensivite数据值。例如,您的数据库:

export MYAPP_DEV_DB_DATABASE=myapp_dev
export MYAPP_DEV_DB_USER=username
export MYAPP_DEV_DB_PW=secret

Now, in your local box, you just refer to the environment variables whenever you need the sensitive data. For example in database.yml :

现在,在本地框中,只要在需要敏感数据时引用环境变量即可。例如在数据库。yml:

development:
  adapter: mysql2
  encoding: utf8
  reconnect: false
  database: <%= ENV["MYAPP_DEV_DB_DATABASE"] %>
  pool: 5
  username: <%= ENV["MYAPP_DEV_DB_USER"] %>
  password: <%= ENV["MYAPP_DEV_DB_PW"] %>
  socket: /var/run/mysqld/mysqld.sock

I think database.yml gets parsed just at the app's initialization or restart so this shouldn't impact performance. So this would solve it for your local development and for making your repository public. Stripped of sensitive data, you can now use the same repository for the public as you do privately. It also solves the problem if you are on a VPS. Just ssh to it and set up the environment variables on your production host as you did in your development box.

我认为数据库。yml在应用程序的初始化或重启时被解析,因此不应该影响性能。因此,这将解决您的本地开发和使您的存储库公开的问题。除去敏感数据,您现在可以为公众使用与您私下使用相同的存储库。它也解决了问题,如果您在一个VPS。只需ssh,并在生产主机上设置环境变量,就像在开发框中所做的那样。

Meanwhile, if your production setup involves a hands off deployment where you can't ssh to the production server, like Heroku's does, you need to look at how to remotely set up environment variables. For Heroku this is done with heroku config:add. So, per the same article, if you had S3 integrated into your app and you had the sensitive data coming in from the environment variables:

同时,如果您的产品设置涉及到无法像Heroku那样ssh到生产服务器的手工部署,那么您需要了解如何远程设置环境变量。对于Heroku,这是通过Heroku配置完成的:添加。因此,根据同一篇文章,如果你把S3集成到你的应用中,你有来自环境变量的敏感数据:

AWS::S3::Base.establish_connection!(
  :access_key_id     => ENV['S3_KEY'],
  :secret_access_key => ENV['S3_SECRET']
)

Just have Heroku create environment variables for it:

让Heroku为它创建环境变量:

heroku config:add S3_KEY=8N022N81 S3_SECRET=9s83159d3+583493190

Another pro of this solution is that it's language neutral, not just Rails. Works for any app since they can all acquire the environment variables.

这个解决方案的另一个优点是它是语言中立的,而不仅仅是Rails。适用于任何应用程序,因为它们都可以获得环境变量。

#2


3  

How about this...

这个怎么样…

Create a new project and check it into GitHub with placeholder values in the production.yml and development.yml files.

创建一个新项目,并将其检查到GitHub中,并在产品中使用占位符值。yml和发展。yml文件。

Update .gitignore to include production.yml and development.yml.

更新。gitignore,包括生产。yml development.yml。

Replace the placeholder values with your secrets.

用您的秘密替换占位符值。

Now you can check your code into GitHub without compromising your secrets.

现在你可以在不泄露你的秘密的情况下把你的代码检查到GitHub上。

And anyone can clone your repo without any extra steps to create missing files (they'll just replace the placeholder values as you did).

任何人都可以克隆您的repo,而不需要任何额外的步骤来创建丢失的文件(它们只会像您那样替换占位符值)。

Does that meet your goals?

这符合你的目标吗?

#3


1  

They're probably best put in initializers (config/initializers/api.yaml) though I think what you've got cooked up is fine. Add the actual keys to your .gitignore file and run git rm config/environments/production.yml to remove that sensitive data from your repo. Fair warning, it will remove that file too so back it up first.

它们可能是最好的初始化器(配置/初始化器/api.yaml),尽管我认为您已经准备好了。向.gitignore文件添加实际的键,并运行git rm配置/环境/生产。yml从你的repo中删除敏感数据。合理的警告,它会删除文件,所以先备份。

Then, just create a config/environments/production.yml.example file next to your actual file with the pertinent details but with the sensitive data left out. When you pull it out to production, just copy the file without the .example and substitute the appropriate data.

然后,创建一个config/environment /product .yml。示例文件位于实际文件旁边,其中包含相关细节,但忽略了敏感数据。当您将它取出到生产环境中时,只需复制文件而不带.example,并替换适当的数据。

#4


1  

Use environment variables.

使用环境变量。

In Ruby, they're accessible like so:

在Ruby中,它们是可以访问的:

ENV['S3_SECRET']

Two reasons:

两个原因:

  1. The values will not make it into source control.
  2. 这些值不会使它成为源代码控件。
  3. "sensitive data" aka passwords tend to change on a per-environment basis anyways. e.g. you should be using different S3 credentials for development vs production.
  4. 无论如何,“敏感数据”(即密码)在每个环境下都有变化。您应该使用不同的S3凭证用于开发和生产。

Is this a best practice?
Yes: http://12factor.net/config

这是最佳实践吗?是的:http://12factor.net/config

How do I use them locally?
foreman and dotenv are both easy. Or, edit your shell.

如何在本地使用它们?工头和多滕夫都很容易。或者,编辑您的shell。

How do I use them in production?
Largely, it depends. But for Rails, dotenv is an easy win.

我如何在生产中使用它们?很大程度上,这取决于。但是对于Rails来说,dotenv是一场轻松的胜利。

What about platform-as-a-service?
Any PaaS should give you a way to set them. Heroku for example: https://devcenter.heroku.com/articles/config-vars

平台呢?任何PaaS都应该提供一种设置它们的方法。Heroku例如:https://devcenter.heroku.com/articles/config-vars

Doesn't this make it more complicated to set up a new developer for the project?
Perhaps, but it's worth it. You can always check a .env.sample file into source control with some example data in it. Add a note about it to your project's readme.

这难道不会使为项目建立一个新的开发人员变得更加复杂吗?也许,但这是值得的。你可以检查。env。示例文件到源代码控制中,其中包含一些示例数据。在您的项目自述中添加关于它的说明。

#5


1  

Rails 4.1 has now a convention for it. You store this stuff in secrets.yml. So you don't end up with some global ENV calls scattered across Your app.

Rails 4.1现在有了它的约定。你把这些东*在秘密里。所以你不会在你的应用程序中有一些全局的ENV调用。

This yaml file is like database.yml erb parsed, so you are still able to use ENV calls here. In that case you can put it under version control, it would then serve just as a documentation which ENV vars has to be used. But you also can exlcude it from version control and store the actual secrets there. In that case you would put some secrets.yml.default or the like into the public repo for documentation purposes.

这个yaml文件类似于数据库。yml erb解析后,仍然可以使用ENV调用。在这种情况下,您可以将它置于版本控制之下,然后它将作为ENV vars必须使用的文档。但你也可以从版本控制中去除它,并在那里存储实际的秘密。在这种情况下,你会把一些秘密文件或类似的东西放入公共的回购文件中。

development: 
   s3_secret: 'foo'
production: 
   s3_secret: <%= ENV['S3_SECRET']%>

Than you can access this stuff under

比你能在

Rails.application.secrets.s3_secret

Its discussed in detail at the beginning of this Episode

本集一开始就对其进行了详细的讨论

#1


48  

TLDR: Use environment variables!

TLDR:使用环境变量!

I think @Bryce's comment offers an answer, which I'll just flush out. It seems one approach Heroku recommends is to use environment variables to store sensitive information (API key strings, database passwords). So survey your code and see in which you have sensitive data. Then create environment variables (in your .bashrc file for example) that store the sensivite data values. For example for your database:

我认为@Bryce的评论提供了一个答案,我将把它冲洗出来。Heroku推荐的一种方法是使用环境变量来存储敏感信息(API密钥字符串、数据库密码)。所以调查你的代码,看看你有哪些敏感的数据。然后创建环境变量(例如在.bashrc文件中),以存储sensivite数据值。例如,您的数据库:

export MYAPP_DEV_DB_DATABASE=myapp_dev
export MYAPP_DEV_DB_USER=username
export MYAPP_DEV_DB_PW=secret

Now, in your local box, you just refer to the environment variables whenever you need the sensitive data. For example in database.yml :

现在,在本地框中,只要在需要敏感数据时引用环境变量即可。例如在数据库。yml:

development:
  adapter: mysql2
  encoding: utf8
  reconnect: false
  database: <%= ENV["MYAPP_DEV_DB_DATABASE"] %>
  pool: 5
  username: <%= ENV["MYAPP_DEV_DB_USER"] %>
  password: <%= ENV["MYAPP_DEV_DB_PW"] %>
  socket: /var/run/mysqld/mysqld.sock

I think database.yml gets parsed just at the app's initialization or restart so this shouldn't impact performance. So this would solve it for your local development and for making your repository public. Stripped of sensitive data, you can now use the same repository for the public as you do privately. It also solves the problem if you are on a VPS. Just ssh to it and set up the environment variables on your production host as you did in your development box.

我认为数据库。yml在应用程序的初始化或重启时被解析,因此不应该影响性能。因此,这将解决您的本地开发和使您的存储库公开的问题。除去敏感数据,您现在可以为公众使用与您私下使用相同的存储库。它也解决了问题,如果您在一个VPS。只需ssh,并在生产主机上设置环境变量,就像在开发框中所做的那样。

Meanwhile, if your production setup involves a hands off deployment where you can't ssh to the production server, like Heroku's does, you need to look at how to remotely set up environment variables. For Heroku this is done with heroku config:add. So, per the same article, if you had S3 integrated into your app and you had the sensitive data coming in from the environment variables:

同时,如果您的产品设置涉及到无法像Heroku那样ssh到生产服务器的手工部署,那么您需要了解如何远程设置环境变量。对于Heroku,这是通过Heroku配置完成的:添加。因此,根据同一篇文章,如果你把S3集成到你的应用中,你有来自环境变量的敏感数据:

AWS::S3::Base.establish_connection!(
  :access_key_id     => ENV['S3_KEY'],
  :secret_access_key => ENV['S3_SECRET']
)

Just have Heroku create environment variables for it:

让Heroku为它创建环境变量:

heroku config:add S3_KEY=8N022N81 S3_SECRET=9s83159d3+583493190

Another pro of this solution is that it's language neutral, not just Rails. Works for any app since they can all acquire the environment variables.

这个解决方案的另一个优点是它是语言中立的,而不仅仅是Rails。适用于任何应用程序,因为它们都可以获得环境变量。

#2


3  

How about this...

这个怎么样…

Create a new project and check it into GitHub with placeholder values in the production.yml and development.yml files.

创建一个新项目,并将其检查到GitHub中,并在产品中使用占位符值。yml和发展。yml文件。

Update .gitignore to include production.yml and development.yml.

更新。gitignore,包括生产。yml development.yml。

Replace the placeholder values with your secrets.

用您的秘密替换占位符值。

Now you can check your code into GitHub without compromising your secrets.

现在你可以在不泄露你的秘密的情况下把你的代码检查到GitHub上。

And anyone can clone your repo without any extra steps to create missing files (they'll just replace the placeholder values as you did).

任何人都可以克隆您的repo,而不需要任何额外的步骤来创建丢失的文件(它们只会像您那样替换占位符值)。

Does that meet your goals?

这符合你的目标吗?

#3


1  

They're probably best put in initializers (config/initializers/api.yaml) though I think what you've got cooked up is fine. Add the actual keys to your .gitignore file and run git rm config/environments/production.yml to remove that sensitive data from your repo. Fair warning, it will remove that file too so back it up first.

它们可能是最好的初始化器(配置/初始化器/api.yaml),尽管我认为您已经准备好了。向.gitignore文件添加实际的键,并运行git rm配置/环境/生产。yml从你的repo中删除敏感数据。合理的警告,它会删除文件,所以先备份。

Then, just create a config/environments/production.yml.example file next to your actual file with the pertinent details but with the sensitive data left out. When you pull it out to production, just copy the file without the .example and substitute the appropriate data.

然后,创建一个config/environment /product .yml。示例文件位于实际文件旁边,其中包含相关细节,但忽略了敏感数据。当您将它取出到生产环境中时,只需复制文件而不带.example,并替换适当的数据。

#4


1  

Use environment variables.

使用环境变量。

In Ruby, they're accessible like so:

在Ruby中,它们是可以访问的:

ENV['S3_SECRET']

Two reasons:

两个原因:

  1. The values will not make it into source control.
  2. 这些值不会使它成为源代码控件。
  3. "sensitive data" aka passwords tend to change on a per-environment basis anyways. e.g. you should be using different S3 credentials for development vs production.
  4. 无论如何,“敏感数据”(即密码)在每个环境下都有变化。您应该使用不同的S3凭证用于开发和生产。

Is this a best practice?
Yes: http://12factor.net/config

这是最佳实践吗?是的:http://12factor.net/config

How do I use them locally?
foreman and dotenv are both easy. Or, edit your shell.

如何在本地使用它们?工头和多滕夫都很容易。或者,编辑您的shell。

How do I use them in production?
Largely, it depends. But for Rails, dotenv is an easy win.

我如何在生产中使用它们?很大程度上,这取决于。但是对于Rails来说,dotenv是一场轻松的胜利。

What about platform-as-a-service?
Any PaaS should give you a way to set them. Heroku for example: https://devcenter.heroku.com/articles/config-vars

平台呢?任何PaaS都应该提供一种设置它们的方法。Heroku例如:https://devcenter.heroku.com/articles/config-vars

Doesn't this make it more complicated to set up a new developer for the project?
Perhaps, but it's worth it. You can always check a .env.sample file into source control with some example data in it. Add a note about it to your project's readme.

这难道不会使为项目建立一个新的开发人员变得更加复杂吗?也许,但这是值得的。你可以检查。env。示例文件到源代码控制中,其中包含一些示例数据。在您的项目自述中添加关于它的说明。

#5


1  

Rails 4.1 has now a convention for it. You store this stuff in secrets.yml. So you don't end up with some global ENV calls scattered across Your app.

Rails 4.1现在有了它的约定。你把这些东*在秘密里。所以你不会在你的应用程序中有一些全局的ENV调用。

This yaml file is like database.yml erb parsed, so you are still able to use ENV calls here. In that case you can put it under version control, it would then serve just as a documentation which ENV vars has to be used. But you also can exlcude it from version control and store the actual secrets there. In that case you would put some secrets.yml.default or the like into the public repo for documentation purposes.

这个yaml文件类似于数据库。yml erb解析后,仍然可以使用ENV调用。在这种情况下,您可以将它置于版本控制之下,然后它将作为ENV vars必须使用的文档。但你也可以从版本控制中去除它,并在那里存储实际的秘密。在这种情况下,你会把一些秘密文件或类似的东西放入公共的回购文件中。

development: 
   s3_secret: 'foo'
production: 
   s3_secret: <%= ENV['S3_SECRET']%>

Than you can access this stuff under

比你能在

Rails.application.secrets.s3_secret

Its discussed in detail at the beginning of this Episode

本集一开始就对其进行了详细的讨论