我正在尝试使用 Secrets Manager 从我的 Cloud Function 安全连接到 Cloud SQL (postgres) 实例。然而,我很困惑
鉴于此示例代码,
# Note: Saving credentials in environment variables is convenient, but not
# secure - consider a more secure solution such as
# Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
# keep secrets safe.
instance_connection_name = os.environ[
"INSTANCE_CONNECTION_NAME"
] # e.g. 'project:region:instance'
db_user = os.environ["DB_USER"] # e.g. 'my-db-user'
db_pass = os.environ["DB_PASS"] # e.g. 'my-db-password'
db_name = os.environ["DB_NAME"] # e.g. 'my-database'
ip_type = IPTypes.PRIVATE if os.environ.get("PRIVATE_IP") else IPTypes.PUBLIC
# initialize Cloud SQL Python Connector object
connector = Connector()
def getconn() -> pg8000.dbapi.Connection:
conn: pg8000.dbapi.Connection = connector.connect(
instance_connection_name,
"pg8000",
user=db_user,
password=db_pass,
db=db_name,
ip_type=ip_type,
)
return conn
我确定了四个设置:实例连接名称、数据库用户、数据库密码和数据库名称(代码来自 https://cloud.google.com/sql/docs/postgres/connect-functions)。
另外,当我看到这篇文章时, 这意味着实例连接名称、数据库用户和数据库密码应作为秘密存储。
我的第一个问题是,这 3 个都应该作为单独的机密存储在 Secrets Manager 中吗?或者它们应该以某种格式存在于一个秘密中? 例如JSON 格式
{ "db_user": "my-db-user", "db_pass": "my-db-password", "instance_connection_name": "xxx" }
当机密作为卷安装时,从性能角度来看,后者更容易检索,但安全性较低,因为攻击者需要破坏对单个机密的访问才能连接到数据库,而不是三个。
第二个问题与上述评论相关:考虑到连接到 SQL 数据库的开销,我是否应该尝试通过将我的秘密公开为环境变量而不是将它们安装为卷来提高性能?
第三个问题是数据库名怎么办。第二篇文章中没有指定,但是将数据库名称存储在环境变量中是否安全,或者也应该存储为秘密?
作为参考,这是我当前的代码,它将数据库用户/密码和实例连接名称存储在秘密中,并将它们作为卷安装在云功能中:
import sqlalchemy
from google.cloud.sql.connector import Connector, IPTypes
connector = Connector()
def getconn():
with open(
"/etc/secrets1/instance-connection-name", "r", encoding="utf-8"
) as f:
instance_connection_name = f.read()
with open("/etc/secrets2/db-user", "r", encoding="utf-8") as f:
db_user = f.read()
with open("/etc/secrets3/db-pass", "r", encoding="utf-8") as f:
db_pass = f.read()
db_name = os.environ.get("DB_NAME")
conn = connector.connect(
instance_connection_name,
"pg8000",
user=db_user,
password=db_pass,
db=db_name,
ip_type=IPTypes.PUBLIC,
)
return conn
pool = sqlalchemy.create_engine(
"postgresql+pg8000://",
creator=getconn,
)
def main():
with pool.connect() as db_conn:
results = db_conn.execute(
sqlalchemy.text(
"select * from pets"
)
).fetchall()
return results
对于您的问题:
如果最佳解决方案不是使用登录名/密码而只是使用 Cloud Functions 身份登录 PostgreSQL 实例怎么办?
看看这里,这是我推荐的方式:https://cloud.google.com/sql/docs/postgres/authentication