[AWS] Api Gateway (2)

곽진호·2023년 3월 17일
0

AWS[ApiGateway]

목록 보기
2/3

이전글에 이어서 오늘은 보안 api key 인증방법에 대해서 알아보자

먼저 api gateway를 통한 auth 인증에는 두가지가 있다.

  1. api gateway 안에있는 기능(API Keys) 사용하여 API key 사용여부를 설정하는 방법
  2. lambda를 통한 인증방법

오늘은 위의 두가지를 연습해보자

[1]먼저 API Keys를 사용한 인증방법

  1. API keys 생성
  2. 사용량 계획 생성
  3. gateway 배포
  4. 테스트

순서로 진행을 해보겠다.

1.API keys 생성

내가 생성한 gateway안에 API keys -> Actions 버튼안에 create Api key를 클릭하면 우측빨간 박스처럼 생성된다.
Auto generate 는 자동으로 키가 생성되고, custom은 내가 생성하는 키 이다.
생성을 맞췄으면 save를 눌러주자

2.사용량 계획 생성


Throttling,Quota는 최대 API요청수를 제한하는것이다. 나는 단순 테스트 이기 때문에 둘다 체크하지 않고 다음으로 진행하겠다.

사용량 계획이 만들어졌다면, 배포했던 Stage를 이 사용량 계획에 추가해줘야한다.

또한 Api Keys에 내가 만든 Key 이름을 적어준다.

이렇게 하면 자동으로 내가 생성한 Api key에 연결이 된다.

3.gateway 배포

이제 key 사용여부 변경후 배포하기 위해 resource 에 들어간다.


아래처럼 false -> True 로 변경해준다.

이제 다시 배포한다.

4.테스트

나는 api requests 테스트를 하기위해 postman을 사용한다.

위의 key부분이 비활성화 되어있으므로 지금 현재 message가 forbidden으로 리턴되고있다.

아까 생성했던 API keys에 key값을 넣고 다시한번 요청을 보내보자

해당 값을 넣고 보내면 성공하는 것을 확인할 수 있다.

만약 여러 서비스합쳐서 운영하는 곳이라면 여러개의 api key 를 같은 Api Gateway에 추가하여 서비스를 막거나, 추가로 연결해주거나 할 수 있을것 같다.

여러개의 api key를 추가하는 방법은 사용량 계획에 추가했던 방식을 여러번 반복하면 된다.

[2]lambda를 통한 인증방법

이건 사실 나도 정확한 방법인지는 잘 모르겠지만, 람다를 통해 내가 코드로써 인증 및 여러가지를 커스텀 할 수 있다는것이 장점인것같다. 람다를 사용하는것도 매우 좋은 경험이라 시도해봤다.

1.lambda 생성 및 lambda 코드 작성
2.Api gateway 연결
3.Resource 수정 및 배포
3.테스트

1.lambda 생성 및 lambda 코드 작성


이미 내가 한번 만든 이름이라 중복확인이 뜨는것이니 무시하셔도 된다.

이렇게 코드를 작성해본다.

아! 코드를 다 작성한 이후에는 Test옆에있는 Deploy를 눌러 꼭 배포해주도록하자 그렇지않으면 저장된 코드로 람다가 실행되지 않는다


// A simple token-based authorizer example to demonstrate how to use an authorization token 
// to allow or deny a request. In this example, the caller named 'user' is allowed to invoke 
// a request if the client-supplied token value is 'allow'. The caller is not allowed to invoke 
// the request if the token value is 'deny'. If the token value is 'unauthorized' or an empty
// string, the authorizer function returns an HTTP 401 status code. For any other token value, 
// the authorizer returns an HTTP 500 status code. 
// Note that token values are case-sensitive.

exports.handler =  function(event, context, callback) {
    console.log(event)
    console.log()
    var token = event.authorizationToken;
    switch (token) {
        case 'zlO0zj2evv9kBA7Bi3zxC6swfQNB2TsKZtvuA4Nj':
            callback(null, generatePolicy('user', 'Allow', event.methodArn));
            break;
        case 'deny':
            callback(null, generatePolicy('user', 'Deny', event.methodArn));
            break;
        case 'unauthorized':
            callback("Unauthorized");   // Return a 401 Unauthorized response
            break;
        default:
            callback("Error: Invalid token"); // Return a 500 Invalid token response
    }
};

// Help function to generate an IAM policy
var generatePolicy = function(principalId, effect, resource) {
    var authResponse = {};
    
    authResponse.principalId = principalId;
    if (effect && resource) {
        var policyDocument = {};
        policyDocument.Version = '2012-10-17'; 
        policyDocument.Statement = [];
        var statementOne = {};
        statementOne.Action = 'execute-api:Invoke'; 
        statementOne.Effect = effect;
        statementOne.Resource = resource;
        policyDocument.Statement[0] = statementOne;
        authResponse.policyDocument = policyDocument;
    }
    
    // Optional output with custom properties of the String, Number or Boolean type.
    authResponse.context = {
        "stringKey": "tmp",
        "numberKey": 123,
        "booleanKey": true
    };
    return authResponse;
}

코드에 case zlO0zj2evv9kBA7Bi3zxC6swfQNB2TsKZtvuA4Nj 에 내가 저번시간에 만들었던 키를 그대로 사용하도록하겠다. 마음대로 변경해도 상관없다.

최종 코드


exports.handler =  function(event, context, callback) {
    var token = event.authorizationToken;
    switch (token) {
        case 'zlO0zj2evv9kBA7Bi3zxC6swfQNB2TsKZtvuA4Nj':
            callback(null, generatePolicy('user', 'Allow', event.methodArn));
            break;
        default:
            callback("Error: Invalid token"); // Return a 500 Invalid token response
    }
};

// Help function to generate an IAM policy
var generatePolicy = function(principalId, effect, resource) {
    var authResponse = {};
    
    authResponse.principalId = principalId;
    if (effect && resource) {
        var policyDocument = {};
        policyDocument.Version = '2012-10-17'; 
        policyDocument.Statement = [];
        var statementOne = {};
        statementOne.Action = 'execute-api:Invoke'; 
        statementOne.Effect = effect;
        statementOne.Resource = resource;
        policyDocument.Statement[0] = statementOne;
        authResponse.policyDocument = policyDocument;
    }

    return authResponse;
}

필요없는 주석 및 사용하지 않는 함수 조건등을 삭제하여 간단하게 적용했다.

위의 코드 및 (Token, request)에 대한 설명은 AWS 안내서에 설명되어있다.
https://docs.aws.amazon.com/ko_kr/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html


이미 내가 트리거를 만들어서 API Gateway가 추가되어있지만 없다고 가정하고 추가를 해보자

Existing Api 에서 내가 만든 Api gateway를 선택하고, 배포 stage를 선택한다
security 도 IAM role을 따른다.

이렇게 트리거를 만들지않으면 API gateway로부터 요청을 받아낼수가 없다.

2.Api gateway 연결

lambda를 다 만들었다면, 이제 다시 Api Gateway쪽으로 돌아오자

Authorization Caching은 enabled 에 체크를 해제하자, 뭐때문인지, 체크를하면 요청이 연속적으로 들어가지 않는다.

Lamdba Function 에 내가 만든 lambda를 연결해주자

그리고 Event Payload에는 두가지 방법이있는데 Token으로 인증할것이냐, Requsts요청방법으로 인증할것이냐로 나뉜다,
두개의 설명은 위에 링크해놓은 AWS공식 문서에 나와있다.
url path나 더 여러가지의 Querystring 등등으로 사용하여 key값을 다르게 설정하고싶다면, request방법을 써서 custom하는게 더 효과적인것 같다.

위처럼 설정하고 create를 눌러 생성해보자


위처럼 Test를 할텐데
내가 저장한 키로 요청을 보냈을때

다른 키로 요청을 보냈을 때

아무것도 보내지않았을때

정상적으로 결과가 리턴되는것을 볼수있다.

3.Resource 수정 및 배포

이제 Resource로 들어가서 Key 조건을 걸고 싶은 method로 들어가자

위처럼 변경해주자 새롭게 생성한 Authorizers이 보이면 클릭해주면된다, 만약 보이지않을경우, AWS콘솔을 다시 키거나 새로고침하면 보이니까 참고하자

기존에 사용하던 Stage에 배포를 쌓아주자

4.테스트

postman을 사용하여 요청을 보내보면 정상적으로 작동하는것을 확인할 수 있다

다음시간엔 서버를 로드밸런서에 연결해 vpc link를 사용하여 방화벽 및 보안에 더 신경쓴 작업을 하겠다.

작업간 내용 확인 할 것

  1. Lambda의 코드를 수정하고 나선 무조건 Deploy를 눌러서 배포해주기
  2. Api Gateway 작업을 수정하고나선 무조건 Deploy를 눌러 배포하기
  3. 혹시 Api Gateway작업을 수정 하고 배포도[Stage를 새롭게 만들었을경우] 했는데 도메인에 연결이안된다면 Custom Domain Names쪽에서 Api mapping 수정해주기!
  4. 그래도 안된다면, Auth 쪽에서 무언가 실수가있었는지 테스트를 꼼꼼하게 해보기
    람다에서 Cloud watch로 로그를 볼수있으니까 활용해보기

혹시 추가 질문사항이나 안되는것이 있다면 알려주세요... 저도 처음이라..

profile
진짜 호랭이

0개의 댓글