Tag: api gateway

  • [AWS] Sử dụng API Gateway Lambda Authorizers với JWT như thế nào?

    [AWS] Sử dụng API Gateway Lambda Authorizers với JWT như thế nào?

    Một trọng những vấn đề quan trọng trong các dự án đó là điều khiển quyền truy cập. Với các ứng dụng xây dựng trên nền tảng AWS việc điều khiển truy cập cũng phức tạp hơn. Trong bài viết này tôi sẽ hướng dẫn các bạn cách tôi đã làm để điểu khiển truy cập với các API sử dụng API Gateway Lambda Authorizers.

    Luồng xác thực Lambda Authorizer

    Luồng xác thực của Lambda Authorizer được minh hoạ trong hình sau:

    auhorizer

    Các bược xác thực như sau:

    1. Máy khách gửi yêu cầu lên API Gateway API có kèm theo Bearer Token.
    2. API Gateway kiểm tra cấu hình authorizer đã được cấu hình tương ứng với hàm Lambda. Nếu nó tồn tại thì Lambda Authoirizer sẽ được gọi.
    3. Lambda Authorizer sẽ thực hiện xác thực bằng Bearer Token đã được gửi lên.
    4. Nếu việc gọi Lambda Authrorizer thực hiện thành công, hàm Lambda sẽ trả về thông tin chứa chính sách IAM và thông tin người dùng.
    5. API Gateway sử dụng thông tin trả về từ Lambda Authorizer để kiểm tra quyền truy cập:
    • Trường hợp nhận được thông tin từ chối truy cập thì API Gateway sẽ trả về mã 403 và từ chối truy cập tới API từ máy khách.
    • Trường hợp nhận được thôn tin cho phép truy cập thì phương thức sẽ được thực thi.

    Định nghĩa Lambda Authorizer

    • Khai báo authorizer trong serverless.yml:
    functions:
      authorizer:
        handler: src.api.authorizer.lambda_handler
        cors: true
    
    • Định nghĩa hàm Lambda Authorizer:
    import jwt
    
    
    def lambda_handler(event, context):
        try:
            token = event.get("authorizationToken").split(" ")[1] # lấy thông tin token trong Authorization header
            claims = jwt.decode(token, "secret", algorithms=["HS256"]) # decode xem token có hợp lệ không
            return {
                "principalId": claims["uid"], # lấy thông tin user đề gán vào IAM
                "policyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Action": "execute-api:Invoke",
                            "Effect": "Allow", # cho phép nếu token hợp lệ
                            "Resource": event["methodArn"],
                        }
                    ],
                },
            }
        except:
            return {
                "principalId": "denied",
                "policyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Action": "execute-api:Invoke",
                            "Effect": "Deny", # từ chối nếu token không hợp lệ
                            "Resource": event["methodArn"],
                        }
                    ],
                },
            }
    

    Định nghĩa hàm Lambda cần điều khiển quyề truy cập

    • Khai báo hàm Lambda trong serverless.yml
    functions:
      test:
        handler: src.api.test.lambda_handler
        events:
          - http:
              method: get
              path: api/test
              cors: true
              authorizer: authorizer # khai báo Lambda Authorizer
    
    • Định nghĩa hàm Lambda:
    import json
    
    
    def lambda_handler(event, context):
        headers = {"Access-Control-Allow-Origin": "*", "Accept": "application/json"}
        body = {"status": "success"}
        return {
            "statusCode": 200,
            "headers": headers,
            "body": json.dumps(body),
        }
    

    Test thử Lambda với Authorizer

    • Trường hợp không truyền token trên Authorizer Header, API Gateway sẽ trả về 403

    No Auth

    • Trường hợp có truyền token trên Authorization Header, API Gateway sẽ cho phép phương thức được thực thi

    Token được tạo như sau

    (zpn) hieunv@HieuNV lambda % python
    Python 3.7.7 (default, Mar 10 2020, 15:43:33)
    [Clang 11.0.0 (clang-1100.0.33.17)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import jwt
    >>> jwt.encode({'uid': 'hieunv'}, "secret", algorithm='HS256')
    b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1aWQiOiJoaWV1bnYifQ.xuZSlS_3lw6NvGvw_fQ2qXGBWiv2HpXTFtYtO85lQac'
    

    Truyền token lên Authorizer Header

    Bearer Auth

    Tài liệu tham khảo:

    Cám ơn các bạn đã theo dõi bài viết. Hy vọng bài viết có thể giúp các bạn cài đặt việc điều khiển truy cập dễ dàng hơn với các ứng dụng trên nền tảng AWS.

  • Mô phỏng AWS Lambda & API Gateway bằng Serverless Offline

    Mô phỏng AWS Lambda & API Gateway bằng Serverless Offline

    Khi phát triển ứng dùng bằng AWS Lambda không phải lúc nào chúng ta cũng có thể phát triển trực tiếp trên AWS được. Do đó việc giả lập môi trường AWS để có thể chạy được Lambda và API Gateway là cần thiết. Nó không chỉ giúp chúng ta có thể học mà còn giúp cho quá trình phát triển nhanh hơn. Trong bài viết này tôi sẽ hướng dẫn các bạn giả lập AWS Lambda và API Gateway bằng Serverless Offline

    Các công cụ cần thiết

    Trước tiên bạn cần cài đặt các tool cần thiết, bạn có thể tham khảo hướng dẫn cài đặt trong các bài viết sau:

    Bạn có thể dùng lệnh sau để cài serverless

    hieunv@HieuNV lambda % yarn global add serverless
    yarn global v1.22.0
    [1/4] ?  Resolving packages...
    [2/4] ?  Fetching packages...
    [3/4] ?  Linking dependencies...
    [4/4] ?  Building fresh packages...
    success Installed "[email protected]" with binaries:
          - serverless
          - slss
          - sls
    ✨  Done in 14.23s.
    

    Tạo một project mới

    • Tạo project với yarn
    hieunv@HieuNV hieunv % mkdir lambda
    hieunv@HieuNV hieunv % cd lambda
    hieunv@HieuNV lambda % yarn init
    yarn init v1.22.0
    question name (lambda):
    question version (1.0.0):
    question description:
    question entry point (index.js):
    question repository url:
    question author:
    question license (MIT):
    question private:
    success Saved package.json
    ✨  Done in 3.53s.
    
    • Cài đặt serverless-offline
    hieunv@HieuNV lambda % yarn add serverless-offline -D
    
    • Cài đặt serverless-python-requirements để viết lambda handler bằng python
    hieunv@HieuNV lambda % yarn add serverless-python-requirements -D
    

    Cấu hình serverless.yml

    serverless.yml

    service: lambda
    
    frameworkVersion: '>=1.1.0 <2.0.0'
    
    provider:
      name: aws
      runtime: python3.7
    custom:
      serverless-offline:
        port: 4000
    plugins:
      - serverless-offline
      - serverless-python-requirements
    

    Cấu hình lambda handler đầu tiên trong serverless.yml

    Chúng ta tạo một Rest API sử dụng lambda bằng cách thêm đoạn sau vào file serverless.yml

    functions:
      test:
        handler: src.api.test.lambda_handler
        events:
          - http:
              method: get
              path: api/test
              cors: true
    

    Ở đây chúng ta tạo ra một Rest API với phướng thức GET và path /api/test. Các bạn nhìn thấy handler: src.api.test.lambda_handler đúng không. Đây là cấu hình hàm lamda sẽ được gọi bởi API Gateway

    Viết code cho lambda handler

    src/api/test.py

    import json
    
    
    def lambda_handler(event, context):
        headers = {"Access-Control-Allow-Origin": "*", "Accept": "application/json"}
        return {
            "statusCode": 200,
            "headers": headers,
            "body": json.dumps({"status": "success", "data": {}}),
        }
    

    Tạo script để run server

    Thêm đoạn sau vào package.json

        "scripts": {
            "start": "sls offline start"
        },
    

    Giờ thì chạy thôi nào các thanh niên

    hieunv@HieuNV lambda % yarn start
    yarn run v1.22.0
    $ sls offline start
    Serverless: Starting Offline: dev/us-east-1.
    
    Serverless: Routes for test:
    Serverless: GET /api/test
    Serverless: POST /{apiVersion}/functions/lambda-dev-test/invocations
    
    Serverless: Offline [HTTP] listening on http://localhost:4000
    Serverless: Enter "rp" to replay the last request
    

    Dùng Postman để call api vừa tạo nhé:

    Cám ơn các bạn đã theo dõi bài viết. Hy vọng bài viết có thể giúp các bạn tiếp tục học và làm việc cùng với AWS Lambda và API Gateway trong các dự án của mình.