[Terraform] 5. Spring Project AWS Terraform으로 띄우기 - (Authorizer, Lambda)

Sunwu Park·2024년 2월 22일
0

Cloud & CI/CD

목록 보기
13/17

전의 게시물에 이어서 먼저 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를 활용하였습니다.

0개의 댓글

관련 채용 정보