特定の IP アドレスにのみアクセスを許可するように HTTP API を設定する方法を教えてください。
HTTP API を AWS Lambda 関数と統合して、特定の IP アドレスのみを認証および許可したいです。
簡単な説明
HTTP API アクセスを特定の定義済みの IP アドレスに制限するには、オーソライザーとして Lambda 関数をデプロイします。Lambda 関数は IP アドレスの検証を実行して、受信リクエストが承認されたソースから送信されたかどうかを判断します。その後、オーソライザーは IP アドレスに基づいて HTTP API へのアクセスを許可または拒否します。
解決策
Lambda 関数を作成する
まず、オーソライザーとして使用する Lambda 関数を作成します。許可リストに環境変数を使用するように Lambda 関数を設定できます。
Key: IP_RANGE, Value: ['0.0.0.0','XX.XX.XX.XX']
値には、許可する特定の IP アドレスまたは、完全な CIDR 範囲を設定できます。
コードをデプロイしたら、Lambda 関数の環境変数を設定し、特定の変数を IP_RANGE として定義します。
セキュリティ上の理由から、AWS Key Management Service (AWS KMS) を使用して環境変数を暗号化するのがベストプラクティスです。
HTTP API を作成する
受信リクエストのエントリポイントとして使用する HTTP API を作成します。HTTP API はデフォルトでパブリックであるため、オーソライザーの Lambda 関数を使用してアクセスを制御します。
Lambda オーソライザーをアタッチする
オーソライザーとして Lambda 関数を API に関連付けます。リクエストが API に到達すると、オーソライザーは送信元 IP アドレスを許可リストと照合して評価します。オーソライザーが IP アドレスを許可すると、HTTP API エンドポイントへのアクセスが許可されます。それ以外の場合、リクエストは拒否されます。
許可リストに登録されている環境変数に基づいて IP アドレスを評価するには、次の Lambda 関数の例を使用します。
注: この例では、secretcode という値を持つ authorizationtoken を渡します。ただし、これらのパラメータは別の値を使用するように構成できます。
# -*- coding: utf-8 -*- # ======================== # AWS Lambda Python Runtime # ======================== # Import necessary modules import os from ipaddress import ip_network, ip_address import uuid import ast # Function to check if an IP address is within the specified IP range def check_ip(IP_ADDRESS, IP_RANGE): VALID_IP = False # Check if any of the elements in IP_RANGE contain a CIDR notation (e.g., "192.168.0.0/24") cidr_blocks = list(filter(lambda element: "/" in element, IP_RANGE)) if cidr_blocks: for cidr in cidr_blocks: # Create an IP network from the CIDR notation net = ip_network(cidr) # Check if the IP_ADDRESS is within the network VALID_IP = ip_address(IP_ADDRESS) in net if VALID_IP: break # If the IP_ADDRESS is not within any CIDR block, check if it matches an exact IP in IP_RANGE if not VALID_IP and IP_ADDRESS in IP_RANGE: VALID_IP = True return VALID_IP # Lambda function handler def lambda_handler(event, context): # Extract the source IP address from the request's RequestContext IP_ADDRESS = event["requestContext"]["http"]["sourceIp"] # Parse the IP_RANGE environment variable, which is a list of allowed IP addresses or CIDR blocks IP_RANGE = ast.literal_eval(os.environ.get("IP_RANGE", "[]")) # Check if the source IP is within the allowed IP range VALID_IP = check_ip(IP_ADDRESS, IP_RANGE) # Extract relevant information from the request event # Extract the AWS API Gateway's API ID from the event API_ID = event["requestContext"]["apiId"] # Extract the AWS account ID from the event ACC_ID = event["requestContext"]["accountId"] # Extract the AWS API Gateway's Details Method, Stage and Route from the event METHOD = event["requestContext"]["http"]["method"] STAGE = event["requestContext"]["stage"] ROUTE = event["requestContext"]["http"]["path"] # Check if the request includes a valid authorization token and the source IP is allowed # Use the {region} based on the region of the API Gateway's configuration. if event["headers"]["authorizationtoken"] == "secretcode" and VALID_IP: # If authorized, allow the execution of the API response = { "principalId": f"{uuid.uuid4().hex}", "policyDocument": { "Version": "2012-10-17", "Statement": [ { "Action": "execute-api:Invoke", "Effect": "Allow", "Resource": f"arn:aws:execute-api:{region}:{ACC_ID}:{API_ID}/{STAGE}/{METHOD}{ROUTE}", } ], }, "context": {"exampleKey": "exampleValue"}, } return response # If the request is not authorized or the IP is not allowed, deny execution # Use the Acc_ID, region & API_ID as per the HTTP API ID Details response = { "principalId": f"{uuid.uuid4().hex}", "policyDocument": { "Version": "2012-10-17", "Statement": [ { "Action": "execute-api:Invoke", "Effect": "Deny", "Resource": f"arn:aws:execute-api:{region}:{ACC_ID}:{API_ID}/*/*/*", } ], }, "context": {"exampleKey": "exampleValue"}, } return response
注: 追加の Python モジュールが必要な場合は、pip を使用してモジュールを Lambda 関数の環境にインストールします。Lambda 関数に必要な依存関係を含め、パッケージ化します。
オーソライザーをテストする
関数を本番環境にデプロイする前に、必ずテスト環境で関数をテストしてください。HTTP API エンドポイントにアクセスさせる IP アドレスを確認するには、アクセスログを使用します。コンテキスト変数を使用して IP アドレスを識別し、**IP_RANGE ** 環境変数を使用してそのアドレスを許可リストに含めます。次の例には、HTTP API のアクセスログ記録用のコンテキスト変数が含まれています。
{"ownerAccountId":"$context.accountId","apiId":"$context.apiId","requestId":"$context.requestId", / "ip":"$context.identity.sourceIp","requestTime":"$context.requestTime","httpMethod":"$context.httpMethod", / "routeKey":"$context.routeKey","status":"$context.status","protocol":"$context.protocol", / "responseLength":"$context.responseLength","errorMessage":"$context.error.message", / "errorMessageString":"$context.error.messageString","extendedRequestId":"$context.extendedRequestId", / "responseLatency":"$context.responseLatency","stage":"$context.stage","path":"$context.path", / "requestTimeEpoch":"$context.requestTimeEpoch","protocol":"$context.protocol","userAgent":"$context.identity.userAgent", / "errorResponseType":"$context.error.responseType","integrationStatus":"$context.integration.status", / "integrationErrorMessage":"$context.integrationErrorMessage","integrationRequestId":"$context.integration.requestId", / "integrationLatency":"$context.integration.latency","integrationStatusfromIntegration":"$context.integration.integrationStatus", / "integrationError":"$context.integration.error","awsEndpointRequestId":"$context.awsEndpointRequestId", / "customAuthorizerUser":"$context.identity.user","authorizerProperty":"$context.authorizer.property", / "customAuthorizerprincipalId":"$context.authorizer.principalId","authorizerError":"$context.authorizer.error"}
変数 ip":"$context.identity.sourceIp で、API エンドポイントをリクエストする IP アドレスを指定します。これにより、IP アドレスを識別して許可リストに追加できます。
関連するコンテンツ
- 質問済み 5年前lg...
- AWS公式更新しました 2ヶ月前