2
votes

Comment s'assurer que l'autorisation de jeton API Gateway est appelée uniquement pour des chemins spécifiques

Nous avons une passerelle API utilisant un auteur de jeton personnalisé . Nous avons 2 lambdas - Salutations et GenerateToken .

Nous voulons que le lambda Salutations soit derrière un auteur - doit être appelé de la manière suivante en utilisant SAM:

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: API Gateway with Lambda Token Authorizer
Resources:
  GreetingsApiGateway:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      DefinitionBody:
        swagger: 2.0
        x-amazon-apigateway-policy:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Principal: "*"
              Action: execute-api:Invoke
              Resource:
                - execute-api:/*/*/*
        paths:
          "/hello":
            get:
              x-amazon-apigateway-integration:
                httpMethod: POST
                type: aws_proxy
                uri:
                  Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GreetingsLambda.Arn}/invocations
              responses: {}
          "/generateToken":
            get:
              x-amazon-apigateway-integration:
                httpMethod: POST
                type: aws_proxy
                uri:
                  Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GenerateTokenLambda.Arn}/invocations
              responses: {}
      Auth:
        DefaultAuthorizer: CustomAuthorizer
        Authorizers:
          MyAuthorizer:
            FunctionArn: !GetAtt AuthLambda.Arn
            Identity:
              Header: X-API-KEY

  GenerateTokenLambda:
    Type: AWS::Serverless::Function
    Properties:
      Role: !GetAtt LambdaRole.Arn
      CodeUri: "s3://<bucket-name>/code.zip"
      Handler: src/generateToken.handler
      Events:
        GetRoot:
          Type: Api
          Properties:
            RestApiId: !Ref GreetingsApiGateway
            Path: /generateToken
            Method: get

  GreetingsLambda:
    Type: AWS::Serverless::Function
    Properties:
      Role: !GetAtt LambdaRole.Arn
      CodeUri: "s3://<bucket-name>/code.zip"
      Handler: src/greetings.handler
      Events:
        GetRoot:
          Type: Api
          Properties:
            RestApiId: !Ref GreetingsApiGateway
            Path: /hello
            Method: get

  AuthLambda:
    Type: AWS::Serverless::Function
    Properties:
      Role: !GetAtt LambdaRole.Arn
      CodeUri: "s3://<bucket-name>/code.zip"
      Handler: src/auth.handler

Globals:
  Function:
    Runtime: nodejs8.10

Outputs:
  ApiURL:
    Description: "OUR API URL"
    Value: !Sub "https://${GreetingsApiGateway}.execute-api.${AWS::Region}.amazonaws.com/Prod/"

Comment pouvons-nous faire en sorte que le chemin GenerateToken ne nécessite pas de jeton HTTP pour l'authentification?

XXX


0 commentaires

3 Réponses :


2
votes

Je ne suis pas sûr d'avoir bien compris ce que vous voulez, mais voici un modèle Cloudformation pour créer des ressources api-gateway avec et sans autorisation activée. J'utilise la méthode d'autorisation Cognito User Pool , mais cela peut être tout aussi facilement un autorisateur personnalisé.

RestAPI:
  Type: AWS::ApiGateway::RestApi
  DeletionPolicy: Delete
  Properties:
    Name: {"Ref": "AWS::StackName"}
    ApiKeySourceType: HEADER
    EndpointConfiguration:
      Types:
        - EDGE

ApiAuthorizer:
  Type: AWS::ApiGateway::Authorizer
  DeletionPolicy: Retain
  DependsOn: UserPoolList
  Properties:
    Name: !Join ["-", [{"Ref": "AWS::StackName"}, "authorizer"]]
    RestApiId: !Ref RestAPI
    Type: COGNITO_USER_POOLS
    AuthType: cognito_user_pools
    IdentitySource: "method.request.header.Authorization"
    ProviderARNs: <User Pool ARN>

ResourceSignin:
  Type: AWS::ApiGateway::Resource
  DeletionPolicy: Delete
  Properties:
    RestApiId: !Ref RestAPI
    ParentId: !GetAtt RestAPI.RootResourceId
    PathPart: "signin"

SigninPostMethod:
  Type: AWS::ApiGateway::Method
  Properties:
    RestApiId: !Ref RestAPI
    ResourceId: !Ref ResourceSignin
    HttpMethod: POST
    AuthorizationType: NONE
    ApiKeyRequired: <true/false>
    Integration:
      Type: AWS_PROXY
      IntegrationHttpMethod: POST
      Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${UserHandlerFunction.Arn}/invocations
      Credentials: !GetAtt GenApiGatewayRole.Arn

ResourceUserCreate:
  Type: AWS::ApiGateway::Resource
  DeletionPolicy: Delete
  Properties:
    RestApiId: !Ref RestAPI
    ParentId: !GetAtt RestAPI.RootResourceId
    PathPart: "create"

CreatePostMethod:
  Type: AWS::ApiGateway::Method
  Properties:
    RestApiId: !Ref RestAPI
    ResourceId: !Ref ResourceUserCreate
    HttpMethod: POST
    AuthorizationType: COGNITO_USER_POOLS
    AuthorizerId: !Ref ApiAuthorizer
    ApiKeyRequired: <true/false>
    Integration:
      Type: AWS_PROXY
      IntegrationHttpMethod: POST
      Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${UserHandlerFunction.Arn}/invocations
      Credentials: !GetAtt UserApiGatewayRole.Arn

Ici, la ressource signin a un La méthode POST sans autorisation tandis que la ressource create a une méthode POST avec l'autorisation activée.

Si vous prévoyez d'utiliser Clés API , c'est peut-être le seul moyen possible. Je n'ai pas pu faire fonctionner les clés API avec SAM (je crois que les clés API avec SAM ne sont pas encore prises en charge - il y a environ un mois, mais vous pouvez vérifier).


3 commentaires

Merci pour cette réponse, je n'ai pas réussi à le faire fonctionner dans notre modèle SAM - ma question est plus liée aux autorisateurs SAM et Token. Mise à jour de la question pour tenter de la clarifier


Vous dites que GreetingsLambda doit être derrière un autorisateur mais l'exemple de curl a un appel à generateToken avec X-API-KEY: allow . Cet en-tête concerne-t-il l'autorisation ou utilisez-vous des clés API ?


c'est l'en-tête de l'autorisateur



0
votes

Nous pouvons y parvenir via swagger dans API Gateway:

Le lambda World est une API publique et le lambda Hello réside derrière l'autorisation AuthLambda

  OurApiGateway:
    Type: AWS::Serverless::Api
    Properties:
      StageName: Prod
      Auth:
        Authorizers:
          MyAuthorizer:
            FunctionPayloadType: REQUEST
            FunctionArn: !GetAtt AuthLambda.Arn
      DefinitionBody:
        swagger: 2.0
        basePath: /prod
        info:
          title: AwsSamExample
        x-amazon-apigateway-policy:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Principal: "*"
              Action: execute-api:Invoke
              Resource:
                - execute-api:/*/*/*
        schemes:
          - https
        paths:
          "/hello":
            get:
              x-amazon-apigateway-integration:
                httpMethod: POST
                type: aws_proxy
                uri:
                  Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HelloLambda.Arn}/invocations
              responses: {}
              security:
                - MyAuthorizer: []
          "/world":
            get:
              x-amazon-apigateway-integration:
                httpMethod: POST
                type: aws_proxy
                uri:
                  Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${WorldLambda.Arn}/invocations
              responses: {}
              security: []



0 commentaires

0
votes

Utilisez le framework Serverless et gérez-le facilement avec juste un attribut. https://www.npmjs.com/package/serverless


0 commentaires