0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SecretManagerからSecretを取得して外部APIを実行させるLambda関数サンプル

Posted at

概要

・OAuth2.0のクライアント認証で使うトークンを取得する。
・SecretManagerにClientSecretとClientIdを保持している
・confidentialを作成してAPI Gateway経由で外部APIを実行し、取得したトークンをAPI Gatewayのステージ変数へ格納する。

import json
import ast
import boto3
import urllib.request
import urllib.parse
import base64
import os
import logging
from botocore.exceptions import ClientError

logging.basicConfig(
    format='%(asctime)-15s %(levelname)s %(message)s',
    level=logging.INFO
)

# AWSクライアント
apigw_client = boto3.client("apigateway")

# リージョン取得
region_name = os.environ['AWS_DEFAULT_REGION']

# API GatewayのIDを環境変数から取得
apigw_id = os.environ['APIGW_ID']

# 格納先のAPI Gatewayステージ変数キー
apigw_stagevalue_key = os.environ['APIGW_VALUE_KEY']

# 外部APIエンドポイント
target_url = os.environ['TARGET_API_URL']

# 格納先変数名
value_name = os.environ['VALUE_NAME']

# Secrets Managerで管理する値の名前
secret_name = "target-clientsecret"
target_client_id = "target-clientid"

# 外部API実行処理
def get_target_token():
    session = boto3.session.Session()
    client = session.client(
        service_name='secretsmanager',
        region_name=region_name
    )
    # Secrets Manager からSecretを取得
    try:
        get_secret_client_secrets_response = client.get_secret_value(
            SecretId=secret_name
        )
        get_secret_secrets_id_response = client.get_secret_value(
            SecretId=target_client_id
        )
        secret_client_secrets_data = get_secret_client_secrets_response['SecretString']
        secret_secrets_id_data = get_secret_secrets_id_response['SecretString']
        secretClientSecrets = ast.literal_eval(secret_client_secrets_data)
        secretClientID = ast.literal_eval(secret_secrets_id_data)
        clientSecret = secretClientSecrets['targetClientSecret'] #シークレット
        clientId = secretClientID['targetClientId'] #クライアントID
    except ClientError as e:
        logging.error(e)
        return "error"
        
    # トークン取得リクエスト(対象の外部APIによって編集する)
    credentials = base64.b64encode((clientId + ":" + clientSecret).encode()).decode()
    headers = {
        'Accept': 'application/json',
        'Authorization': 'Basic ' + credentials,
        'Content-Type': 'application/x-www-form-urlencoded'
    }
    data = {'grant_type':'client_credentials'}
    req = urllib.request.Request(target_url, headers=headers, data=urllib.parse.urlencode(data).encode('utf-8'), method='POST')
    
    # リクエスト実行
    try:
        with urllib.request.urlopen(req) as response:
            body = response.read()
            value = json.loads(body.decode('utf-8'))["access_token"]
            return value
    except urllib.error.HTTPError as err:
        logging.error(err)
        return "error"

def lambda_handler(event, context):
    # 外部APIを実行してtokenを取得
    token = get_target_token()
  
    # 設定ファイル書き換える
    if len(token) < 500:
        response = apigw_client.update_stage(
            restApiId=apigw_id,
            stageName=apigw_stagevalue_key,
            patchOperations=[
                {
                    'op': 'replace',
                    'path': '/variables/' + value_name,
                    'value': token
                }
            ]
        )
    else:
        # ステージ変数が500文字制限があるので、500文字で分割
        split_token_arr = [token[x:x+500] for x in range(0, len(token), 500)]
        patch_operations = [
            {
                'op': 'replace',
                'path': '/variables/' + value_name + "0",
                'value': split_token_arr[0]
            }
        ]
        if len(split_token_arr) > 1:
            patch_operations.append(
                {
                    'op': 'replace',
                    'path': '/variables/' + value_name + "1",
                    'value': split_token_arr[1]
                }
            )
        #  ステージ変数に値を格納
        response = apigw_client.update_stage(
            restApiId=apigw_id,
            stageName=apigw_stagevalue_key,
            patchOperations=patch_operations
        )
    # 終了
    return {
        'statusCode': 200,
        'body': token
    }
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?