如何从 App Engine 应用程序中使用强制 SSL 连接到 Google Cloud SQL

How to connect to Google Cloud SQL with enforced SSL from within App Engine app

我想在连接到我的 Google Cloud SQL (postgres) 实例时强制执行 SSL,但我找不到为我的 [=22= 提供证书的方法] 部署到 App Engine 的应用程序 - psycopg2 要求证书具有适当的权限:<cert> has group or world access; permissions should be u=rw(0600) or less,但由于无法访问 App Engine 上的 chmod,我不知道如何更改它。

有什么想法吗?

为了提供上下文,目标主要是在 GCP 之外(从我的工作站)强制安全访问数据库。 App Engine 应用程序的问题是此更改的副作用。但也许有不同的更好的方法来实现同样的目标?

谢谢。

这有点棘手,因为这里存在先有鸡还是先有蛋的问题:

  • Postgres 驱动程序需要一个文件(因为它是读取文件的 C 库的包装器)
  • 并且您无法在启动时在 App Engine 中设置正确的文件权限。

这个问题有几种情况(和解决方案):

  • AppEngine 经典环境
    • 解决方法 - 自己将证书文件写入 /tmp ramdisk
    • 使用 UNIX 套接字连接到具有 public IP 地址(无 SSL)的云 SQL 实例。
    • 或者对具有 私有 IP 地址的云 SQL 实例使用 VPC 和私有 VPC 访问 and 使用解决方法.
  • AppEngine Flex 环境
    • 在您的 docker 图像中包含证书文件

解决方法:自己将证书文件写入 /tmp

解决此问题的最简单方法是自己将证书文件写入 /tmp - 这是 App Engine 环境中的虚拟磁盘。

像这样的东西就可以了:

import os
import psycopg2

certfile_path = '/tmp/certfile' # /tmp/ is a ramdisk
certfile_content = os.environ.get('CERTFILE')

if certfile_content != None:
   with open(certfile_path,'w+') as fp:
      fp.write(certfile_content)
   os.chmod(certfile_path, 0o600)
   # Now the certfile is "safe" to use, we can pass it in our connection string:
   connection_string= f"postgres+prycopg2://host/database?sslmode=require&sslcert={certfile_path}"

else:
   connection_string = 'postgres+prycopg2://host/database'
   # or just trow an exception, log the problem, and exit.

(有关 SSL 选项,请参阅 Postgres connection string reference

长期解决方案

使用 SSL 的目的是在数据库和您之间加密流量,并避免中间人攻击。

这里有一些选项:

  • 选项 1:当您在 App Engine 中时 AND 您的云 SQL 实例具有 public IP 地址。

    在这种情况下,您可以使用 Unix 域套接字连接到 Postgres 实例。 Google 使用代理侦听该套接字并将负责加密和保护端点(顺便说一句 - SSL 已禁用)。

    在这种情况下,您需要向您使用的服务帐户添加 SQL Client 权限,并在您的 Yaml 文件中添加 UNIX 套接字目录(请参阅 Google documentation).

  • 选项 2:当您在 App Engine Classic 中时 AND 您的云 SQL 实例具有私有 IP 地址。

    如果您的云 SQL 实例有一个 私有 IP,这可能会更“简单”一些。 我们需要启用无服务器 VPC 访问 - 这会将 AppEngine 连接到我们在私有 IP 地址上拥有资源的 VPC(对于 public IP,不需要,因为 public IP 地址不重叠)和云 SQL服务器必须连接到VPC。

    现在您可以像往常一样连接到 Postgres。 VPC 网络内部的流量是加密的。如果您在 VPC 中只有这个 CloudSQL 实例,则无需使用 SSL(没有人可以在网络上放置嗅探器 进行 Mitm 攻击)。

    但是如果您仍然want/need使用 SSL,则必须使用之前描述的解决方法。

  • 选项 3:使用 AppEngine FLEX 环境。

    flex 环境是 'just' 一个 docker 图像。 您需要为包含证书文件的 Python 运行时构建自定义 docker 映像。 请记住,免费套餐中不包含 Flex 环境。

Google Cloud App Engine 使用 Cloud SQL 代理进行任何使用 /cloudsql unix 套接字目录中的构建的连接。这些连接会自动包装在 SSL 层中,直到它们到达您的 Cloud SQL 实例。

您无需担心使用证书,因为代理会自动为您完成此过程。