#AWS Certified Developer Associate
350. API Gateway CORS 및 실습
api gateway는 교차 오리진 리소스 공유 브라우저 보안을 제공함
다른 도메인으로부터 오는 api 호출을 받으려면 CORS 를 꼭 활성화 해야 함
사전 요청 옵션 생성 - CORS 헤더 포함
- Access-Control-Allow-Methods
- Access-Control-Allow-Headers
- Access-Control-Allow-Origin
위 메서드들은 콘솔에서 설정 가능함
CORS - Enable on the API Gateway
s3 버킷의 정적 웹 호스팅된 브라우저에서 api cross origin 의 api 결과를 가져올때
사전 요청 옵션을 확인하고 사전 응답을 웹으로 보냄
이후 웹브라우저와 api 간 소통이 가능하게 됨
실습
먼저 api gateway 와 같은 리전에 웹 호스팅용 s3버킷을 하나 만들어줄꺼다
이름은 yeonwoo-demo-cors-apigateway 로 하고 퍼블릭 액세스 차단을 비활성화 해주고 생성
생성된 버킷의 속성탭에서 정적 웹사이트 호스팅을 활성화해주고 인덱스 문서에 index.html 을 넣고 저장
정책 생성기에서 버킷ARN/* 에 대해 getobject 에 모든 접근을 허용하는 정책 생성 후 버킷에 적용
<html>
<head>
<title>CORS Demo API Gateway</title>
</head>
<body>
<h1>Making a CORS request to API Gateway...</h1>
<div id="tofetch"/>
</body>
<!-- CORS demo -->
<script>
var tofetch = document.getElementById("tofetch");
fetch('https://u2j6yb9crh.execute-api.ap-northeast-1.amazonaws.com/prod/houses')
.then((response) => {
return response.text();
})
.then((html) => {
tofetch.innerHTML = html
});
</script>
</html>
위 index.html 을 만들어서 버킷에 업로드할껀데
아래 script 는 api gateway 에서 fetch 한 내용을 가져오는 코드라고 한다
api gateway 로 가서 prod 의 houses 리소스의 get 메서드의 url 을 복사해서 위에 fetch 함수 안에 넣어준다
버킷에 index.html 을 업로드 해주고 버킷 웹 호스팅 엔드포인트로 들어가보면
위처럼 결과가 반환되지 않는다
아래 get 메서드 url 에서 확인할 수 있듯이 메서드는 정상작동중이다
오른쪽의 개발자 콘솔에서 보면 access to fetch 링크 from origin 이라고 나오는데 이후
has been blocked by CORS policy 라고 한다
요청 응답에 'Access-Control-Allow-Origin' 이라는 헤더가 없다고 한다
CORS 를 활성화 해줄꺼다
api 콘솔의 리소스로 들어가서 해당 리소스의 cors 를 활성화해준다
여러 옵션들이 있는데
맨 아래 Access-Control-Allow-Origin 에 별표만 남겨놓으면 모든 도메인에 작동하게 된다
버킷 앤드포인트로 바꿔주고 활성화하면
이렇게 했는데 프록시가 활성화된 api 에서는 작동이 안된다고 한다
이전에 만들었던 mapping 리소스는 프록시가 아니니까 여기다가 CORS 를 활성화 한 후 배포하고 index.html 에 url 을 넣은 뒤 버킷에 업로드하면 된다고 한다
(해봤는데 안됨;;)
아니면
요청이 람다 프록시로 넘어가는 api 의 람다 함수에 헤더를 포함시켜서
import json
def lambda_handler(event, context):
#print(event)
body = "Hello from yuniyuniya"
statusCode = 200
return {
"statusCode": statusCode,
"body": json.dumps(body),
"headers": {
"Content-Type": "application/json",
"Access-Control-Allow-Origin" : "*"
}
}
위 예시처럼 실행하게 되면
이렇게 정상 응답을 확인할 수 있다
351. API Gateway 인증 및 권한 부여
IAM Permissions
iam 정책을 사용해서 사용자에게 역할을 연결하고 api gateway 를 호출 할 수 있다
이 경우 인증은 iam 을 통해 진행되고 권한 부여는 iam 정책에 의해 진행 됨
aws 계정을 통해 액세스 하는 경우 최적의 보안 환경
api gateway 로 iam 자격 증명을 통과하려면 sig v4 기능을 활용해 iam 자격 증명에 서명되고 해더로 배치됨
Resource Policies
위 과정은 리소스 정책들과 결합될 수 있음 (람다 리소스 정책과 유사함)
api gateway 에 액세스 할 수 있는 대상을 정의함
리소스 정책의 주된 use cases 는 Cross Account Access (교차 계정 액세스) 사용임
리소스 정책을 특정 IP 주소를 필터링하는 데 사용하거나 VPC 엔드포인트만 허용하는 작업에도 사용 가능
Cognito User Pools
cognito 는 큰 틀에서 보면 user db 볼 수 있음
user 의 수명 주기 관리, 토큰 연결은 자동 만료
api gateway 는 cognito 를 통해 api 에 연결한 사람들의 신분을 검증하게 됨
사용자 지정 구현이 필요 없음
유저들은 cognito 사용자 풀을 통해 인증 - 인증은 api gateway 의 method 레벨에서 설정됨
Lambda Authorizer (람다 권한 부여자)
이전에는 Custom Authorizers (사용자 지정 권한 부여자) 라고 불렀다고 함
가장 유연하면서도 엔드에 가장 많은 개입을 요구함
베어러 토큰(bearer token) 을 이용하는 토큰 기반 권한 부여자 (JSON 웹 토큰인 JWT 나 Oauth 와 비슷함)
요청 기반 매개변수를 헤더나 쿼리 문자열을 통해 람다 권한 부여자로 통과시키게 됨
람다 함수는 전달된 내용을 평가한 뒤에 유효한 내용인 경우, 요청을 보낸 클라이언트에게 IAM 정책을 반환하고 정책은 캐시됨
인증은 외부에서 이루어지고 권한 부여는 람다 함수에서 진행됨
실습
api 의 아무 메소드에 들어가서 메서드 요청에 들어가서
iam 인증에 대해 활성화 할 수 있다
리소스 정책에서 리소스 제어를 구성할 수 있는데
위 예제 코드는 aws 교차 계정 액세스에 대한 정책이고 예제 코드에 ip 필터나 vpc 화이트리스트 예제도 확인할 수 있다
api 콘솔의 왼쪽 메뉴에 보면 authorizers (권한 부여자) 에 들어가보면
사용자 설정 권한 부여자로 람다 함수를 통해 인증을 할 수도 있고
cognito arn 만을 이용해서 인증과 권한부여를 진행할 수도 있다
코딩이 필요없이 간단해서 많이 선호된다고 한다
(2.22 끝)
(2.26 시작)
352. API Gateway - REST API vs HTTP API
HTTP API
지연 시간이 짧고 비용이 적게 드는 AWS 람다 프록시 이다.
HTTP 프록시 API 와 사설 통합(private integration)임
가능한 데이터 매핑이 없음
특정 권한 부여만을 지원 (OIDC, OAuth 2.0) (CORS 에 대한 자체 지원 있음 - 사용량 설정이나 api 키는 없음)
REST API
openID connect 와 OAuth 2.0 을 제외한 모든 기능 탑재
353. API Gateway - WebSocket API
WebSocket :
사용자 브라우저와 서버 사이에 양방향 상호작용
클라이언트가 요청하지 않아도 서버가 클라이언트에게 정보를 다시 보낼 수 있음
상태 유지(stateful) 애플리케이션에서 사용 가능
websocket api 는 실시간 애플리케이션에서 활용
- 채팅 애플리케이션, 협업 프로그램, 멀티플레이어게임, 금융 거래 플랫폼 등
백앤드에 있는 모든 종류의 API Gateway 작업이 가능 (lambda, dynamoDB, http endpoint 등)
Connecting to the API
wss 로 시작하는 암호화된 WebSocket URL
wss://[고유-ID].execute-api.[리전].amazonaws.com/[스테이지-이름] 의 형식을 가짐
1. 클라이언트가 websocket api gateway 에 연결
2. 위를 통해 지속적 연결을 설정 - 람다 함수 호출 - connectionId 수행
- connectionId : 클라이언트가 api gateway 에 연결된 상태인 이상 그대로 유지됨
3. connectionId 는 Amazon DynamoDB 등에 사용자와 관련된 메타데이터를 저장
Client to Server Messaging - ConnectionID is re-used
1. websocket api 를 통해 지속적 연결로 메세지를 보내는데 이와 같은 메세지를 프레임이라고 함
2. 프레임이 새로운 람다 함수를 호출 - connectionId 는 동일
3. 람다 함수가 DynamoDB 와 통신하여 해당 connectionId 를 기반으로 사용자 정보 검색 및 원하는 작업 수행
따라서 클라이언트가 WebSocket API 의 API Gateway 를 통해 더 많은 메세지를 보낼수록 동일한 연결을 통해 더 많은 프레임을 보내게 되는 것
- connectionID 는 변경될 일 없이 람다 함수가 호출될때마다 재사용할 수 있음
Server to Client Messaging
1. API Gateway 가 있을때, 연결 URL 콜백(Connection URL callback)이 수행됨
- 연결 URL 은 기존 url 에서 /@connections/connectionid 가 더 추가됨
- 람다 함수 등이 IAM Sig v4 를 이용해서 서명된 HTTP 포스트에 클라이언트 connectionId 를 지정하면 이와 같은 연결 URL 콜백이 생성됨
2. 이를 통해 api gateway 에서 클라이언트로 다시 메세지를 전송함
Connection URL Operations
POST - 서버에 연결된 WebSocket 클라이언트에 메세지를 다시 보낼 수 있음
GET - 연결된 WebSocket 클라이언트의 최신 연결 상태를 가져옴
DELETE - WebSocket 연결에서 클라이언트의 연결을 끊을 수 있음
WebSocket API - Routing
websocket routing - 클라이언트가 어떻게 호출할 람다함수나 백엔드를 알 수 있는지
수신되는 JSON 메세지는 다른 백엔드로 라우팅됨
라우트를 따로 지정해놓지 않으면 기본 라우트로 이동함
라우팅은 라우팅 표현식을 기반으로 특정 백엔드에 라우팅 할 수 있는지를 확인할 때 쓰임
연결은 이미 열려있는 상태임 - 라우팅이 수신하는 데이터 메세지의 일부여야 하기 때문
라우트 선택 표현식 (route selection expression) 을 생성해서 라우팅할 JSON 필드를 선택할 수 있음
수신 데이터에 route 정의
api gateway 레벨에 정의하는 route key table
- 필수 라우트 : $connect, $disconnect, $default 정
- (예시) 고객 라우트 : $join, $quit, $delete 등 정의
api gateway 에 대한 샘플 표현식을 $request.body.action 으로 지정
위 표현식으로 api gateway 에서 사용할 수 있는 route key table 을 평가하는 것
354. API Gateway - WebSocket API 실습
먼저 람다 함수를 만들어 준다고 함
기존 함수와 다르게 서버리스 애플리케이션을 생성해줄껀데
사용자 지정 iam 역할 또는 리소스 정책을 생성하는 앱 표시를 체크해주고
websocket 을 검색하면 나오는 심플 챗 앱을 선택해준다
onConnect, onDisconnect, sendMessage 람다 함수가 생성되고
애플리케이션 이름, 테이블 이름과 각 클라이언트의 연결 식별자를 저장할 dynamoDB 의 이름도 설정할 수 있다
배포해주고 조금 기다려 준다고 함
백엔드에 배포되면 cloudformation 탬플릿을 사용
api gateway 를 배포하기 위해 websocket 과 다른 여러 함수가 쓰인다고 함
애플리케이션 생성이 완료되면 이렇게 리소스 목록이 나오는데
dynamoDB 테이블은 옆에 띄워놓고
나중에 OnCennectFunction 을 조금 수정해본다고 함
api gateway 콘솔로 이동
경로 선택 표현식이라고 나와있는데 라우팅 선택 표현식이다
작업 키를 포함하고 있는 JSON 을 지정해야 한다
각 route 경 에 맞는 람다 함수가 연결되어있다
이제 websocket api 를 테스트 해본다고 함
cloudshell 로 이동
wscat 이라는 websocket api 테스트용 프로그램을 설치한다고 함
npm 으로 wscat 을 설치해준 후 prod stage 에서 websocket url 을 가져와서 커넥팅 해본다고 함
[cloudshell-user@ip-10-2-12-48 ~]$ sudo npm install -g wscat
added 9 packages, and audited 10 packages in 3s
found 0 vulnerabilities
npm notice
npm notice New major version of npm available! 8.19.2 -> 9.5.1
npm notice Changelog: https://github.com/npm/cli/releases/tag/v9.5.1
npm notice Run npm install -g npm@9.5.1 to update!
npm notice
[cloudshell-user@ip-10-2-12-48 ~]$ wscat -c wss://rwdio4xhq7.execute-api.ap-northeast-1.amazonaws.com/Prod
Connected (press CTRL+C to quit)
>
-c 옵션을 통해 url 로 접속하게 되면
바로 websocket api 에 연결됨
- wscat 명령어를 통해 OnCennect 라는 람다 함수로 이동해서 실행된 것
- OnCennect 함수가 실행되면 DynamoDB 테이블로 이동해서 connectionId 가 생성
위 id 는 cloudshell 이 활성화되어있는 동안 지속적으로 유지된다고 함
ctrl + c 를 눌러 중단하면 OnDisconnect 함수가 실행됨
[cloudshell-user@ip-10-2-12-48 ~]$ wscat -c wss://rwdio4xhq7.execute-api.ap-northeast-1.amazonaws.com/Prod
Connected (press CTRL+C to quit)
> [cloudshell-user@ip-10-2-12-48 ~]$
OnDisconnect 함수가 실행되면 dynamoDB 의 connectionId 는 삭제됨
dynamoDB 테이블 상에는 websocket api 상에 열려있는 모든 연결 목록이 표시됨
다시 wscat 으로 websocket api 에 연결해서 메세지를 보내본다고 함
action 이라는 json 메세지를 열어야 하는데
아래 json 형식으로 action json 해주면 api gateway 에서 라우트 표현식을 쓸 수 있다고 함
data 에 대충 문자열을 넣고 전송하면
> [cloudshell-user@ip-10-2-12-48 ~]$ wscat -c wss://rwdio4xhq7.execute-api.ap-northeast-1.amazonaws.com/Prod
Connected (press CTRL+C to quit)
> { "action" : "sendmessage", "data" : "hello world!" }
< hello world!
>
람다함수에서 해당 메세지가 전송된 것을 볼 수 있다
더 정확한 동작 확인을 위해 cloudshell 을 하나 더 열어준다
기존 wscat 명령으로 websocket api 에 접속해주고
dynamoDB table 을 확인해보면 이제 connectionId 가 2개가 된 것을 확인할 수 있다
왼쪽 쉘에서 이전과 같이 json action 으로 sendmessage 에 data 로 문자열을 담아 보내면
오른쪽 화면에서도 이를 확인할 수 있다
서버가 우측에 있는 클라이언트에게도 데이터를 푸시한 것
세번째 창을 열고 wscat 으로 websocket api 에 접속해준 다음 똑같이 메세지를 서버로 보내보면
다른 클라이언트에게도 모두 동일하게 서버에서 메세지를 푸시해주는 것을 확인할 수 있다
실습 정리
스택 삭제
355. API Gateway - Architecture
api gateway 로 실행할 수 있는 마이크로 서비스 아키텍처
API Gateway 덕분에 회사의 마이크로 서비스를 모두 단일 인터페이스에서 표시할 수 있음
백엔드 내 여러 리소스와 함께 API endpoint 를 사용할 수 있음
- 클라이언트로부터 모든 복잡성을 숨길 수 있음
모든 방법을 통해서 하위 라우트를 정의하고 위와 같은 서비스에 연결하도록 단일 URL 을 사용하는 api gateway 를 사용
route53 을 이용해 도메인을 등록+분리 할 수 있음
- 위 도메인을 기반으로 SSL 인증서를 적용할 수 있음
API Gateway 내에서 포워딩 및 트랜스포메이션 규칙을 적용하여 백엔드에 전송하기 전 수신 데이터를 수정할 수도 있음
마이크로 서비스를 통합하고 외부 통합 URL 을 제공하는 것이 api gateway 활용 목적
라우팅 서비스와 데이터 변환, SSL 인증서 지정 등 복잡한 면은 모두 클라이언트가 볼 수 없도록 숨김
위 작업들은 모두 api gateway level 에서 작업할 수 있음
'AWS > AWS Certified Developer Associate' 카테고리의 다른 글
[Udemy][day-58] Section24 : AWS SAM - 2 (0) | 2023.02.28 |
---|---|
[Udemy][day-57,58] Section24 : AWS SAM - 1 (0) | 2023.02.26 |
[Udemy][day-55] Section23 : AWS 서버리스 : API Gateway - 2 (0) | 2023.02.21 |
[Udemy][day-54,55] Section23 : AWS 서버리스 : API Gateway (0) | 2023.02.15 |
[Udemy][day-53] Section22 : AWS 서버리스 : DynamoDB - 3 (0) | 2023.02.13 |