

# Características comunes de los canarios
<a name="CloudWatch_Synthetics_Canaries_CommonFeatures"></a>

Puede utilizar las siguientes características con todos los tiempos de ejecución de los canarios.

## Variables de entorno
<a name="CloudWatch_Synthetics_Environment_Variables"></a>

Puede utilizar variables de entorno al crear canarios. Puede escribir un único script de canario y utilizarlo con distintos valores para crear rápidamente varios canarios que realicen una tarea similar.

Por ejemplo, suponga que la organización tiene puntos de conexión como `prod`, `dev` y `pre-release` para distintas etapas del desarrollo de software. Debe crear canarios para probar cada punto de conexión. Puede escribir un único script de canario que pruebe el software. A continuación, especifique distintos valores para la variable de entorno del punto de conexión al crear cada uno de los tres canarios. Cuando cree un canario, especifique el script y los valores de las variables de entorno.

Los nombres de las variables de entorno pueden contener letras, números y guiones bajos. Deben comenzar con una letra y tener al menos dos caracteres. El tamaño total de las variables de entorno no puede superar los 4 KB. No es posible especificar variables de entorno reservadas de Lambda como claves para sus variables de entorno. Para obtener más información acerca de las variables de entorno reservadas, consulte [Runtime environment variables](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime) (Variables de entorno en tiempo de ejecución).

**Las variables de entorno no se cifran del lado del cliente**  
De forma predeterminada, AWS cifra en reposo las claves y los valores de las variables de entorno mediante una clave propiedad de AWS. Sin embargo, CloudWatch Synthetics no aplica cifrado del cliente. Almacene información confidencial únicamente después de cifrarla en tránsito. Para obtener más información, consulte [Cifrado de las variables de entorno en tránsito](#CloudWatch_Synthetics_transit_encryption). También puede utilizar una clave de AWS KMS administrada por el cliente para cifrar en reposo las variables de entorno del canario. Para obtener más información, consulte [Cifrado en reposo de las variables de entorno mediante una clave administrada por el cliente](#CloudWatch_Synthetics_function_encryption).

En el siguiente ejemplo el script utiliza dos variables de entorno. Este script es para un valor controlado que verifica si hay una página web disponible. Utiliza variables de entorno para parametrizar tanto la URL que verifica como el nivel de registro de CloudWatch Synthetics que utiliza.

Los siguientes fragmentos forman parte del script completo que se muestra más adelante.

La siguiente función establece `LogLevel` al valor de la variable de entorno `LOG_LEVEL`.

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

La función establece `URL` al valor de la variable de entorno `URL`.

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

El siguiente script completo muestra el uso de ambas variables de entorno. Cuando se crea un valor controlado con este script, se especifican los valores para las variables de entorno `LOG_LEVEL` y `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();
};
```

### Traspaso de las variables de entorno al script
<a name="CloudWatch_Synthetics_Canaries_pass_variables"></a>

Para pasar variables de entorno al script cuando cree un valor controlado en la consola, especifique las claves y los valores de las variables de entorno en la sección **Variables de entorno** en la consola. Para obtener más información, consulte [Creación de un valor controlado](CloudWatch_Synthetics_Canaries_Create.md).

Para pasar variables de entorno a través de la API o AWS CLI, utilice el parámetro `EnvironmentVariables` en la sección `RunConfig`. A continuación, se observa un ejemplo del comando de AWS CLI que crea un valor controlado que utiliza dos variables de entorno con claves de `Environment` y `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"
}'
```

## Cifrado en reposo de las variables de entorno mediante una clave administrada por el cliente
<a name="CloudWatch_Synthetics_function_encryption"></a>

De forma predeterminada, una clave propiedad de AWS cifra en reposo las variables de entorno del canario. Puede especificar una clave de AWS KMS administrada por el cliente para cifrar en reposo las variables de entorno del canario. Con una clave administrada por el cliente, tiene control total sobre el cifrado de los datos de configuración confidenciales. Las siguientes secciones describen los requisitos, los pasos de configuración y los permisos necesarios para utilizar una clave administrada por el cliente.

### Requisitos
<a name="CloudWatch_Synthetics_function_encryption_requirements"></a>

Antes de configurar una clave administrada por el cliente, compruebe que cumple los siguientes requisitos:
+ La clave de AWS KMS debe ser una clave de cifrado simétrico.
+ La política de claves debe conceder `kms:CreateGrant` a la persona que realiza la llamada, es decir, la entidad principal de IAM que llama a la API de Synthetics.
+ AWS Lambda utiliza la concesión para cifrar y descifrar en reposo las variables de entorno.
+ La clave de AWS KMS debe estar en la misma región de AWS que el canario.

### Configuración de una clave administrada por el cliente
<a name="CloudWatch_Synthetics_function_encryption_configure"></a>

Puede configurar una clave administrada por el cliente al crear o actualizar un canario. Los siguientes procedimientos muestran cómo configurar el cifrado mediante la consola de Amazon CloudWatch y la API de Synthetics.

#### Configuración del cifrado en la consola
<a name="CloudWatch_Synthetics_function_encryption_configure_console"></a>

Para crear o editar un canario en la consola de Amazon CloudWatch, expanda la sección **Variables de entorno**. En **Configuración del cifrado en reposo**, seleccione **Usar una clave administrada por el cliente** y, a continuación, seleccione o especifique el ARN de la clave de AWS KMS.

#### Configuración del cifrado mediante la API
<a name="CloudWatch_Synthetics_function_encryption_configure_api"></a>

Al llamar a `CreateCanary` o `UpdateCanary`, especifique el parámetro `KmsKeyArn` con el ARN de la clave administrada por el cliente. Para volver a utilizar la clave administrada por AWS, establezca `KmsKeyArn` en una cadena vacía.

#### Ejemplo: solicitud CreateCanary con una clave administrada por el cliente
<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"
  }
}
}
```

### Permisos obligatorios para el cifrado en reposo
<a name="CloudWatch_Synthetics_function_encryption_permissions"></a>

Para crear o actualizar el canario, debe disponer de los siguientes permisos para la clave de AWS KMS:
+ `kms:CreateGrant`, `kms:Encrypt`: necesarios para configurar una clave administrada por el cliente para el canario.
+ `kms:Decrypt`: necesario para ver y administrar las variables de entorno cifradas mediante una clave administrada por el cliente.
+ `kms:DescribeKey`: necesario para validar la clave.

El rol de ejecución del canario no requiere permisos de AWS KMS para el cifrado en reposo. Lambda utiliza la concesión para gestionar el cifrado y el descifrado.

### Canarios en varias ubicaciones
<a name="CloudWatch_Synthetics_function_encryption_multilocation"></a>

En el caso de los canarios en varias ubicaciones, cada ubicación de réplica puede tener su propia clave de AWS KMS. Especifique el `KmsKeyArn` en el parámetro `AddReplicaLocations` al crear o actualizar un canario. La clave debe estar en la misma región que la réplica.

## Cifrado de las variables de entorno en tránsito
<a name="CloudWatch_Synthetics_transit_encryption"></a>

Además del cifrado en reposo, puede cifrar los valores individuales de las variables de entorno antes de que CloudWatch Synthetics los almacene. CloudWatch Synthetics denomina a este proceso cifrado en tránsito. Cuando cifra un valor en tránsito, la consola sustituye el valor de texto plano por un texto cifrado codificado en base64 que solo el canario puede descifrar durante el tiempo de ejecución.

### Funcionamiento del cifrado en tránsito
<a name="CloudWatch_Synthetics_transit_encryption_how"></a>

Cuando elige cifrar en tránsito el valor de una variable de entorno:

1. La consola llama a `kms:Encrypt` con la clave de AWS KMS seleccionada para cifrar el valor de texto plano.

1. El texto cifrado, codificado en base64, sustituye el valor de texto plano en la configuración de la variable de entorno.

1. Durante el tiempo de ejecución, el script del canario descifra el valor mediante una llamada a `kms:Decrypt`.

### Permisos obligatorios para el cifrado en tránsito
<a name="CloudWatch_Synthetics_transit_encryption_permissions"></a>

Se necesitan los siguientes permisos para el cifrado en tránsito:
+ **Usuario de la consola o persona que realiza la llamada a la API**: `kms:Encrypt` en la clave de AWS KMS. Este permiso es necesario para cifrar el valor antes de almacenarlo.
+ **Rol de ejecución del canario**: `kms:Decrypt` en la clave de AWS KMS. La función de Lambda del canario necesita este permiso para descifrar el valor durante el tiempo de ejecución.

A continuación, se muestra un ejemplo de una política de IAM que puede asociar al rol de ejecución del canario:

```
{
"Version": "2012-10-17",
"Statement": [
  {
    "Effect": "Allow",
    "Action": "kms:Decrypt",
    "Resource": "arn:aws:kms:us-east-1:111122223333:key/a1b2c3d4-e5f6-7890-abcd-EXAMPLE11111"
  }
]
}
```

### Descifrado de valores en el script del canario
<a name="CloudWatch_Synthetics_transit_encryption_decrypt"></a>

Para utilizar una variable de entorno cifrada en el script del canario, descífrela durante el tiempo de ejecución. En el siguiente ejemplo de Node.js se muestra cómo descifrar una variable de entorno:

```
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');
```

## Integración del valor controlado con otros servicios de AWS
<a name="CloudWatch_Synthetics_Canaries_AWS_integrate"></a>

Puede utilizar la biblioteca del SDK de AWS en el canario para integrarlo con otros servicios de AWS.

Para ello, agregue el siguiente código al canario. En estos ejemplos, el canario se integra con AWS Secrets Manager.
+ Importar el SDK de AWS.

  ```
  const AWS = require('aws-sdk');
  ```
+ Cree un cliente para el servicio de AWS con el que se está integrando.

  ```
  const secretsManager = new AWS.SecretsManager();
  ```
+ Use el cliente para realizar llamadas a la API a ese servicio.

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

En el siguiente fragmento de código del script del canario se muestra con más detalle cómo realizar la integración con 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();
};
```

## Forzar al valor controlado para que utilice una dirección IP estática
<a name="CloudWatch_Synthetics_Canaries_staticIP"></a>

Se puede configurar un valor controlado para que utilice una dirección IP estática.

**Para forzar a un valor controlado a utilizar una dirección IP estática**

1. Cree una nueva VPC Para obtener más información, consulte [Utilización de DNS con su VPC](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html).

1. Cree una gateway de Internet. Para obtener más información, consulte [Adding an internet gateway to your VPC](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Internet_Gateway.html#working-with-igw) (Cómo añadir una gateway de Internet a la VPC).

1. Cree una subred pública en la nueva VPC.

1. Agregue una nueva tabla de enrutamiento a la VPC.

1. Agregue una ruta a la nueva tabla de enrutamiento que vaya de `0.0.0.0/0` a la puerta de enlace de Internet.

1. Asocie la nueva tabla de enrutamiento con la subred pública.

1. Cree una dirección IP elástica Para obtener más información, consulte [Direcciones IP elásticas](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html).

1. Cree una nueva gateway NAT y asígnela a la subred pública y a la dirección IP elástica.

1. Cree las subredes privadas en la VPC

1. Agregue una ruta a la tabla de enrutamiento predeterminada de la VPC que vaya de `0.0.0.0/0` a la puerta de enlace NAT.

1. Cree el valor controlado. 