访问秘密
如果您的流程需要访问一个需要认证的外部服务(例如,数据库),您需要向流程提供凭证。如果安全不是一个问题,您可以轻松使用 Metaflow parameters来实现这一点。然而,涉及凭证和其他敏感信息时,安全性是首要问题。
业界标准最佳实践是将凭据存储在密钥管理器中,例如 AWS Secrets Manager,Azure Key Vault 或 GCP Secret Manager。一旦凭据由这样的系统管理,Metaflow 提供了一个装饰器 @secrets,使在流程中安全访问它们变得简单。
有关更多背景信息,请参见 关于 @secrets 的启动博客文章。此外,请查看 关于 @secrets 的API文档。
目前, @secrets 支持 AWS Secrets Manager、Azure Key Vault 和 GCP Secrets Manager。如果您对使用其他秘密管理工具感兴趣,请在 Metaflow support Slack 上联系我们。
基本使用
该视频提供了关于如何在Metaflow中存储一个秘密并访问它的一分钟概述(没有声音):
秘密管理器将秘密存储为一组通过名称识别的键值对。给定一个名称,@secrets 装饰器获取键值对 - 假设您的 IAM 用户被允许读取秘密 - 并通过环境变量将它们暴露出来。
这里是视频中展示的简单示例:
from metaflow import FlowSpec, step, secrets
import os
class SecretFlow(FlowSpec):
@secrets(sources=['metaflow-example-password'])
@step
def start(self):
print("Here's the password:", os.environ['password'])
self.next(self.end)
@step
def end(self):
pass
if __name__ == '__main__':
SecretFlow()
在这种情况下,metaflow-example-password 是包含一个密钥 password 的秘密名称。sources 属性定义了秘密来源,可以包含多个名称,在这种情况下,所有秘密集的并集通过环境变量暴露。
配置一个秘密后端
要使用 @secrets,您需要告知 Metaflow 您希望使用哪个秘密管理器。如果您正在使用 AWS Secrets Manager,请确保您的 Metaflow 配置包含以下行:
"METAFLOW_DEFAULT_SECRETS_BACKEND_TYPE": "aws-secrets-manager"
如果您正在使用 Azure Key Vault,请确保您的 Metaflow 配置包含以下行:
"METAFLOW_DEFAULT_SECRETS_BACKEND_TYPE": "az-key-vault"
在命令行中定义秘密
您可以通过配置文件配置 @secrets。请查看 配置流程 以获取更多信息。
请注意,您可以像使用其他装饰器一样,使用 --with 选项在命令行上定义 @secrets。这在原型和生产之间迁移时特别方便:例如,您可以在开发和生产期间访问不同的数据库。
考虑这个连接到Postgres数据库的示例:
from metaflow import FlowSpec, step, secrets
import os
from psycopg import connect
class DBFlow(FlowSpec):
@step
def start(self):
with connect(user=os.environ['DB_USER'],
password=os.environ['DB_PASSWORD'],
dbname=os.environ['DB_NAME'],
host=os.environ['DB_HOST']) as conn:
with conn.cursor() as cur:
cur.execute("SELECT * FROM data")
print(cur.fetchall())
self.next(self.end)
@step
def end(self):
pass
if __name__ == '__main__':
DBFlow()
在开发过程中,您可以在本地运行流程,可能从环境变量读取本地数据库的凭据 - 在早期原型设计阶段无需使用秘密管理器。
要从测试数据库读取数据,您可以通过如下方式运行流从秘密管理器获取凭据:
python dbflow.py
–with 'secrets:sources=[“test-db-credentials”]'
run
您可以使用像这样的生产数据库部署到生产环境:
python dbflow.py
–with 'secrets:sources=["prod-db-credentials”]'
argo-workflows create
高级主题
在认真生产环境中运行流时,以下主题偶尔会出现。
控制对机密的访问
使用秘密管理器的一个主要好处是您可以严格控制谁可以访问哪些秘密。对于AWS Secrets Manager,访问控制是通过IAM策略实现的。有关更多详细信息,请参阅AWS Secrets Manager文档中的访问控制部分。
例如,您可以设置IAM策略,以便只有测试数据库可以直接访问,而生产数据库只能被在生产调度器上运行的任务访问。
使用替代角色
默认情况下,@secrets使用执行环境中可用的默认IAM角色访问机密。对于本地运行,这通常是附加到IAM用户的角色。
如果默认角色无法访问指定的秘密,您可以通过role属性定义一个替代角色:
@secrets(sources=['metaflow-example-password'],
role='arn:aws:iam::123456789012:role/SecretsAccess')
默认角色需要能够承担指定的 role 才能使其工作。
从非默认位置访问密钥
AWS Secrets Manager 是一个账户和区域特定的服务。默认情况下,当您在 sources 列表中指定一个密钥名称时,@secrets 假定该名称在当前 AWS 账户的当前默认区域内可用。
如果不是这种情况,您可以指定完整的秘密ARN(可在AWS秘密管理控制台中获得)作为来源:
@secrets(sources=['arn:aws:secretsmanager:us-west-2:001234556000:secret:some-secret'])
在Azure中访问机密
Azure Key Vault是一个特定于帐户的服务,通过Azure资源管理器进行管理。当前,仅支持Secret对象类型。您可以在sources列表或字典对象中指定机密,如下所示。
支持以下格式的秘密。
完全限定的密钥保管库ID:
@secrets(sources=['https://az-key-vault.vault.azure.net/secrets/secretkey/2260d88aca504269999c5f9413c3abcd'])
没有版本的密钥保管库 ID:
@secrets(sources=['https://az-key-vault.vault.azure.net/secrets/secretkey'])
密钥保管库对象名称带版本:
@secrets(sources=['secretkey/2260d88aca504269999c5f9413c3abcd'])
密钥保管库对象名称:
@secrets(sources=['secretkey'])
可以通过以下方式使用字典来指定sources属性的参数:
@secrets(sources=[{"type": "az-key-vault", "id":"https://az-key-vault.vault.azure.net/secrets/secretkey/2260d88aca504269999c5f9413c3ddcd"}])
如果在sources属性中没有指定Azure Key Vault URL,则必须在metaflow配置中设置为:
"METAFLOW_AZURE_KEY_VAULT_PREFIX": "https://az-key-vault.vault.azure.net/"
在GCP中访问密钥
Metaflow 支持与 GCP Secret Manager 的集成 - 以安全的方式存储和检索秘密。秘密通过环境变量检索并提供。
前置条件:
- 在您的 GCP 项目中启用 Secrets Manager API
- 为了访问GCP中的一个秘密,您应该至少拥有该秘密的秘密管理器秘密访问者角色。
您可以在sources列表或字典对象中指定秘密,如下所示。支持以下格式的秘密。
密钥的完全限定路径:
@secrets(sources=["projects/1234567890/mysecret"])
秘密名称:
@secrets(sources=['mysecret'])
使用字典来指定环境变量名称,选项如下:
@secrets(sources=[{"id": "mysecret", {"options": {"env_var_name": "MY_SECRET"}}])
如果在sources属性中没有指定完全限定的GCP Secret路径,则必须在metaflow配置中设置为:
"METAFLOW_GCP_SECRET_MANAGER_PREFIX": "projects/1234567890"