从 Firebase 功能使用 Cloud SQL 代理

Posted

技术标签:

【中文标题】从 Firebase 功能使用 Cloud SQL 代理【英文标题】:Using Cloud SQL Proxy from Firebase function 【发布时间】:2020-04-19 13:59:15 【问题描述】:

我在本地运行 Google 的 Cloud SQL Proxy,它使用以下命令与本地提供的 Firebase 功能一起使用:

/cloud_sql_proxy -instances=my-project-12345:us-central1:my-instance=tcp:1433

但是我真的不知道如何在已部署的 Firebase 功能上进行这项工作。

export const typeOrmConnectionOptions: ConnectionOptions = 
  name: 'primary',
  type: 'mssql',
  host: '127.0.0.1',
  port: 1433,
  username: 'sqlserver',
  password: 'my$trongPa$$word',
  database: 'TestDB',
  synchronize: true,
  logging: true,
  entities: ['lib/entity/**/*.js'],
  ...(prod && 
    extra: 
      socketPath:
        '/cloudsql/my-project-12345:us-central1:my-instance=tcp',
      credential_file: './admin-service-account-file-long-a1b2c3-hash.json'
    
  )
;

我真的是在黑暗中拍摄,将凭证文件作为额外对象的一部分传递给 TypeORM 的连接对象,但是我觉得必须有这样的东西才能链接我在 this step 之后创建的服务帐户到数据库查询。

我的另一个长期想法是使用the environment variable 来设置使用此 JSON 文件的凭据:

process.env.GOOGLE_APPLICATION_CREDENTIALS = fs.readFileSync(
  './admin-service-account-file-long-a1b2c3-hash.json',
  'utf8'
)

不开心。

我认为错误消息没有多大帮助,因为我确定我尝试这样做的方式从根本上是不正确的,但是对于它的价值,上面得到了错误

"Failed to connect to 127.0.0.1:1433 - connect ECONNREFUSED 127.0.0.1:1433"

如何使用 Cloud SQL 代理从 Firebase 连接到 GCP 数据库?

编辑

我没有运气连接socketPath 属性,也没有使用 root 用户名和密码直接引用 GCP RD 实例的 IP。我在很多地方看到云代理只在本地开发中需要,在生产中也需要它(这就是我对socketPath 的想法)。

此外,我还尝试使用 mysql 进行测试,如下面的答案中所链接。以前我用它作为 SQL Server 的指南,但由于它仍处于测试阶段,我想我会试试 MySQL。仍然失败,但是当使用它并使用服务 IP 而不是云代理时,我收到超时错误。

我还使用从 GCP 仪表板创建的服务帐户凭据开始 initializing the app。

import  serviceAccount  from './service-account';
const adminConfig = JSON.parse(process.env.FIREBASE_CONFIG);
adminConfig.credential = admin.credential.cert(
  serviceAccount as admin.ServiceAccount
);
admin.initializeApp(adminConfig);

【问题讨论】:

【参考方案1】:

只有在尝试从谷歌云网络外部连接时才需要云代理。从函数中,您可以使用主机、端口、用户名和密码直接连接。

我在部署期间通过函数配置传递了这些细节。

firebase functions:config:set envs.db_host=$DB_HOST_PROD envs.db_user=$DB_USER_PROD envs.db_password=$DB_PASSWORD_PROD envs.db_name=$DB_NAME_PROD envs.db_use_ssl=false --project hello-world

firebase functions:config:set envs.node_env=production --project hello-world

firebase deploy --token=$FIREBASE_TOKEN --project hello-world --only functions,hosting

请参阅https://***.com/a/55974919/515774,了解我如何使用它来设置环境变量。然后我使用环境变量连接数据库

【讨论】:

嗯,我明白了,谢谢。 FIREBASE_TOKEN 来自哪里? 这些命令来自我的 CI 系统。参考this获取新令牌github.com/firebase/firebase-tools#using-with-ci-systems 这似乎不适用于使用 db 用户名/密码及其 IP 作为连接主机的 firebase。您确定您没有启用某些服务帐户或其他权限或使用例如admin.credential.cert( serviceAccountJson );(这对我也不起作用,但只是我尝试过的。 当安全很重要时,这不是一个好的答案。使用基于主机 (IP) 的连接意味着向全世界(非常糟糕)或向 Google IP 地址(仍然很糟糕)开放 Cloud SQL 实例。 Cloud SQL 代理是连接到 Cloud SQL 的推荐安全方法。【参考方案2】:

要从 Cloud Function(或 Firebase 函数)连接到 Cloud SQL 实例,您可以使用 UNIX 域套接字。该文档仅显示how to do this for MySQL and PosgreSQL,不适用于 SQL Server。可能是因为还不支持。不过,我鼓励您尝试一下。

无论哪种方式,您都可以将 Cloud Functions 连接到 SQL Server Cloud SQL 实例 using a Serverles VPC Connector and the instance's private IP。引用文档:

默认情况下,Cloud Functions 不支持使用 TCP 连接到 Cloud SQL 实例。除非您已配置无服务器 VPC 访问,否则您的代码不应尝试使用 IP 地址(例如 127.0.0.1 或 172.17.0.1)访问实例。

【讨论】:

域套接字是否需要一个云代理实例才能在 Firebase 中运行?从您链接的文档中,socketPath: /cloudsql/$process.env.CLOUD_SQL_CONNECTION_NAME``,/cloudsql... 看起来像是 Firebase 主机上的一个目录。这需要以某种方式打开吗?只需按原样设置连接就会给我同样的连接问题。 不,您不需要设置 Cloud SQL 代理。代理用于从 GCP 外部或 Cloud SQL 实例所在的 VPC 网络外部连接到 Cloud SQL 实例。您可能会遇到连接问题,因为域套接字可能对 SQL Server 不可用。您仍然可以尝试按照答案链接中的说明设置无服务器 VPC 连接器 该链接对于如何选择 IP 范围相当模糊。你知道吗?我尝试输入recommended page 为我的区域提供的范围,但在创建后,我收到连接器处于“错误状态,建议手动删除”的错误。另外,对于网络,我只能选择“默认”,这似乎也不是我所期望的。 您是否仍然面临此设置的任何问题?我还想提一下,我编辑了您的原始问题以隐藏潜在的用户密码。如果这恰好是您的密码,请立即用新密码替换。

以上是关于从 Firebase 功能使用 Cloud SQL 代理的主要内容,如果未能解决你的问题,请参考以下文章

Flutter Firebase Cloud 功能无法调用

无法按日期从 Google Cloud Pub/Sub 功能中的 Firebase 获取文档

在 Firebase Cloud 功能中启用 Cors

使用 Cloud Functions 的下载 URL 从 Firebase 存储中删除文件

如何直接从您的 Angular 项目中调用 Firebase Cloud Function

如何使用 Cloud Function 将数据从 Firebase Firestore 索引到 Elastic App Search?