为什么在使用 "App Platform" 时将 API 密钥存储在 DigitalOceans API "Environment Variable" 选项中是安全的?

Why is it safe to store API keys in DigitalOceans API "Environment Variable" option when using "App Platform"?

我正在设置一个 NodeJS 后端,它需要保存一些 API 密钥以与其他 Firebase 联系以对用户进行身份验证。

我已经能够发布后端并从其上的 API 端点成功获得 HTTP 回复。我使用 Express 来 运行 NodeJS API.

现在我希望 NodeJS API 充当我的用户和数据库联系点。但是我不确定在哪里安全地存储项目的 API 密钥。因为我对这种安全类型比较陌生。

所以,我用 Google 搜索了一下,发现人们说 .env 文件不是存储 API 密钥的安全地方。然而在 DigitalOcean documentation 上它说了以下内容:

Environment variables are excellent places to store sensitive information (such as API keys), or information that needs to be globally accessible from anywhere in the app, (such as version numbers or hardcoded paths).

所以我的问题是,为什么 DigitalOcean 会说在环境变量中存储 API 密钥是安全的,而许多其他来源都说它不是。这是因为危险在于文件的可访问性,然后 DigitalOcean 以某种方式保护文件吗? 我注意到他们有一个你可以勾选的“秘密”布尔框,它说它不会出现在控制台中。但是对于一般人来说是否也完全无法访问?

我主要关心的是防止黑客或有恶意的人访问 API 密钥。我不担心有合法访问权限的人会滥用它,只有没有合法访问权限的人会滥用它。

期待您的见解。

我将按照以下顺序(从最不安全到最安全)对存储秘密的安全性进行排序:

  1. 将它们直接存储在您的代码中(真的非常糟糕)
  2. 将它们存储在环境变量中
  3. 将它们存储在磁盘上的文件中
    • 可以设置访问权限,例如谁可以阅读它
    • 如果将内容加载到环境变量中,则与 Point 2
    • 没有区别
  4. 将它们存储在对象存储中(AWS S3,Google 云存储)
  5. 使用机密管理器(AWS、GCP 机密管理器)存储它们
  6. 使用 IAM(实际上不是存储秘密的地方,而是一种控制谁可以使用上述方法访问秘密的方法)。

阐述:

第 2 点和第 3 点:

如果您的系统受到威胁,points 2 and 3 之间的区别就会变得模糊不清。在这种情况下,如果攻击者拥有 root 访问权限,he/she 可以 read/write/delete/change 一切,因此 point 3 将失败。对于 point 2,攻击者可以通过 3 种方法访问环境变量:

根据@phmmmer 在this post

  1. The running environment of the process When the process is running, the environment variables of that process can be > > accessed through /proc/$PID/environ. However, only the user who owns the process, or root, can access that file.

  2. The source of the environment variables If you're using an init script, and the variables are stored in that init script, the variables can of course be obtained by reading that script.

Or if the environment variables are coming from somewhere else, then wherever that is.

  1. 'ps' output Yeah, I know I said 2, and in any decent system, it will be 2. However if the admin doesn't know what he's doing, it's possible to open up the 3rd avenue.

If the process is launched via something like sh -c 'cd /foo/bar; POP=tart /my/executable', then that sh process will be visible in ps: If the process is launched via something like sh -c 'cd /foo/bar; POP=tart /my/executable', then that sh process will be visible in ps:


$ ps ax | grep POP phemmer   3085  14   5  0.0  0.0 SN         00:00
sh -c cd /; POP=tart sleep 10```

第 4 点:

您可以将机密作为对象存储在对象存储中,并在部署或启动期间下载它们。大多数对象存储都提供日志记录功能,因此您还可以监控您的秘密如何被使用以及谁在使用它们。注意:Point 4很好,当且仅当您正确配置了IAM权限。否则,它与 Point 2 没有区别,尽管现在您是从远程位置获取文件。

第 5 点:

您的应用程序可以使用所有机密管理器的 API 以使用机密。除了内存之外,您的秘密不会存储在本地的任何地方。是的。您也可以加密您的内存,您可以在 this post

中阅读更多内容

第 6 点:

IAM 或身份和访问管理用于在正确的时间向正确的资源person/user/application授予正确的访问权限。它不是秘密存储,但可用于管理对秘密存储的访问。

所以回答你的问题:

"Environment variables are excellent places to store sensitive information" 可能是 DO 的夸大其词。但他们提供的不仅仅是将您的敏感信息存储在环境变量中然后将它们留在那里。

在您在问题中提到的文档的 next post "How to Use Environment Variables in App Platform" 中,确实提供了有关环境变量的某些级别的访问控制和加密:

  1. 运行时变量
    • 应用创建期间
    • 创建应用后
  2. 构建时间变量
  3. 环境变量中的可绑定变量
    • 应用范围的变量
    • 特定于组件的变量

所以当人们说使用环境变量存储敏感信息不安全时,他们中的大多数人都在谈论没有访问控制和加密的普通环境变量。在这种情况下,将 API 密钥存储在那里绝对是不安全的。应使用普通环境变量来存储端口号、生产环境或其他非敏感信息等信息。

有一些 post 我用作此答案的参考:

  1. 5 ways to manage serverless secrets, ranked best to worst
  2. A comprehensive guide to managing secrets in your Terraform code
  3. DigitalOcean: How to Use Environment Variables in App Platform

同意前面的post。一个好的做法是考虑“如果您的系统受到威胁,它们将 运行 作为您系统上的 ROOT”。如果有任何事情你可以像 sudo 一样做 - 假设他们也可以。

我想补充的一个项目是养成使用唯一 API 密钥的习惯,用于 dev/test/prod/ 和每个本地开发人员。我知道这似乎很明显,但我已经看到很多情况,人们在产品中做了很棒的事情,但在开发中重复使用相同的 API 键,甚至允许开发人员在产品中使用相同的 API 键他们的本地机器没有受到同样严格的保护。

如上所述使用 IAM 也能很好地确保限制访问,但如果您沿着这条路走下去,请确保您愿意让自己更难在 Azure、AWS、GCP 环境之间移动。