如何在 Strapi 中安全地设置数据库密码?

Posted

技术标签:

【中文标题】如何在 Strapi 中安全地设置数据库密码?【英文标题】:How to securely set database password in Strapi? 【发布时间】:2021-08-03 20:20:18 【问题描述】:

Strapi 框架(据我所知)要求在启动时提供数据库密码。通常,密码在database.js 文件中指定,如下所示:

module.exports = ( env ) => (
  defaultConnection: 'default',
  connections: 
    default: 
      connector: 'bookshelf',
      settings: 
        client: 'postgres',
        host: '/cloudsql/myDatabaseInstanceName',
        database: 'databaseName',
        username: 'databaseUsername',
        password: 'databasePassword',
      ,
    ,
  ,
);

这当然不是很安全,因为 database.js 文件通常会提交到 repo。

因此,有些人将密码注入database.js文件,而不是将其存储为环境变量:

module.exports = ( env ) => (
  defaultConnection: 'default',
  connections: 
    default: 
      connector: 'bookshelf',
      settings: 
        client: 'postgres',
        host: `/cloudsql/$env('INSTANCE_CONNECTION_NAME')`,
        database: env('DATABASE_NAME'),
        username: env('DATABASE_USERNAME'),
        password: env('DATABASE_PASSWORD'),
      ,
    ,
  ,
);

但是,这也不是很安全。在许多运行时环境(包括我正在使用的 Google App Engine)中,任何项目用户都可以以纯文本形式查看环境密码。

理想情况下,我想将数据库密码存储在一个秘密保险库中(我正在使用 Google Secret Manager),并在启动时以某种方式将保险库中的密码提供给 database.js 文件。但我不明白如何实现?甚至可以从database.js 访问秘密保险库吗?或者,我还能如何将我的数据库密码安全地注入 Strapi?

谢谢!

【问题讨论】:

【参考方案1】:

使用dotenv 和dotenv-defaults 包。

对于默认值和非关键值,请使用“.env.defaults”文件并将此文件提交到您的 VCS。 这将为其他开发人员提供一键式环境设置。

如果您的团队成员想要覆盖值,他们应该在本地开发环境中使用 gitignored ".env" 文件。 这将防止错误提交。

在您的服务器中,在外部定义环境变量并使用它们而不将它们嵌入到您的代码中。 这将为您的现场制作环境提供安全保障。

在这些包的文档中,您可以使用这些文件或环境变量中的任何值

....,
password: process.env.MY_PASSWORD,
....

【讨论】:

感谢您的回复!这绝对是一种方法,但是(正如我在问题中模糊提到的那样)我希望找到一个比将敏感数据存储在 prod 环境变量中更安全的解决方案,因为可以看到环境变量由有权访问 Google Cloud Platform 项目的所有人提供。 您应该使用 Secret Manager,它将加密的存储密码传递到您的应用程序环境中。所以在最后,你的应用程序从环境变量中读取秘密,但这些环境变量来自一个安全的地方。 cloud.google.com/run/docs/configuring/secrets 所以我想使用 Secret Manager,但是获取密钥的 API 调用是异步的,在导出配置对象之前我无法弄清楚如何调用异步函数。也许我可以使用***等待?但是那些在 JS 文件中不起作用,只能在 ES 模块中使用……我对 JS 没有很多经验;我不清楚如何使用 Secret Manager。【参考方案2】: @raxetul 评论是最简单的方法。可以从代码中作为环境变量访问 google secret。根据 Google - “很常见,但应尽可能避免”here 要在初始数据库配置之前通过异步代码检索密钥,您应该使用Strapi bootstrap function。

每次服务器启动时都会调用引导函数。您可以使用它在服务器生命周期的这个时刻添加特定逻辑。

无论您选择什么 - 请记住,任何可以更改密码的人 - 都可以访问密码,无论您存储的密码有多安全。 “流氓”开发人员可以添加类似 console.log(env('HIGHLY_ENCRYPTED_PASSWORD')) 的行并读取输出。

【讨论】:

bootstrap.js 需要返回某种 JS 对象,对吗?对象和database.js导出的对象格式一样吗? 不必返回任何东西,可以返回一个承诺,将秘密存储在您可以从 database.js 引用的某个地方。 等等,我如何“将秘密存储在可以从 database.js 引用的地方”?我尝试只使用一个全局变量,但显然这些变量不像我想象的那样工作。然后我尝试导出一个全局变量,但这是不允许的。

以上是关于如何在 Strapi 中安全地设置数据库密码?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android 应用程序中安全地存储凭据(密码)?

如何在移动应用程序中安全地存储密码

如何:具有动态区域/组件的 Strapi GraphQL 突变

Strapi,使用 Auth0 访问 Strapi 中的用户数据

如何使用 Strapi 在 GraphQL 中添加自定义查询?

如何通过 HTTP 安全地发送密码?