Lambda 에 AWS API-Gateway 를 연결하여 Route53의 DNS Record 를 등록 삭제하는 API 만들기 (feat Python)

 뭐 이미 잘 아시는 분들이야 딱히 볼만한 내용은 없을것 같습니다. (당연한 소리인가요? )
(코드를 pre - code 로 해가가 넣었더니 민감 컨텐츠로 분류 되는듯 하여 스샷으로 넣을수 밖에 없었...)

개발팀 으로부터 요청이 들어왔습니다. 

웹 애플리 케이션에서 고객사채널이 오픈되면 서브도메인 등록과 IIS 사이트 바인딩까지 사람손 안거치고 되도록 해달라. 

사실 뭔지도 모를 도메인들이 막 생기면 나중에 관리가 안될것 같아서 도메인의 경우 인프라팀의 승인하에 등록 및 삭제를 하고 있었으나 막생긴다면 + 정책이 빨리처리하는게 우선! 이라고 하니.. 
그리고 개발자는 운영 서버에 직접 접근할 권한이 없기도 하기에 

젠킨스를 통해 구현 하려 했는데 이참에 API 로 만들어서 던져주고 나중에 젠킨스에서도 API 를 사용해야 겠다 라는 생각이 들었습니다. 

AWS 의 윈도우 이미지를 사용하는 EC2 의 경우 기본적으로 SSM 에이전트를 이용하는 람다를 통해 IIS 의 사이트 바인딩을 추가 제거 할수 있는 API 와 Route53 에 레코드를 추가 제거 할수 있는 API 를 만들었습니다. 

일단 도메인 레코드 추가삭제 API 를 기준으로 진행해보겠습니다. 

일단 람다 함수를 먼저 생성합니다. 

만만하고 람다 친화적? 인 파이썬님을 런타임 기본으로 잡고 이름을 정한뒤 기본실행 역할을 정합니다. 

동일한 그룹으로 묶을것들이 아니기 때문에 또 앞으로 어떻게 쓰게 될지 모르기 때문에 새 역할 생성을 선택합니다.

추가 구성에 네트워킹 관련 구성들이 있는데 
인프라가 Azure 와 AWS, 온프레미스로 여러곳에 있기도 해서 API 게이트웨이를 사용할 예정이기에 
추가구성은 하지 않습니다. 

만약 람다를 직접 호출 하려면 URL 활성화나 VPC 내에서 접근하려면 VPC활성화를 선택해 주시면 되겠죠? 


그럼 코드를 직접 입력 할수 있는 화면이 나옵니다 (현재 새로운 에디터인데 창 크기 조절도 안되고 뭔가 답답한 면이 있습니다. 오히려 저는 기존의 에디터가 더 좋은것 같네요)

요기서 에디터를 변경할 수 있습니다. 

순서는 사람들 마다 차이가 있긴한데 일단 route53 을 사용해야 하기 때문에 권한이 필요 합니다. 
람다 생성시 역할 생성을 자동으로 했다면 IAM 에 가서 역할에 람다함수 이름으로 검색해보시면 
이름-role-어쩌구 하는 정책이 생성되어 있습니다. 

선택하고 권한 정책 부분을 보면 람다 기본정책으로 로그 관련된 기능만 추가 되어있을것입니다. 


권한 추가를 선택하고 
정책 연결로 route53 관련 ChangeResourceRecordSets 이 존재하는 정책을 연결해도 되고
인라인 정책 생성을 통해 새로운 정책을 만들어서 연결 해도 됩니다. 
저는 만들어서 연결했습니다. 

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "route53:ChangeResourceRecordSets"
            ],
            "Resource": "*"
        }
    ]
}

이제 코드를 작성하거나 일단 API GateWay연결부터 해도 상관은 없습니다. 

API GateWay 를 연결하는데는 람다의 다이어그램에서 트리거 추가를 통해 하는 방법이 있고 
API GateWay 메뉴로 가서 생성후 연결하는 방법이 있습니다. 
저는 API Gateway 로 가서 생성하도록 하겠습니다. 
API 유형은 REST 로 선택하고


이름을 정하고 API 생성을 누릅니다.


새로 생성된 API 인데요  메서드가 아무것도 없습니다. 

POST 일때는 레코드 생성이나 수정, DELETE 일때는 레코드 삭제로 동작할 계획이기 때문에 POST 와 DELETE 메서드를 생성해 줍니다. 
인증은 IP 기반으로 할 계획이기 때문에 그냥단순하게 연결만 합니다. 

메서드 유형 POST 에 람다 함수 를 연결 선택하고 람다 프록시 통합을 켜줍니다 (그래야 요청처리 구조가 단준해집니다) 나머지는 그대로 두고 메서드를 생성합니다.
DELETE 역시 동일하게 생성합니다. 
두가지가 생성 되었습니다. 


이상태에서는 당연히 사용할수 없고 위의 배포를 해야 실제 사용할수 있습니다. (뭔가 수정해도 배포를 해야 적용이 됩니다 ) 
스테이지는 default 던 prod / dev 던 필요한 네이밍을 붙여서 배포를 합니다.



완전 처음 하시는 분들을 위한 보충 설명

좌측 메뉴 구성은 맨위의 API 에서 선택한 현재 선택된 API 의 설정 메뉴가 아래에 있는형태입니다. 은처음 보면 은근 눈에 안띄더라고요 


배포를 하고 나면 자동으로 스테이지 메뉴로 이동 되는데요. 

여기에서 이 API 의 URL 을 확인 할수 있습니다. 
루트에 있기 떄문에 스테이지의 주소 루트인 /default/ 가 URL 로 잡혀있는데요. 
리소스 메뉴에서 / 아래로 새로운 리소스를 생성하고 거기에 메서드를 만들면 

이런식으로 주소가 나오게 됩니다. 

여기에서 만약 API 주소를 자신이 가진 도메인에서 사용하고 싶다면 좌측 상단의 사용자 지정 도메인 이름 을 선택하시고 도메인을 연결하시면 됩니다. 

도메인 이름추가에 도메인을 하나 추가하고 (ex : api.domain.com ) ACM 의 인증서를 사용하도록 합니다.  등록한 도메인을 클릭해서 들어가면 하단에 API매핑 이라는 메뉴가 있습니다. 
여기에서 API 매핑 구성을 선택하고 새 매핑 추가를 누르시면 API 를 선택할수 있는 드롭박스가 나타납니다.
여기에서 매핑할 API / 스테이지를 선택합니다. 경로의 경우 입력하면 URL 의 주소가 경로 주소가 됩니다. 입력하지 않으면 api 의 이름이 사용됩니다. 

dnscontrol 로 경로를 지정해 보겠습니다.

이렇게 API Gateway 는 일단 구성했습니다.
그러면 접근 주소는 https://내도메인/dnscontrol  이 됩니다. 
다시 람다로 가서 새로 고침해보면 




트리거에 API 게이트웨이 가 연결되어 있는것을 볼수 있습니다. 
근데 POST 와 DELETE 두개인데 (3) 으로 표시되어있네요? 
네 아까 위에 리소스 설명을 위해 GET 을 임시로 만들었다가 지운것 때문에 없는 메서드 1 개가 포함되어있습니다. (생성은 자동이지만 삭제는 안해줍니다) 없어진 트리거는 선택후 삭제 처리 합니다. 

이제 람다 코드를 넣어야 겠죠? 
만만한게 파이썬이고 간단한게 파이썬이라서 사용하고 있습니다만 
아래는 boto3 를 이용해 route53 의 레코드를 제어하는 람다 코드샘플입니다.




주의할 점은
API 게이트웨이에서 REST 방식 으로 사용시엔 입력되는 json 값이 body 에 묶여서 들어옵니다.

예를 들어 POST 로 { "name":"park" , "Type":"human" } 을 API 게이트웨이에 보내면 실제 람다가 받는 정보는 
{
  "httpMethod": "POST",
  "body": "{\"name\": \"park\", \"Type\": \"human\"}"
}
이 됩니다.  그래서  파싱은 body 에서 해야 합니다. 
람다에서 테스트를 할때도 코드를 그렇게 짜놔야 하니 이벤트json 도 위 형태를 가져야 정상적으로 동작하겠죠?

원래는 모두 입력 받아서 하려고 했었는데 그러다보면 관리적인 면에서나  오류확률등이 있어서 코드별로 고정값을 사용하도록 (어차피 한서버에서 운용하는 애플리케이션이라) 했고
동일 도메인에 대해서 퍼블릭 호스티드 존과 프라이빗 호스티드존 두가지가 존재 하기 때문에 
ALB 를 거치는 경우와 내부 IP 를 사용하게 되는 경우를 반영하여  퍼블릭한번 프라이빗 한번 동작하도록 구성했습니다. 

등록 : [POST] 
{ "Code": "D01", "Name": "test.도메인." } 

삭제 : [DELETE] 
{ "Code": "D01", "Name": "test.도메인." }

로 사용합니다.

동작이 잘 되면 이제 보안을 위해 IP 제어를 합니다.
lambda 에는 엔드포인트가 없기 때문에 (URL 받지 않음) 람다는 API 게이트웨이를 통해서만 접속할수 있습니다. 그런 이유로 API 게이트웨이에서만 IP 제어를 하면 된다는 결론이죠. 

다시 API 게이트웨이로 가서 API 메뉴의 만든 API 를 클릭하고 좌측 메뉴에서 리소스 정책 을 선택합니다.
정책이 아무것도 없을텐데요. 여기에


{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "execute-api:Invoke",
      "Resource": "arn:aws:execute-api:ap-northeast-2:************:khy*****0h/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "아이피/32",
            "아이피/32"
          ]
        }
      }
    }
  ]
}

이런 식으로 입력합니다. 
그럼 해당 IP 외에는 접근이 제한 됩니다. 
arn 은 리소스에 메서드 아무거나 눌러보시면 볼수 있습니다. 
특정 메서드만 제한을 하려면 
      "Resource": "arn:aws:execute-api:ap-northeast-2:************:khy*****0h/*/DELETE",
이런식으로 메서드까지 적어주면 됩니다.


소스 코드에 넣지 않고 람다 함수의 변수에 데이터를 넣고 쓰는 방법도 있습니다만 특별한 비밀 정보도 아닌지라.. 

여튼 도움되시는 분이 있길 바랍니다. 

댓글

이 블로그의 인기 게시물

비만 오면 C103 통신에러 걸리는 삼성 무풍 에어컨

CT6 겉벨트를 갈아 봅시다. | Cadillac CT6 serpentine belt replacement

CT6 고스트도어(소프트 클로징) 장착 | Installing Soft-Close Doors (Ghost Doors) on a Cadillac CT6