serverless-components / express

⚡ Take existing Express.js apps and host them easily on cheap, auto-scaling, serverless infrastructure (AWS Lambda and AWS HTTP API).
https://serverless.com/components
Apache License 2.0
376 stars 34 forks source link

Invalid certificate ARN: arn:aws:acm:us-east-1:LAMBDA_ID:certificate/CERTIFICATE_ID. Certificate must be in 'eu-central-1'. #10

Closed StErMi closed 4 years ago

StErMi commented 4 years ago

This is my serverless.yaml

component: express
org: orgName
app: appName
name: api
stage: prod

inputs:
  src:
    src: ./src
    hook: npm run build:prod
    dist: ./dist
  domain: api.MY_ROUTE53_DOMAIN.com
  region: eu-central-1

and this is the error output

Initializing...
Action: "deploy" - Stage: "prod" - Org: "orgName" - App: "appName" - Name: "api"
Deploying...
Deploying Express App...
Packaging Express.js application...
Unzipping /tmp/e8ygooh/source.zip...
Files unzipped into /tmp/fd7zly1...
Installing Express + AWS Lambda handler...
Installing Serverless Framework SDK...
Zipping files...
Files zipped into /tmp/iywiid5.zip...
Verifying the default IAM Role found in state exists with the name: api-rjrujf8-lambda-role...
Verifying the meta IAM Role found in state exists with the name: arn:aws:iam::LAMBDA_ID:role/api-rjrujf8-meta-role...
Verifying the AWS Lambda with the ARN: arn:aws:lambda:eu-central-1:LAMBDA_ID:function:api-rjrujf8-function:3 and Name: api-rjrujf8-function found in state exists...
"AWS Lambda function found.  Updating it's configuration and code..."
AWS Lambda version "4" published
AWS Lambda function updated with ARN: arn:aws:lambda:eu-central-1:LAMBDA_ID:function:api-rjrujf8-function:4
Verifying alias "default"...
Alias "default" found. Updating...
Alias "default" updated.
Checking for existing API with ID: rkda8gh0wl
API found. Updating API with ID: rkda8gh0wl...
Add permission to Lambda enabling API Gateway with this ARN to call it: arn:aws:execute-api:eu-central-1:LAMBDA_ID:rkda8gh0wl/*/*
API with ID "rkda8gh0wl" Updated.
Getting Route53 Hosted Zone ID for domain: MY_ROUTE53_DOMAIN
Domain hosted zone id for MY_ROUTE53_DOMAIN is Z06488292F0FY3V47RWQ2
Checking if a certificate for the MY_ROUTE53_DOMAIN domain exists
Certificate for MY_ROUTE53_DOMAIN is in a "ISSUED" status
Verifying Custom Domain exists on API Gateway: api.MY_ROUTE53_DOMAIN...
Custom Domain not found in API Gateway: api.MY_ROUTE53_DOMAIN.  Creating it...
Domain api.MY_ROUTE53_DOMAIN not found in API Gateway. Creating...

 BadRequestException: Invalid certificate ARN: arn:aws:acm:us-east-1:LAMBDA_ID:certificate/CERTIFICATION_ID. Certificate must be in 'eu-central-1'.
    at Object.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/json.js:51:27)
    at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/rest_json.js:55:8)
    at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
    at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:683:14)
    at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/var/runtime/node_modules/aws-sdk/lib/request.js:685:12)

72s » api » Invalid certificate ARN: arn:aws:acm:us-east-1:LAMBDA_ID:certificate/CERTIFICATION_ID. Certificate must be in 'eu-central-1'.
eahefnawy commented 4 years ago

@StErMi yeah, unfortunately, custom domains are only supported in us-east-1 atm. This is due to an AWS limitation.

To be more specific, the express component uses AWS APIGV2 HTTP under the hood, which only supports regional endpoints that requires the cert to be in the same region as the API, and because ACM free certs are only available in us-east-1, your API must also be in us-east-1.

StErMi commented 4 years ago

Hi @eahefnawy as far as I can see from the ACM

Public SSL/TLS certificates provisioned through AWS Certificate Manager are free. You pay only for the AWS resources you create to run your application.

am I interpreting it wrongly?

StErMi commented 4 years ago

@eahefnawy what do you mean with "custom domains"? This domain has been registered with Route53. And as far as I can see in your README file both express and website are supporting custom domains.

At the moment you are forcing the us-east-1 region in both express and website components. I would like to understand why and which could be some solutions. Otherwise, it seems that the only thing I can do is to deploy all my lambda functions only in the us-east-1 region...

eahefnawy commented 4 years ago

@StErMi we are not forcing us-east-1. This is a limitation from AWS. I'll try to break it down for you:

  1. The express component uses the new AWS APIG V2 HTTP.
  2. APIG V2 HTTP does not support EDGE endpoints yet like APIG V1 REST APIs. It only supports REGIONAL endpoints atm. So that's what this component creates.
  3. A condition for REGIONAL endpoints is that the certificate MUST be in the same region as the APIG, unlike EDGE endpoints which basically uses CloudFront under the hood and can accept a certificate from any region.
  4. Now, you could deploy your component to any other region, however the free ACM certificate that we request on your behalf must be done in us-east-1, another AWS limitation, which would not satisfy the condition in the point above unless your APIG is also in us-east-1, hence the error above.

Do you see the dilemma? So until AWS APIG V2 HTTP supports EDGE endpoints, this seems to be an issue.

The website component, on the other hand, shouldn't have this issue. Are you facing this issue with the website component as well?

I hope this clears things up. This is all based on my humble understanding of AWS, but please do correct me if I'm wrong.

StErMi commented 4 years ago

Hi @eahefnawy sorry for the delay.

The website component (I think for the same reason) has us-east-1 enforced into code as well I don't get why you say that the AWS Certificate must be requested on us-east-1

So as far as I understood working with the framework and AWS the only limitation from AWS is that you need to create a CERT from us-east-1 to be used for your CF distribution.

Everything else can be regional without a problem. The only other limitation (but I need to experiment) that comes to my mind would be for the API custom domain distributed through CF. So maybe I would be limited to us-east-1 even for that. So everything should be under us-east-1 region.

If that's the case, I don't get how would it be possible to have a distributed system around the globe or even just in Europe (if all my customers are from Europe).

eahefnawy commented 4 years ago

So as far as I understood working with the framework and AWS the only limitation from AWS is that you need to create a CERT from us-east-1 to be used for your CF distribution.

Yep, that is correct. Just the CERT needs to be in us-east-1. Everything else could be in other regions. The issue as explained above is the fact that APIG V2 HTTP does not yet support EDGE endpoints, which allows the use of CERTS from any region.

If that's the case, I don't get how would it be possible to have a distributed system around the globe or even just in Europe (if all my customers are from Europe).

Yeah unfortunately until AWS APIGV2 HTTP supports EDGE endpoints, that will be a limitation.

eahefnawy commented 4 years ago

Also, I double-checked with the website component, and the region is only hardcoded for ACM, which is the desired behavior. So you should be able to deploy websites with custom domains to any region because AWS APIGV2 HTTP and its limitation is not involved here.

REF: https://github.com/serverless-components/website/search?q=us-east-1&unscoped_q=us-east-1

eahefnawy commented 4 years ago

If you'd like to explore more, I suggest you remove the domain property from your express YAML file and deploy it to any region you want. This should work, but you will not have a custom domain.

You can then configure the domain manually if possible. Based on my own trials, I personally don't think it's currently possible with the free CERT, but I could be wrong. If you are able to pull it off, we'd be happy to incorporate your changes 😊

eahefnawy commented 4 years ago

I just stumbled upon this page and thought I'd share it here. https://aws.amazon.com/premiumsupport/knowledge-center/custom-domain-name-amazon-api-gateway/

Only REST APIs can use edge-optimized custom domain names.

From this page, it is clear that only API Gateway V1 (ie. REST APIs) supports EDGE domains.

eddeee888 commented 4 years ago

Hello! I'm having a similar problem and I came across this: https://aws.amazon.com/premiumsupport/knowledge-center/acm-export-certificate/. It's saying I could create the same certificate in a different region and use it for resources in that region.

If I read the utils code here and according to the ACM API, we always return the first certificate with the same domain name so it could be in the wrong region.

I think if we could somehow check the provided region and use that when checking the domain, we might be able to get it to use the right certificate.

I'm still new to AWS/serverless framework so please correct me if I'm wrong. :)

References:

eahefnawy commented 4 years ago

Thanks for the thorough research @eddeee888 ... You could be correct, which I guess would fix this issue, but I think we still won't be able to use EDGE endpoints until APIG2 officially support it.

I'll investigate this more...