

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 常見的 Canary 功能
<a name="CloudWatch_Synthetics_Canaries_CommonFeatures"></a>

您可以搭配所有 Canary 執行時間使用下列功能。

## 環境變數
<a name="CloudWatch_Synthetics_Environment_Variables"></a>

您可以在建立 Canary 時使用環境變數。您可以撰寫單一 Canary 指令碼，並搭配不同的值使用，以快速為類似的任務建立多個 Canary。

例如，假設您的組織具有不同軟體開發階段`pre-release`的端點`prod`，例如 `dev`、 和 。您必須建立 Canary 來測試每個端點。您可以撰寫單一 Canary 指令碼來測試您的軟體。然後在建立三個 Canary 的每個 Canary 時指定不同的端點環境變數值。當您建立 Canary 時，請指定指令碼和環境變數值。

環境變數名稱可包含字母、數字和底線字元。其必須以字母開頭，且至少有兩個字元。環境變數的總大小不能超過 4 KB。您無法指定任何 Lambda 保留環境變數作為環境變數的名稱。如需有關保留環境變數的詳細資訊，請參閱[執行時間環境變數](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime)。

**環境變數不是加密的用戶端**  
根據預設， 會使用 AWS 擁有的金鑰 AWS 加密環境變數金鑰和靜態值。不過，CloudWatch Synthetics 不會套用用戶端加密。只有在傳輸中加密敏感資訊之後，才能儲存敏感資訊。如需詳細資訊，請參閱[加密傳輸中的環境變數](#CloudWatch_Synthetics_transit_encryption)。您也可以使用客戶受管 AWS KMS 金鑰來加密 Canary 的環境變數。如需詳細資訊，請參閱[使用客戶受管金鑰加密靜態環境變數](#CloudWatch_Synthetics_function_encryption)。

以下範例指令碼使用了兩個環境變數。這個指令碼可用於檢查網頁是否可用的 Canary。它使用環境變數來參數化其檢查的 URL 和其使用的 CloudWatch Synthetics 日誌層級。

下列程式碼片段是完整指令碼的一部分，如下所示。

以下函數會將 `LogLevel` 設定為 `LOG_LEVEL` 環境變數的數值。

```
 synthetics.setLogLevel(process.env.LOG_LEVEL);
```

此函數會將 `URL` 設定為 `URL` 環境變數的數值。

```
const URL = process.env.URL;
```

下列完整指令碼示範兩種環境變數。當您使用此指令碼建立 Canary 時，您可以指定要用於 `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();
};
```

### 將環境變數傳遞給指令碼
<a name="CloudWatch_Synthetics_Canaries_pass_variables"></a>

若要在主控台中建立 Canary 時將環境變數傳遞至指令碼，請在主控台的 **Environment variables** (環境變數) 區段中指定環境變數的金鑰和數值。如需詳細資訊，請參閱[建立 Canary](CloudWatch_Synthetics_Canaries_Create.md)。

若要透過 API 或 傳遞環境變數 AWS CLI，請使用 `RunConfig`區段中的 `EnvironmentVariables` 參數。以下是建立 Canary 的範例 AWS CLI 命令，該 Canary 使用兩個具有 `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"
}'
```

## 使用客戶受管金鑰加密靜態環境變數
<a name="CloudWatch_Synthetics_function_encryption"></a>

根據預設， AWS 擁有的金鑰會加密靜態 Canary 環境變數。您可以指定客戶受管 AWS KMS 金鑰來加密靜態 Canary 環境變數。使用客戶受管金鑰，您可以完全控制敏感組態資料的加密。下列各節說明使用客戶受管金鑰的需求、組態步驟和許可。

### 要求
<a name="CloudWatch_Synthetics_function_encryption_requirements"></a>

設定客戶受管金鑰之前，請確認您符合下列要求：
+  AWS KMS 金鑰必須是對稱加密金鑰。
+ 金鑰政策必須授予`kms:CreateGrant`發起人 （呼叫 Synthetics API 的 IAM 主體）。
+ AWS Lambda 使用 授予來加密和解密靜態環境變數。
+  AWS KMS 金鑰必須與 Canary 位於相同的 AWS 區域。

### 設定客戶受管金鑰
<a name="CloudWatch_Synthetics_function_encryption_configure"></a>

您可以在建立或更新 Canary 時設定客戶受管金鑰。下列程序說明如何使用 Amazon CloudWatch 主控台和 Synthetics API 設定加密。

#### 在 主控台中設定加密
<a name="CloudWatch_Synthetics_function_encryption_configure_console"></a>

若要在 Amazon CloudWatch 主控台中建立或編輯 Canary，請展開**環境變數**區段。在**靜態加密組態**下，選擇**使用客戶受管金鑰**，然後選擇或指定 AWS KMS 金鑰的 ARN。

#### 使用 API 設定加密
<a name="CloudWatch_Synthetics_function_encryption_configure_api"></a>

呼叫 `CreateCanary`或 時`UpdateCanary`，使用客戶受管金鑰的 ARN 指定 `KmsKeyArn` 參數。若要還原至 AWS 受管金鑰，請將 `KmsKeyArn`設定為空字串。

#### 範例：CreateCanary 請求搭配客戶受管金鑰
<a name="CloudWatch_Synthetics_function_encryption_configure_example"></a>

```
{
"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"
  }
}
}
```

### 靜態加密的必要許可
<a name="CloudWatch_Synthetics_function_encryption_permissions"></a>

如果您建立或更新 Canary，您必須在 AWS KMS 金鑰上擁有下列許可：
+ `kms:CreateGrant`、 `kms:Encrypt`— 設定 Canary 的客戶受管金鑰時需要。
+ `kms:Decrypt`- 需要檢視和管理使用客戶受管金鑰加密的環境變數。
+ `kms:DescribeKey`- 驗證金鑰時需要。

Canary 執行角色不需要靜態加密的 AWS KMS 許可。Lambda 使用授予來處理加密和解密。

### 多位置 Canary
<a name="CloudWatch_Synthetics_function_encryption_multilocation"></a>

對於多位置 Canary，每個複本位置都可以有自己的 AWS KMS 金鑰。建立或更新 Canary 時，請在 `AddReplicaLocations` 參數`KmsKeyArn`中指定 。金鑰必須與複本位於相同的區域。

## 加密傳輸中的環境變數
<a name="CloudWatch_Synthetics_transit_encryption"></a>

除了靜態加密之外，您還可以在 CloudWatch Synthetics 儲存個別環境變數值之前對其進行加密。CloudWatch Synthetics 會在傳輸中呼叫此加密。當您加密傳輸中的值時，主控台會將純文字值取代為 base64 編碼的加密文字，只有 Canary 可以在執行時間解密。

### 傳輸中加密的運作方式
<a name="CloudWatch_Synthetics_transit_encryption_how"></a>

當您選擇加密傳輸中的環境變數值時：

1. 主控台`kms:Encrypt`會使用您選取的 AWS KMS 金鑰呼叫 ，以加密純文字值。

1. 加密的加密文字 (base64 編碼） 會取代環境變數組態中的純文字值。

1. 在執行時間，您的 Canary 指令碼會呼叫 來解密值`kms:Decrypt`。

### 傳輸中加密的必要許可
<a name="CloudWatch_Synthetics_transit_encryption_permissions"></a>

您需要下列許可才能在傳輸中加密：
+ **主控台使用者或 API 呼叫者** - 在 AWS KMS 金鑰`kms:Encrypt`上。您需要此許可來加密值，才能儲存該值。
+ **Canary 執行角色** - AWS KMS 金鑰`kms:Decrypt`上的 。Canary 的 Lambda 函數需要此許可，才能在執行時間解密值。

以下是要連接到 Canary 執行角色的範例 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"
  }
]
}
```

### 解密 Canary 指令碼中的值
<a name="CloudWatch_Synthetics_transit_encryption_decrypt"></a>

若要在 Canary 指令碼中使用加密的環境變數，請在執行時間將其解密。下列 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');
```

## 將您的 Canary 與其他 AWS 服務整合
<a name="CloudWatch_Synthetics_Canaries_AWS_integrate"></a>

您可以使用 Canary 中的 AWS SDK 程式庫來與其他 AWS 服務整合。

若要這樣做，請將下列程式碼新增至 Canary。在這些範例中，Canary 會與 整合 AWS Secrets Manager。
+ 匯入 AWS SDK。

  ```
  const AWS = require('aws-sdk');
  ```
+ 為您整合 AWS 的服務建立用戶端。

  ```
  const secretsManager = new AWS.SecretsManager();
  ```
+ 使用用戶端對該服務進行 API 呼叫。

  ```
  var params = {
  SecretId: secretName
  };
  return await secretsManager.getSecretValue(params).promise();
  ```

下列 Canary 指令碼程式碼片段會詳細說明如何與 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();
};
```

## 強制您的 Canary 使用靜態 IP 地址
<a name="CloudWatch_Synthetics_Canaries_staticIP"></a>

您可以設定 Canary，以便使用靜態 IP 地址。

**若要強制 Canary 使用靜態 IP 地址**

1. 建立新 VPC 如需詳細資訊，請參閱[以 VPC 使用 DNS](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html)。

1. 建立新的網際網路閘道。如需詳細資訊，請參閱[將網際網路閘道新增至您的 VPC](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html#working-with-igw)。

1. 在您的新 VPC 內部建立一個公有子網路。

1. 將新的路由表新增到 VPC。

1. 在從 `0.0.0.0/0`到網際網路閘道的新路由表中新增路由。

1. 將新的路由表與公有子網路建立關聯。

1. 建立彈性 IP 地址。如需詳細資訊，請參閱[彈性 IP 地址](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html)。

1. 建立新的 NAT 閘道，並將其指派給公有子網路和彈性 IP 地址。

1. 在 VPC 內部建立私有子網路。

1. 將路由新增至從 `0.0.0.0/0`到 NAT 閘道的 VPC 預設路由表。

1. 建立 Canary。