Come integrare API Gateway con s3 in CDK
I documenti sono molto chiari nel farlo nella console, https://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-s3.html, ma replicare in CDK è davvero doloroso.
La mia domanda è come creare un'API Rest supportata con s3 (senza lambda nel mezzo) in CDK, o almeno come funziona apigateway.AwsIntegration.
Ho provato molte cose e ho capito che stavo codificando alla cieca. Ho già fatto più integrazioni tra restApi, lambda, sqs, dynamoDB, s3 e tutti erano così facili. Ma l'integrazione diretta di API Gateway con S3 sta per farmi piangere.
Ho bisogno che un restAPI memorizzi il payload della richiesta direttamente in un bucket S3.
Questo è quello che ho già provato:
Aggiungi una politica 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
});
Ho pensato che questo dovrebbe essere sufficiente per risolvere i problemi di autorizzazione, ma quando ho aggiunto l'integrazione AWS all'API, in questo modo:
const getS3Integration = new apigateway.AwsIntegration({
service: "s3",
path: bucket.bucketName,
});
api.root.addMethod("PUT", getS3Integration, {
requestValidator: requestValidator,
requestModels: {"application/json": myModel},
});
Sto ottenendo:
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)
Non so come specificare quel ruolo ARN, non l'ho trovato nei documenti. Non so neanche se fosse necessario aggiungere criteri a restAPI. Stavo cercando di replicare l'esempio qui in CDK.
Risposte
Di seguito non è il set completo, ma questo dovrebbe darti alcune idee. Ho fatto cose simili su SQS, ho pianto anch'io allora
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"
}
]});
}
Nel documento che hai collegato (https://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-s3.html), sezione "Configurazione delle autorizzazioni IAM per l'API per richiamare le azioni Amazon S3", la policy che devi utilizzare è completamente diversa da quella che hai codificato.
La tua policy, se applicata a un bucket, direbbe: se la richiesta proviene dal servizio "api gateway", consenti put:*azioni. Questo approccio è per altri casi d'uso.
Secondo la documentazione, hai bisogno di:
- creare un ruolo
- il ruolo dovrebbe contenere politiche:
- azioni consentite (
put:*nel tuo caso) - consentire al gateway API di passare al ruolo.
- azioni consentite (
- usa il ruolo in
apigateway.RestApi
La politica (1) dovrebbe essere ovvia, la (2) fornita nella documentazione è:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Dalla tua descrizione, mi sembra che tu non stia fornendo il ruolo IAM per la tua integrazione. Stai fornendo una politicaRestApi solo per la quale è una politica basata sulle risorse per la tua API. In altre parole, non si applica alle tue integrazioni, ma piuttosto specifica chi può eseguire la tua API. Generalmente non lo usi se vuoi rendere pubblica la tua API.
Per l'integrazione AWS, dovresti fornire al ruolo IAM le autorizzazioni S3 utilizzando IntegrationOptions . Nello specifico, tramite credentialsopzione:
Un ruolo IAM assunto da API Gateway .
I documenti di CloudFormation, a cui CDK mappa, contengono maggiori dettagli sull'integrazione Credentials:
Le credenziali necessarie per l'integrazione. Per specificare un ruolo AWS Identity and Access Management (IAM) assunto da API Gateway, specifica l'Amazon Resource Name (ARN) del ruolo. Per richiedere che l'identità del chiamante venga trasmessa dalla richiesta, specificare arn: aws: iam ::: user / .
Per utilizzare le autorizzazioni basate sulle risorse sulla funzione AWS Lambda (Lambda), non specificare questa proprietà. Utilizza la risorsa AWS :: Lambda :: Permission per consentire a API Gateway di chiamare la funzione. Per ulteriori informazioni, consulta Consentire ad Amazon API Gateway di richiamare una funzione Lambda nella Guida per sviluppatori AWS Lambda.