Cómo integrar API Gateway con s3 en CDK
Los documentos son muy claros al hacer esto en la consola, https://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-s3.html, pero replicar en CDK es realmente doloroso.
Mi pregunta es cómo crear una API Rest respaldada con s3 (sin lambda en el medio) en CDK, o al menos cómo funciona apigateway.AwsIntegration.
Probé muchas cosas y me di cuenta de que estaba codificando a ciegas. Ya hice múltiples integraciones entre restApi, lambda, sqs, dynamoDB, s3 y todas fueron muy fáciles. Pero integrar API Gateway con S3 directamente está a punto de hacerme llorar.
Necesito que un restAPI almacene la carga útil de la solicitud directamente en un bucket de S3.
Esto es lo que ya probé:
Agregue una declaración de política a RestApi:
const apiResourcePolicy = new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ['s3:Put*'],
resources: [bucket.bucketName],
principals: [new ServicePrincipal('apigateway.amazonaws.com')]
})
]
});
const api = new apigateway.RestApi(this, "dispatch-api", {
restApiName: "my api name",
description: "api description",
policy: apiResourcePolicy
});
Pensé que esto debería ser suficiente para resolver los problemas de permisos, pero cuando agregué la integración de AWS a la API, así:
const getS3Integration = new apigateway.AwsIntegration({
service: "s3",
path: bucket.bucketName,
});
api.root.addMethod("PUT", getS3Integration, {
requestValidator: requestValidator,
requestModels: {"application/json": myModel},
});
Me estoy poniendo:
1:41:11 PM | CREATE_FAILED | AWS::ApiGateway::Method | XXXXXXXXXXXXXXXX
Role ARN must be specified for AWS integrations (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestException; Request ID: xxxxxxxxxxxxxxxxxxxxx; Proxy:
null)
No sé cómo especificar ese ARN de rol, no lo encontré en los documentos. Tampoco sé si era necesario agregar una política a restAPI. Estaba intentando replicar el ejemplo aquí en CDK.
Respuestas
Lo que sigue no es el conjunto completo, pero esto debería darle algunas ideas. Hice cosas similares en SQS, también lloré en ese entonces
const bucket = new s3.Bucket(this, 'storage');
const executeRole = new iam.Role(this, "role", {
assumedBy: new iam.ServicePrincipal('apigateway.amazonaws.com'),
path: "/service-role/"
});
bucket.grantReadWrite(executeRole);
const api = new apigateway.RestApi(this, 's3api');
const s3Integration = new apigateway.AwsIntegration({
service: 's3',
integrationHttpMethod: "PUT",
path: "{bucket}",
options : {
credentialsRole: executeRole,
// should have all kind of path mapping..
}
})
api.root.addResource("{folder}").addMethod("PUT", s3Integration, {
methodResponses: [
{
statusCode: "200"
}
]});
}
En el documento que vinculó (https://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-s3.html), sección "Configurar permisos de IAM para que la API invoque acciones de Amazon S3", la política que debe utilizar es totalmente diferente a la que codificó.
Su política, si se aplica a un depósito, diría: si la solicitud es del servicio "api gateway", permitir put:*acciones. Este enfoque es para otros casos de uso.
Según la documentación, necesita:
- crear un rol
- el rol debe contener políticas:
- acciones permitidas (
put:*en su caso) - permitir que la puerta de enlace de la API cambie al rol.
- acciones permitidas (
- usar el papel en
apigateway.RestApi
La política (1) debe ser obvia, la (2) como se indica en la documentación es:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Según su descripción, me parece que no está proporcionando el rol de IAM para su integración. Solo proporciona una política para la RestApique es una política basada en recursos para su API. En otras palabras, no se aplica a sus integraciones, sino que especifica quién puede ejecutar su API. Por lo general, no lo usa si desea que su API sea pública.
Para la integración de AWS, debe proporcionar el rol de IAM con permisos de S3 mediante IntegrationOptions . En concreto, a través de la credentialsopción:
Una función de IAM que asume API Gateway .
Los documentos de CloudFormation, a los que se asigna CDK, tienen más detalles sobre la integración Credentials:
Las credenciales que se requieren para la integración. Para especificar un rol de AWS Identity and Access Management (IAM) que asume API Gateway, especifique el nombre de recurso de Amazon (ARN) del rol. Para requerir que la identidad de la persona que llama se transfiera desde la solicitud, especifique arn: aws: iam ::: user / .
Para usar permisos basados en recursos en la función AWS Lambda (Lambda), no especifique esta propiedad. Utilice el recurso AWS :: Lambda :: Permission para permitir que API Gateway llame a la función. Para obtener más información, consulte Permitir que Amazon API Gateway invoque una función Lambda en la AWS Lambda Developer Guide.