常见的金丝雀功能
您可以对所有金丝雀运行时使用下面的功能。
环境变量
您可以在创建金丝雀时使用环境变量。您可以编写单个金丝雀脚本,并将其与不同的值搭配使用来快速创建用于类似任务的多个金丝雀。
例如,假设贵组织具有用于不同软件开发阶段的端点(例如 prod、dev 和 pre-release)。您必须创建金丝雀来测试每个端点。您可以编写一个金丝雀脚本来测试软件。然后,在创建三个金丝雀时,请分别指定不同的端点环境变量值。创建金丝雀时,请指定脚本和环境变量值。
环境变量的名称可以包含字母、数字和下划线字符,必须以字母开头,并且至少为两个字符。环境变量的总大小不能超过 4 KB。不能将任何 Lambda 预留环境变量指定为环境变量的名称。有关预留环境变量的更多信息,请参阅运行时环境变量。
环境变量在客户端未加密
默认情况下,Amazon 使用 Amazon 自有密钥对环境变量键和值进行静态加密。但是,CloudWatch Synthetics 并不应用客户端加密。敏感信息在传输中加密后才能存储。有关更多信息,请参阅 对环境变量进行传输中加密。您还可以使用客户自主管理型 Amazon KMS 密钥来对金丝雀的环境变量进行静态加密。有关更多信息,请参阅 使用客户自主管理型密钥对环境变量进行静态加密。。
下面的示例脚本使用两个环境变量。此脚本用于检查网页是否可用的金丝雀。该金丝雀使用环境变量来参数化所检查的 URL 和所使用的 CloudWatch Synthetics 日志级别。
以下代码段是下面显示的完整脚本的一部分。
以下函数将 LogLevel 设置为 LOG_LEVEL 环境变量的值。
synthetics.setLogLevel(process.env.LOG_LEVEL);
此函数将 URL 设置为 URL 环境变量的值。
const URL = process.env.URL;
下面的完整脚本演示了这两个环境变量。当您使用此脚本创建金丝雀时,您可以指定 LOG_LEVEL 和 URL 环境变量的值。
var synthetics = require('@aws/synthetics-puppeteer'); const log = require('@aws/synthetics-logger'); const pageLoadEnvironmentVariable = async function () { // Setting the log level (0-3) synthetics.setLogLevel(process.env.LOG_LEVEL); // INSERT URL here const URL = process.env.URL; let page = await synthetics.getPage(); //You can customize the wait condition here. For instance, //using 'networkidle2' may be less restrictive. const response = await page.goto(URL, {waitUntil: 'domcontentloaded', timeout: 30000}); if (!response) { throw "Failed to load page!"; } //Wait for page to render. //Increase or decrease wait time based on endpoint being monitored. await page.waitFor(15000); await synthetics.takeScreenshot('loaded', 'loaded'); let pageTitle = await page.title(); log.info('Page title: ' + pageTitle); log.debug('Environment variable:' + process.env.URL); //If the response status code is not a 2xx success code if (response.status() < 200 || response.status() > 299) { throw "Failed to load page!"; } }; exports.handler = async () => { return await pageLoadEnvironmentVariable(); };
将环境变量传递到脚本
要在控制台中创建金丝雀时将环境变量传递给脚本,请在控制台上的 Environment variables(环境变量)部分指定环境变量的密钥和值。有关更多信息,请参阅 创建金丝雀。
要通过 API 或 Amazon CLI 传递环境变量,请使用 RunConfig 部分中的 EnvironmentVariables 参数。以下为 Amazon CLI 命令示例,该命令创建一个使用两个环境变量(具有 Environment 和 Region 密钥)的金丝雀。
aws synthetics create-canary --cli-input-json '{ "Name":"nameofCanary", "ExecutionRoleArn":"roleArn", "ArtifactS3Location":"s3://amzn-s3-demo-bucket-123456789012-us-west-2", "Schedule":{ "Expression":"rate(0 minute)", "DurationInSeconds":604800 }, "Code":{ "S3Bucket": "canarycreation", "S3Key": "cwsyn-mycanaryheartbeat-12345678-d1bd-1234-abcd-123456789012-12345678-6a1f-47c3-b291-123456789012.zip", "Handler":"pageLoadBlueprint.handler" }, "RunConfig": { "TimeoutInSeconds":60, "EnvironmentVariables": { "Environment":"Production", "Region": "us-west-1" } }, "SuccessRetentionPeriodInDays":13, "FailureRetentionPeriodInDays":13, "RuntimeVersion":"syn-nodejs-2.0" }'
使用客户自主管理型密钥对环境变量进行静态加密。
默认情况下,Amazon 自有密钥会对金丝雀环境变量进行静态加密。您可以指定客户自主管理型 Amazon KMS 密钥来对金丝雀环境变量进行静态加密。使用客户自主管理型密钥,您可以完全控制敏感配置数据的加密。以下部分介绍使用客户自主管理型的要求、配置步骤和权限。
要求
配置客户自主管理型密钥之前,请确认您满足以下要求:
-
Amazon KMS 密钥必须是对称加密密钥。
-
密钥策略必须向调用方(调用 Synthetics API 的 IAM 主体)授予
kms:CreateGrant。 -
Amazon Lambda 使用该授权对环境变量进行静态加密和解密。
-
Amazon KMS 密钥必须与金丝雀版本位于同一 Amazon 区域。
配置客户自主管理型密钥
您可以在创建或更新金丝雀时配置客户自主管理型密钥。以下过程展示了如何使用 Amazon CloudWatch 控制台和 Synthetics API 来配置加密。
在控制台中配置加密
要在 Amazon CloudWatch 控制台中创建或编辑金丝雀,请展开环境变量部分。在静态加密配置下,选择使用客户自主管理型密钥,然后选择或指定 Amazon KMS 密钥的 ARN。
使用 API 配置加密
调用 CreateCanary 或 UpdateCanary 时,请使用客户自主管理型密钥的 ARN 指定 KmsKeyArn 参数。要恢复为 Amazon 托管式密钥,请将 KmsKeyArn 设置为空字符串。
示例:使用客户自主管理型密钥创建金丝雀请求
{ "Name": "my-canary-EXAMPLE", "KmsKeyArn": "arn:aws:kms:us-east-1:111122223333:key/a1b2c3d4-e5f6-7890-abcd-EXAMPLE11111", "RunConfig": { "EnvironmentVariables": { "SECRET_KEY": "my-secret-value-EXAMPLE" } } }
静态加密所需的权限
如果创建或更新金丝雀,则必须对 Amazon KMS 密钥具有以下权限:
-
kms:CreateGrant、kms:Encrypt:为金丝雀配置客户自主管理型密钥所必需的。 -
kms:Decrypt:查看和管理使用客户自主管理型密钥加密的环境变量所必需的。 -
kms:DescribeKey:验证密钥所必需的。
金丝雀执行角色不需要任何 Amazon KMS 权限即可进行静态加密。Lambda 使用该授权来处理加密和解密。
多位置金丝雀
对于多位置金丝雀,每个副本位置都可以拥有自己的 Amazon KMS 密钥。创建或更新金丝雀时,请在 AddReplicaLocations 参数中指定 KmsKeyArn。密钥必须与副本位于同一区域。
对环境变量进行传输中加密
除了静态加密之外,您还可以在 CloudWatch Synthetics 存储各个环境变量值之前对其进行加密。CloudWatch Synthetics 称之为传输中加密。当对值进行传输中加密时,控制台会将明文值替换为 base64 编码的加密文字,仅您的金丝雀可以在运行时解密该加密文字。
传输中加密的工作原理
当您选择对环境变量值进行传输中加密时:
-
控制台使用您选择的 Amazon KMS 密钥调用
kms:Encrypt以加密明文值。 -
加密的加密文字(base64 编码)取代了环境变量配置中的明文值。
-
在运行时,金丝雀脚本会通过调用
kms:Decrypt来解密该值。
传输中加密所需的权限
您需要拥有以下权限才能进行传输中加密:
-
控制台用户或 API 调用方:对 Amazon KMS 密钥拥有
kms:Encrypt权限。您需要此权限才能在存储值之前对其进行加密。 -
金丝雀执行角色:对 Amazon KMS 密钥拥有
kms:Decrypt权限。金丝雀的 Lambda 函数需要此权限才能在运行时对该值进行解密。
下面是附加到金丝雀执行角色的 IAM 策略示例。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "kms:Decrypt", "Resource": "arn:aws:kms:us-east-1:111122223333:key/a1b2c3d4-e5f6-7890-abcd-EXAMPLE11111" } ] }
解密金丝雀脚本中的值
要在金丝雀脚本中使用经过加密的环境变量,请在运行时对其进行解密。以下 Node.js 示例展示了如何解密环境变量:
const { KMSClient, DecryptCommand } = require('@aws-sdk/client-kms'); const client = new KMSClient({ region: process.env.AWS_REGION }); async function decryptEnvVar(name) { const encrypted = process.env[name]; const req = { CiphertextBlob: Buffer.from(encrypted, 'base64'), }; const command = new DecryptCommand(req); const response = await client.send(command); return new TextDecoder().decode(response.Plaintext); } // Usage const mySecret = await decryptEnvVar('MY_CONFIG_VAR');
将您的金丝雀与其他 Amazon 服务集成
您可以在金丝雀中使用 Amazon SDK 库来与其他 Amazon 服务集成。
为此,请将以下代码添加到金丝雀中。在这些示例中,金丝雀与 Amazon Secrets Manager 集成。
-
导入 Amazon SDK。
const AWS = require('aws-sdk'); -
为要集成的 Amazon 服务创建客户端。
const secretsManager = new AWS.SecretsManager(); -
使用客户端对该服务进行 API 调用。
var params = { SecretId: secretName }; return await secretsManager.getSecretValue(params).promise();
下面的金丝雀脚本代码段更详细地展示了如何与 Secrets Manager 集成。
var synthetics = require('@aws/synthetics-puppeteer'); const log = require('@aws/synthetics-logger'); const AWS = require('aws-sdk'); const secretsManager = new AWS.SecretsManager(); const getSecrets = async (secretName) => { var params = { SecretId: secretName }; return await secretsManager.getSecretValue(params).promise(); } const secretsExample = async function () { let URL = "<URL>"; let page = await synthetics.getPage(); log.info(`Navigating to URL: ${URL}`); const response = await page.goto(URL, {waitUntil: 'domcontentloaded', timeout: 30000}); // Fetch secrets let secrets = await getSecrets("secretname") /** * Use secrets to login. * * Assuming secrets are stored in a JSON format like: * { * "username": "<USERNAME>", * "password": "<PASSWORD>" * } **/ let secretsObj = JSON.parse(secrets.SecretString); await synthetics.executeStep('login', async function () { await page.type(">USERNAME-INPUT-SELECTOR<", secretsObj.username); await page.type(">PASSWORD-INPUT-SELECTOR<", secretsObj.password); await Promise.all([ page.waitForNavigation({ timeout: 30000 }), await page.click(">SUBMIT-BUTTON-SELECTOR<") ]); }); // Verify login was successful await synthetics.executeStep('verify', async function () { await page.waitForXPath(">SELECTOR<", { timeout: 30000 }); }); }; exports.handler = async () => { return await secretsExample(); };
强制金丝雀使用静态 IP 地址
您可以设置金丝雀,使其使用静态 IP 地址。
强制金丝雀使用静态 IP 地址
-
创建新的 VPC。有关更多信息,请参阅将 DNS 与您的 VPC 一起使用。
-
创建新的互联网网关。有关更多信息,请参阅在您的 VPC 中添加互联网网关。
-
在新的 VPC 内创建公有子网。
-
向 VPC 添加新的路由表。
-
在新路由表中添加一条从
0.0.0.0/0到互联网网关的路由。 -
将新的路由表与公有子网关联。
-
创建弹性 IP 地址。有关更多信息,请参阅弹性 IP 地址。
-
创建一个新的 NAT 网关,并将其分配给公有子网和弹性 IP 地址。
-
在 VPC 中创建私有子网。
-
向 VPC 默认路由表添加一条从
0.0.0.0/0到 NAT 网关的路由。 -
创建金丝雀。