Jak zintegrować API Gateway z s3 w CDK

Sep 12 2020

Dokumentacja jest bardzo jasna, robiąc to w konsoli, https://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-s3.html, ale replikacja w CDK jest naprawdę bolesna.

Moje pytanie brzmi, jak stworzyć Rest API z s3 (bez lambdy w środku) w CDK, a przynajmniej jak działa apigateway.AwsIntegration.

Próbowałem wielu rzeczy i zdałem sobie sprawę, że kodowałem na ślepo. Zrobiłem już wiele integracji między restApi, lambda, sqs, dynamoDB, s3 i wszystkie z nich były takie łatwe. Ale bezpośrednia integracja API Gateway z S3 sprawi, że zacznę płakać.

Potrzebuję, aby restAPI przechowało ładunek żądania bezpośrednio do zasobnika S3.

Oto, czego już próbowałem:

Dodaj zasadę do 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        
      });

Pomyślałem, że to powinno wystarczyć do rozwiązania problemów z uprawnieniami, ale kiedy dodałem Integrację AWS do API, tak:

const getS3Integration = new apigateway.AwsIntegration({
        service: "s3",        
        path: bucket.bucketName,                               
      });

api.root.addMethod("PUT", getS3Integration, {
    requestValidator: requestValidator,
    requestModels: {"application/json": myModel},
  });

Dostaję:

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)

Nie wiem, jak określić tę rolę ARN, nie znalazłem tego w dokumentach. Nie wiem też, czy konieczne było dodanie polityki do restAPI. Próbowałem odtworzyć przykład tutaj w CDK.

Odpowiedzi

3 Chun Sep 14 2020 at 18:19

Poniższy opis nie jest pełnym zestawem, ale powinno dać ci kilka pomysłów. Robiłem podobne rzeczy na SQS, wtedy też płakałem


    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"
        }
      ]});
  }
1 olpa Sep 14 2020 at 04:20

W dokumencie, do którego utworzyłeś łącze (https://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-s3.html), sekcja „Skonfiguruj uprawnienia interfejsu API do wywoływania działań Amazon S3”, zasada, której musisz użyć, jest zupełnie inna niż ta, którą zakodowałeś.

Twoja zasada, jeśli zostanie zastosowana do zasobnika, będzie brzmiała: jeśli żądanie pochodzi z usługi „brama interfejsu API”, zezwól na put:*działania. To podejście jest przeznaczone dla innych przypadków użycia.

Zgodnie z dokumentacją potrzebujesz:

  • stworzyć rolę
  • rola powinna zawierać zasady:
    1. dozwolone działania ( put:*w Twoim przypadku)
    2. zezwól bramie API na przełączenie się do roli.
  • użyj roli w apigateway.RestApi

Polityka (1) powinna być oczywista, (2) zgodnie z dokumentacją to:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "apigateway.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
} 
1 Marcin Sep 14 2020 at 08:02

Z twojego opisu wynika, że nie zapewniasz roli IAM dla swojej integracji. Jesteś zapewniając politykę dla RestApitylko co jest polityka oparta zasobów dla API. Innymi słowy, nie dotyczy Twoich integracji, ale raczej określa, kto może wykonywać Twoje API. Generalnie nie używasz go, jeśli chcesz upublicznić swój interfejs API.

W przypadku integracji AWS należy zapewnić rolę IAM z uprawnieniami S3 przy użyciu IntegrationOptions . W szczególności poprzez credentialsopcję:

Rola IAM, którą przyjmuje API Gateway .

Dokumentacja CloudFormation, do której mapuje CDK, zawiera więcej szczegółów na temat integracji Credentials:

Poświadczenia wymagane do integracji. Aby określić rolę AWS Identity and Access Management (IAM), którą przyjmuje API Gateway, określ nazwę zasobu Amazon (ARN) roli. Aby wymagać, aby tożsamość osoby dzwoniącej była przekazywana z żądania, określ arn: aws: iam ::: user / .

Aby użyć uprawnień opartych na zasobach w funkcji AWS Lambda (Lambda), nie określaj tej właściwości. Użyj zasobu AWS :: Lambda :: Permission, aby zezwolić API Gateway na wywołanie funkcji. Aby uzyskać więcej informacji, zobacz Zezwalanie Amazon API Gateway na wywoływanie funkcji Lambda w AWS Lambda Developer Guide.