web-dev-qa-db-fra.com

Comment ajouter CloudFront devant API Gateway

API Gateway (APIG), bien qu’elle utilise CloudFront (CF), elle ne prend pas en charge la mise en cache CDN Edge. Lorsque j'ai configuré une distribution CF pour qu'elle utilise APIG en tant qu'origine personnalisée, j'obtiens une erreur d'autorisation refusée.

Comment configurer CF pour résoudre ce problème?

31
rynop

Jusqu'à ce que la passerelle API (APIG) prenne en charge la mise en cache Edge via son utilisation interne de CloudFormation (CF), je propose une solution de contournement. 

Vous pouvez en effet mettre CF dist devant APIG, l’astuce consiste à forcer HTTPS uniquement "Stratégie de protocole du visualiseur" ET à ne pas transmettre l’en-tête de l’hôte, car APIG a besoin du SNI.

J'ai configuré mes "Paramètres de comportement du cache par défaut" de la CF pour qu'ils ne transmettent aucun en-tête, et j'ai forcé "Stratégie de protocole du visualiseur" à "HTTPS uniquement" et cela fonctionne. J'espère que cela aide les autres.

Voici un objet de ressource CloudFormation qui a toute la configuration requise (Remarque: j'utilise la convention <stage>--<app name> pour StackName):

CloudFront:  
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Enabled: true
        IPV6Enabled: true
        HttpVersion: http2
        Comment: !Join [ '--', [!Ref 'AWS::StackName', ' Cloud Front']]
        Aliases: [!Ref CloudFrontCname]
        ViewerCertificate:
          AcmCertificateArn: !Ref AcmCertificateArn
          SslSupportMethod: sni-only
          MinimumProtocolVersion: TLSv1.1_2016
        Origins:
        - Id: APIGOrigin
          DomainName: !Sub
            - ${apigId}.execute-api.${AWS::Region}.amazonaws.com
            - { apigId: !Ref ApiGatewayLambdaProxy }
          OriginPath: !Sub
            - /${Stage}
            - { Stage: !Select [ "0", !Split [ '--', !Ref 'AWS::StackName' ] ] }
          CustomOriginConfig:
            # HTTPPort: 80
            HTTPSPort: 443
            OriginProtocolPolicy: https-only
          OriginCustomHeaders:
            - HeaderName: 'Verify-From-Cf'
              HeaderValue: !Ref VerifyFromCfHeaderVal
        DefaultCacheBehavior:
          AllowedMethods: ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
          CachedMethods: ["GET", "HEAD", "OPTIONS"]
          ForwardedValues:
            Headers:
            - Access-Control-Request-Headers
            - Access-Control-Request-Method
            - Origin
            - Authorization
            # - Host APIG needs to use SNI
            QueryString: true
          TargetOriginId: APIGOrigin
          ViewerProtocolPolicy: https-only
          Compress: true
          DefaultTTL: 0
        CustomErrorResponses:
        - ErrorCachingMinTTL: 0
          ErrorCode: 400
        - ErrorCachingMinTTL: 1
          ErrorCode: 403
        - ErrorCachingMinTTL: 5
          ErrorCode: 500
  DNSARecord:    
    Type: AWS::Route53::RecordSet
    Properties:
      Comment: !Ref 'AWS::StackName'
      Name: !Ref CloudFrontCname
      Type: A
      HostedZoneName: !Join ['.', [ !Select [1, !Split ['.', !Ref CloudFrontCname]], !Select [2, !Split ['.', !Ref CloudFrontCname]], '']]
      AliasTarget:
        HostedZoneId: !Ref Route53HostedZoneId
        DNSName: !GetAtt CloudFront.DomainName
  DNSAAAARecord:    
    Type: AWS::Route53::RecordSet
    Properties:
      Comment: !Ref 'AWS::StackName'
      Name: !Ref CloudFrontCname
      Type: AAAA
      HostedZoneName: !Join ['.', [ !Select [1, !Split ['.', !Ref CloudFrontCname]], !Select [2, !Split ['.', !Ref CloudFrontCname]], '']]
      AliasTarget:
        HostedZoneId: !Ref Route53HostedZoneId
        DNSName: !GetAtt CloudFront.DomainName

Mises à jour fin 2018

  • Enfin, CloudFormation prend en charge la définition du protocole SSL: MinimumProtocolVersion: TLSv1.1_2016
  • J'ai intégré cette (et beaucoup d'autres) meilleures pratiques dans un projet de logiciel libre: aws-blueprint
51
rynop

Si API Gateway renvoie une erreur 403 avec:

L'en-tête d'autorisation nécessite le paramètre 'Credential'. Autorisation l'en-tête nécessite le paramètre 'Signature'. L'en-tête d'autorisation nécessite Paramètre 'SignedHeaders'. L'en-tête d'autorisation requiert l'existence de soit un en-tête 'X-Amz-Date' ou 'Date'.

il se peut également que le noeud final Origin soit incorrect. "API Gateway traite toutes les erreurs sur des chemins inexistants comme des erreurs 403 d'autorisation refusées plutôt qu'une erreur 404 non trouvée." (voir ce fil de support ).

J'ai eu cette erreur et j'ai supposé que je transmettais incorrectement l'en-tête Authorization, mais j'avais simplement mal configuré le chemin d'origine.

2
Kevin

Ajout aux réponses précédentes: 

il est important que le modèle de chemin de comportement corresponde en réalité à un chemin "réel". 


Si le point de terminaison de l'API est <id>.execute-api.<region>.amazonaws.com/stage-name/my-api

Et le domaine d'origine + chemin est <id>.execute-api.<region>.amazonaws.com/stage-name

Le modèle de chemin de comportement doit êtremy-api, my-api/*, my-api/something, etc.


Je ne sais pas pourquoi, mais je pensais que ce type de chemin pouvait être utilisé comme alias, par exemple:

https://www.example.com/random-name (modèle de chemin random-name) est résolu en domaine + chemin défini dans Origine, par exemple <id>.execute-api.<region>.amazonaws.com/stage-name.

Ce n'est pas le cas.

0
Solo

Avec le lancement des points finaux régionaux API Gateway en novembre 2017, je pense qu'il est maintenant optimal de les utiliser avec les distributions CloudFront au sommet. Voici des instructions détaillées pour passer des API Edge Optimized aux API régionales et configurer les distributions CloudFront: 

AWS API Gateway devrait empêcher l'utilisation de TLS v1

0
Alistair