전의 게시물에 이어서 먼저 api gateway authorizer에 들어가는 람다 함수를 만들겠습니다.
resource "aws_lambda_function" "terraform_lambda_func" {
s3_bucket = "terraform-state-saving"
s3_key = "authorizer.zip"
function_name = "JWTAuthorizer"
role = aws_iam_role.lambda_role.arn
handler = "index.lambda_handler"
runtime = "nodejs16.x"
depends_on = [aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role]
}
function_name - (Required) Unique name for your Lambda Function.
role - (Required) Amazon Resource Name (ARN) of the function's execution role. The role provides the function's identity and access to AWS services and resources.
handler - (Optional) Function entrypoint in your code.
s3_bucket - (Optional) S3 bucket location containing the function's deployment package. This bucket must reside in the same AWS region where you are creating the Lambda function. Exactly one of filename, image_uri, or s3_bucket must be specified. When s3_bucket is set, s3_key is required.
s3_key - (Optional) S3 key of an object containing the function's deployment package. When s3_bucket is set, s3_key is required.
저는 이런식으로 미리 nodejs파일을 s3에 올려놓았고 그 s3파일을 이용해 람다함수를 만드는 테라폼 코드를 작성하였습니다.
제 nodejs함수는
// index.js
const jwt = require('jsonwebtoken');
const secretKey = '${var.secrets}';
module.exports.handler = async (event,context, callback) => {
console.log(event);
const {awsRequestId} = context;
let {authorizationToken, methodArn} = event;
authorizationToken = authorizationToken.split(' ')[1];
try{
const token = jwt.verify(authorizationToken, secretKey);
console.log("token : ",token);
const username = token.username;
return generateAllow(awsRequestId, methodArn, username);
}catch(err){
if(err.name === 'TokenExpiredError'){
console.log("TokenExpiredError");
callback("Unauthorized");
} else if(err.name === 'JsonWebTokenError'){
console.log("JsonWebTokenError");
console.log("JsonWebTokenError:", err.message);
console.log("Stack trace:", err.stack); // Log
return generateDeny(awsRequestId, methodArn);
}
}
};
const generateAllow = (principalId, methodArn, username) => {
console.log("Allow")
return generatePolicy(principalId, 'Allow', methodArn, username);
};
const generateDeny = (principalId, methodArn) => {
console.log(`[auth.js] deny. principalId: ${principalId}, resource: ${methodArn}`);
return generatePolicy(principalId, 'Deny', methodArn);
};
const generatePolicy = (principalId, effect, methodArn, username) => {
const authResponse = {principalId};
if (effect && methodArn) {
const policyDocument = {
Version: '2012-10-17',
Statement: [{
Action: 'execute-api:Invoke',
Effect: effect,
Resource: methodArn
}]
};
authResponse.policyDocument = policyDocument;
}
console.log(authResponse);
return authResponse;
}
이런식으로 jwt token이 만료가 되었는지 확인하는 코드였습니다.
(아직 완성은 못함..)
이런 람다 함수를 작성해놓고
resource "aws_api_gateway_authorizer" "demo" {
name = "authorizer"
rest_api_id = aws_api_gateway_rest_api.meme_gateway.id
authorizer_uri = aws_lambda_function.terraform_lambda_func.invoke_arn
authorizer_credentials = aws_iam_role.invocation_role.arn
}
이 authorizer에서 uri를 이 람다를 가리키게 하였습니다.
위의 api gateway를 위한 iam role과 policy도 작성하였습니다
resource "aws_iam_role" "invocation_role" {
name = "api_gateway_auth_invocation"
path = "/"
assume_role_policy = data.aws_iam_policy_document.invocation_assume_role.json
}
data "aws_iam_policy_document" "invocation_assume_role" {
statement {
effect = "Allow"
principals {
type = "Service"
identifiers = ["apigateway.amazonaws.com"]
}
actions = ["sts:AssumeRole"]
}
}
실제 적용은 Method 부분에서 하였습니다
resource "aws_api_gateway_method" "api_auth_proxy" {
rest_api_id = aws_api_gateway_rest_api.meme_gateway.id
resource_id = aws_api_gateway_resource.auth_proxy.id
http_method = "ANY"
authorization = "JWT"
authorizer_id = aws_api_gateway_authorizer.demo.id
request_parameters = {
"method.request.path.proxy" = true
}
}
이런식으로 authorization과 authorizer_id를 활용하였습니다.