¿Cómo soluciono el error «No se han podido validar las siguientes configuraciones de destino» en AWS CloudFormation?

6 minutos de lectura
0

Suscribo un tema de Amazon Simple Notification Service (Amazon SNS) o una función de AWS Lambda a las notificaciones de eventos de Amazon Simple Storage Service (Amazon S3). Recibo el siguiente error: «No se han podido validar las siguientes configuraciones de destino». Cuando intento establecer una dependencia en la política de temas de SNS desde el bucket de S3 de mi plantilla, aparece un error de validación de dependencia circular.

Breve descripción

Debido a la forma en que AWS CloudFormation gestiona el orden de dependencias, las notificaciones de eventos de Amazon S3 se definen como un atributo del bucket de S3. Estas notificaciones se establecen cuando se crea el recurso de bucket de S3.

Para evitar un error, debe crear los recursos en el siguiente orden:

  1. Creación del tema de SNS, ya que el bucket de S3 hace referencia al tema de SNS.
  2. Creación del bucket de S3, ya que la política de temas de SNS hace referencia tanto al bucket de S3 como al tema de SNS.

Antes de suscribir un tema de SNS a las notificaciones de eventos de S3, debe especificar una política de temas (AWS::SNS::TopicPolicy) con los permisos adecuados. Esa política de temas debe existir antes de crear la suscripción.

Pruebe una de las siguientes estrategias para evitar el error «No se han podido validar las siguientes configuraciones de destino»:

  • Especificar un valor para BucketName en la plantilla de AWS CloudFormation
  • Crear una pila y, a continuación, realizar una actualización de la pila

Resolución

Especificar un valor para BucketName en la plantilla de AWS CloudFormation

Utilice un nombre estático para el bucket de S3 especificando un valor para la propiedad BucketName en el recurso S3Bucket de la plantilla de AWS CloudFormation. Así se elimina la necesidad de incluir {"Ref": "paramBucketName"} en la política de temas de SNS. De este modo, se elimina la dependencia intrínseca entre la política de temas de SNS y Amazon S3.

El siguiente ejemplo de plantilla de AWS CloudFormation especifica un valor codificado de forma rígida (-Bucket-Name-) para la propiedad BucketName. En la plantilla, sustituya todas las instancias de -Bucket-Name- por el nombre del bucket.

{
  "Resources": {
    "SNSTopic": {
      "Type": "AWS::SNS::Topic"
    },
    "SNSTopicPolicy": {
      "Type": "AWS::SNS::TopicPolicy",
      "Properties": {
        "PolicyDocument": {
          "Id": "MyTopicPolicy",
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "Statement-id",
              "Effect": "Allow",
              "Principal": {
                "Service": "s3.amazonaws.com"
              },
              "Action": "sns:Publish",
              "Resource": {
                "Ref": "SNSTopic"
              },
              "Condition": {
                "ArnLike": {
                  "aws:SourceArn": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:aws:s3:::",
                        "-Bucket-Name-"
                      ]
                    ]
                  }
                }
              }
            }
          ]
        },
        "Topics": [
          {
            "Ref": "SNSTopic"
          }
        ]
      }
    },
    "S3Bucket": {
      "Type": "AWS::S3::Bucket",
      "DependsOn": [
        "SNSTopicPolicy"
      ],
      "Properties": {
        "AccessControl": "BucketOwnerFullControl",
        "BucketName": "-Bucket-Name-",
        "NotificationConfiguration": {
          "TopicConfigurations": [
            {
              "Topic": {
                "Ref": "SNSTopic"
              },
              "Event": "s3:ObjectCreated:Put"
            }
          ]
        }
      }
    }
  }
}

Nota: El recurso S3Bucket tiene un valor DependsOn explícito que se establece en SNSTopicPolicy. Este atributo especifica que la plantilla crea el recurso SNSTopicPolicy antes que el recurso S3Bucket.

Para usar la misma plantilla de AWS CloudFormation para buckets de S3 con nombres diferentes, defina un parámetro para el nombre del bucket. El parámetro le permite utilizar la misma plantilla para diferentes nombres de bucket pasando el nombre del bucket como parámetro durante la creación de la pila.

Para usar la siguiente plantilla de ejemplo, debe pasar el nombre del bucket como parámetro paramBucketName durante la creación de la pila.

{
  "Parameters": {
    "paramBucketName": {
      "Type": "String",
      "Description": "Bucket Name"
    }
  },
  "Resources": {
    "SNSTopic": {
      "Type": "AWS::SNS::Topic"
    },
    "SNSTopicPolicy": {
      "Type": "AWS::SNS::TopicPolicy",
      "Properties": {
        "PolicyDocument": {
          "Id": "MyTopicPolicy",
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "Statement-id",
              "Effect": "Allow",
              "Principal": {
                "Service": "s3.amazonaws.com"
              },
              "Action": "sns:Publish",
              "Resource": {
                "Ref": "SNSTopic"
              },
              "Condition": {
                "ArnLike": {
                  "aws:SourceArn": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:aws:s3:::",
                        {
                          "Ref": "paramBucketName"
                        }
                      ]
                    ]
                  }
                }
              }
            }
          ]
        },
        "Topics": [
          {
            "Ref": "SNSTopic"
          }
        ]
      }
    },
    "S3Bucket": {
      "Type": "AWS::S3::Bucket",
      "DependsOn": [
        "SNSTopicPolicy"
      ],
      "Properties": {
        "AccessControl": "BucketOwnerFullControl",
        "BucketName": {
          "Ref": "paramBucketName"
        },
        "NotificationConfiguration": {
          "TopicConfigurations": [
            {
              "Topic": {
                "Ref": "SNSTopic"
              },
              "Event": "s3:ObjectCreated:Put"
            }
          ]
        }
      }
    }
  }
}

Crear una pila y, a continuación, realizar una actualización de la pila

Divida la creación de la pila en dos etapas. Primero, cree la pila, pero no especifique la propiedad NotificationConfiguration en el recurso S3Bucket. A continuación, realice una actualización de la pila para añadir la notificación de eventos de S3. De este modo, se evita configurar la notificación de eventos de S3 antes de crear la política de temas de SNS.

1.    Cree todos los recursos, incluida la política de temas de SNS. Por ejemplo:

{
  "Resources": {
    "SNSTopic": {
      "Type": "AWS::SNS::Topic"
    },
    "SNSTopicPolicy": {
      "Type": "AWS::SNS::TopicPolicy",
      "Properties": {
        "PolicyDocument": {
          "Id": "MyTopicPolicy",
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "Statement-id",
              "Effect": "Allow",
              "Principal": {
                "Service": "s3.amazonaws.com"
              },
              "Action": "sns:Publish",
              "Resource": {
                "Ref": "SNSTopic"
              },
              "Condition": {
                "ArnLike": {
                  "aws:SourceArn": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:aws:s3:::",
                        {
                          "Ref": "S3Bucket"
                        }
                      ]
                    ]
                  }
                }
              }
            }
          ]
        },
        "Topics": [
          {
            "Ref": "SNSTopic"
          }
        ]
      }
    },
    "S3Bucket": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "AccessControl": "BucketOwnerFullControl"
      }
    }
  }
}

2.    Actualice la pila para añadir la notificación de eventos de S3. Por ejemplo:

{
  "Resources": {
    "SNSTopic": {
      "Type": "AWS::SNS::Topic"
    },
    "SNSTopicPolicy": {
      "Type": "AWS::SNS::TopicPolicy",
      "Properties": {
        "PolicyDocument": {
          "Id": "MyTopicPolicy",
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "Statement-id",
              "Effect": "Allow",
              "Principal": {
                "Service": "s3.amazonaws.com"
              },
              "Action": "sns:Publish",
              "Resource": {
                "Ref": "SNSTopic"
              },
              "Condition": {
                "ArnLike": {
                  "aws:SourceArn": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:aws:s3:::",
                        {
                          "Ref": "S3Bucket"
                        }
                      ]
                    ]
                  }
                }
              }
            }
          ]
        },
        "Topics": [
          {
            "Ref": "SNSTopic"
          }
        ]
      }
    },
    "S3Bucket": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "AccessControl": "BucketOwnerFullControl",
        "NotificationConfiguration": {
          "TopicConfigurations": [
            {
              "Topic": {
                "Ref": "SNSTopic"
              },
              "Event": "s3:ObjectCreated:Put"
            }
          ]
        }
      }
    }
  }
}

Nota: Puede utilizar AWS CloudFormation Template Flip para convertir las plantillas de AWS CloudFormation entre los formatos JSON y YAML.


Información relacionada

¿Cómo puedo evitar el error «No se han podido validar las siguientes configuraciones de destino» con las notificaciones de eventos de Lambda en AWS CloudFormation?

Actualizaciones de pila de AWS CloudFormation

Configuración de notificaciones de Amazon SNS

OFICIAL DE AWS
OFICIAL DE AWSActualizada hace 2 años