pulumi / pulumi-awsx

AWS infrastructure best practices in component form!
https://www.pulumi.com/docs/guides/crosswalk/aws/
Apache License 2.0
210 stars 105 forks source link

Crosswalk API Gateway Fails without set region #869

Open Fredi100 opened 2 years ago

Fredi100 commented 2 years ago

What happened?

When creating an AWS API Gateway for a lambda using awsx.apigateway.API, the provisioning process fails. Setting the region beforehand via pulumi config set aws:region fixes the problem.

Steps to reproduce

export function createBackend(){

// Points to the built backend const packageArchive = new pulumi.asset.FileArchive("../../../dist/apps/backend");

// A simple s3 bucket to store the backend code const bucket = new aws.s3.Bucket("srcBucket", { acl: "public-read" });

// A bucket object containing the backend code as a zip file const bucketObject = new aws.s3.BucketObject("lambdaSourceObject",{ bucket: bucket, source: packageArchive, key: "backend.zip" }, {dependsOn: [bucket]});

const iamForLambda = new aws.iam.Role("iamForLambda", { assumeRolePolicy: JSON.stringify({ Version: "2012-10-17", Statement: [{ Action: "sts:AssumeRole", Principal: { Service: "lambda.amazonaws.com" }, Effect: "Allow", Sid: "" }] }) }, {dependsOn: [bucketObject]});

// The lambda function needs permissions to actually create logs const lambdaLogPolicy = new aws.iam.RolePolicy('lambdaLogPolicy', { role: iamForLambda, policy: JSON.stringify({ Version: "2012-10-17", Statement: [{ Effect: "Allow", Action: [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], Resource: "*" }] } as PolicyDocument) }, {dependsOn: [iamForLambda]});

// The lambda function needs permission to query database entries const lambdaDBPolicy = new aws.iam.RolePolicy('lambdaDBPolicy',{ role: iamForLambda, policy: { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "dynamodb:BatchGetItem", "dynamodb:GetItem", "dynamodb:Scan", "dynamodb:Query", "dynamodb:BatchWriteItem", "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem" ], "Resource": "arn:aws:dynamodb:*:*:table/DiscountCodesCreationLog" } ] } }, {dependsOn: [iamForLambda]});

// Creating the actual lambda function const lambda = new aws.lambda.Function(backendLambda, { role: iamForLambda.arn, runtime: "nodejs14.x", handler: "main.handler", s3Bucket: bucket.id, s3Key: bucketObject.key, memorySize: 256, environment: { variables: { production: 'true' } } }, {dependsOn: [bucketObject, iamForLambda, lambdaLogPolicy, lambdaDBPolicy]});

const api = new awsx.apigateway.API("awsxTest", { routes: [ { path: "/api", method: "ANY", eventHandler: lambda }, { path: "/api/{proxy+}", method: "ANY", eventHandler: lambda } ] }, {dependsOn: [lambda]}) }

createBackend();


### Expected Behavior

The automation API should be able to infer the region for the route as the deployment of the s3 bucket as well as the lambda itself works without explicitly setting the region.

### Actual Behavior

When I try to run my script I get following error in the terminal:
 Type                          Name                Status                  Info

Diagnostics: pulumi:pulumi:Stack (Backend-dev): error: update failed

aws:apigateway:RestApi (awsxTest): error: 1 error occurred:

I was running pulumi up --logtostderr --logflow -v=9 2> out.txt to get a more comprehensive log. At the very end was following error response from aws included:

{
    "swagger": "2.0",
    "info": {
        "title": "awsxTest",
        "version": "1.0"
    },
    "paths": {
        "/api": {
            "x-amazon-apigateway-any-method": {
                "x-amazon-apigateway-integration": {
                    "uri": "arn:aws:apigateway:undefined:lambda:path/2015-03-31/functions/arn:aws:lambda:eu-central-1: <id>:function:backendLambda-5dec676/invocations",
                    "passthroughBehavior": "when_no_match",
                    "httpMethod": "POST",
                    "type": "aws_proxy"
                }
            }
        },
        "/api/{proxy+}": {
            "x-amazon-apigateway-any-method": {
                "x-amazon-apigateway-integration": {
                    "uri": "arn:aws:apigateway:undefined:lambda:path/2015-03-31/functions/arn:aws:lambda:eu-central-1: <id>:function:backendLambda-5dec676/invocations",
                    "passthroughBehavior": "when_no_match",
                    "httpMethod": "POST",
                    "type": "aws_proxy"
                }
            }
        }
    },
    "x-amazon-apigateway-binary-media-types": [
        "* /*"
    ],
    "x-amazon-apigateway-gateway-responses": {
        "MISSING_AUTHENTICATION_TOKEN": {
            "statusCode": 404,
            "responseTemplates": {
                "application/json": "{\"message\": \"404 Not found\" }"
            }
        },
        "ACCESS_DENIED": {
            "statusCode": 404,
            "responseTemplates": {
                "application/json": "{\"message\": \"404 Not found\" }"
            }
        }
    },
    "x-amazon-apigateway-api-key-source": "HEADER"
}

When looking at the uri of the integration, the region is undefined.

*Note: I have replaced my aws id with <id>.

Versions used

Here is the version of pulumi I was using:

CLI          
Version      3.33.1
Go Version   go1.17.10
Go Compiler  gc

Host     
OS       Microsoft Windows 11 Pro
Version  10.0.22000 Build 22000
Arch     x86_64

Additional context

The error message provided by the pulumi cli only states an invalid ARN. As the invalid URI for the failing integration which includes the undefined part is not provided, its not very clear as to what the actual problem is. Especially because the ARN and the URI are automatically created and therefore not accessible to the user.

Contributing

Vote on this issue by adding a 👍 reaction. To contribute a fix for this issue, leave a comment (and link to your pull request, if you've opened one already).

Frassle commented 2 years ago

I don't think there's anything automation API specific about this. Looks like just an issue with awsx apigateway.

jkisk commented 2 years ago

We will look into this a bit more, but in the mean time setting the region explicitly is a good workaround, thanks for calling it out.

praneetloke commented 1 year ago

It's possible that this could be fixed by making sure this function (getRegionFromProvider in utils.ts) considers the region set by the AWS SDK as a fallback (i.e. aws.sdk.region I believe?) I think the problem is that it only falls back to the provider config (stack config) if there is no explicit provider instance to use. But as noted by @Fredi100, if you don't set aws:region in your stack config, then even that is undefined.