공부하기싫어
article thumbnail

#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 을 업로드 해주고 버킷 웹 호스팅 엔드포인트로 들어가보면

 

url

위처럼 결과가 반환되지 않는다

아래 get 메서드 url 에서 확인할 수 있듯이 메서드는 정상작동중이다

오른쪽의 개발자 콘솔에서 보면 access to fetch 링크 from origin 이라고 나오는데 이후

has been blocked by CORS policy 라고 한다

요청 응답에 'Access-Control-Allow-Origin' 이라는 헤더가 없다고 한다

 

CORS 를 활성화 해줄꺼다

api 콘솔의 리소스로 들어가서 해당 리소스의 cors 를 활성화해준다

 

CORS 활성화

 

 

여러 옵션들이 있는데

맨 아래 Access-Control-Allow-Origin 에 별표만 남겨놓으면 모든 도메인에 작동하게 된다

버킷 앤드포인트로 바꿔주고 활성화하면

 

CORS 활성화
변경 사항 확인

 

이렇게 했는데 프록시가 활성화된 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 (권한 부여자) 에 들어가보면

Custom Authorizers

사용자 설정 권한 부여자로 람다 함수를 통해 인증을 할 수도 있고

 

Cognito User Pools

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) 애플리케이션에서 사용 가능

 

chat application

websocket api 는 실시간 애플리케이션에서 활용

- 채팅 애플리케이션, 협업 프로그램, 멀티플레이어게임, 금융 거래 플랫폼 등 

백앤드에 있는 모든 종류의 API Gateway 작업이 가능 (lambda, dynamoDB, http endpoint 등)

 

Connecting to the API

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

client to server messaging

1. websocket api 를 통해 지속적 연결로 메세지를 보내는데 이와 같은 메세지를 프레임이라고 함

2. 프레임이 새로운 람다 함수를 호출 - connectionId 는 동일

3. 람다 함수가 DynamoDB 와 통신하여 해당 connectionId 를 기반으로 사용자 정보 검색 및 원하는 작업 수행

 

따라서 클라이언트가 WebSocket API 의 API Gateway 를 통해 더 많은 메세지를 보낼수록 동일한 연결을 통해 더 많은 프레임을 보내게 되는 것

- connectionID 는 변경될 일 없이 람다 함수가 호출될때마다 재사용할 수 있음

 

Server to Client Messaging

server to client messaing

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 실습

먼저 람다 함수를 만들어 준다고 함

기존 함수와 다르게 서버리스 애플리케이션을 생성해줄껀데

 

simple-websockets-chat-app

사용자 지정 iam 역할 또는 리소스 정책을 생성하는 앱 표시를 체크해주고

websocket 을 검색하면 나오는 심플 챗 앱을 선택해준다

 

onConnect, onDisconnect, sendMessage 람다 함수가 생성되고

애플리케이션 이름, 테이블 이름과 각 클라이언트의 연결 식별자를 저장할 dynamoDB 의 이름도 설정할 수 있다

배포해주고 조금 기다려 준다고 함

 

백엔드에 배포되면 cloudformation 탬플릿을 사용

api gateway 를 배포하기 위해 websocket 과 다른 여러 함수가 쓰인다고 함

 

리소스

애플리케이션 생성이 완료되면 이렇게 리소스 목록이 나오는데

dynamoDB 테이블은 옆에 띄워놓고

나중에 OnCennectFunction 을 조금 수정해본다고 함

 

api gateway 콘솔로 이동

route selection expression

경로 선택 표현식이라고 나와있는데 라우팅 선택 표현식이다

작업 키를 포함하고 있는 JSON 을 지정해야 한다

각 route 경 에 맞는 람다 함수가 연결되어있다

 

이제 websocket api 를 테스트 해본다고 함

cloudshell 로 이동

wscat 이라는 websocket api 테스트용 프로그램을 설치한다고 함

 

npm 으로 wscat 을 설치해준 후 prod stage 에서 websocket url 을 가져와서 커넥팅 해본다고 함

prod stage

[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 가 생성

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 ~]$

connectionId

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

 

더 정확한 동작 확인을 위해 cloudshell 을 하나 더 열어준다

cloudshell
dynamoDB connectionId

기존 wscat 명령으로 websocket api 에 접속해주고

dynamoDB table 을 확인해보면 이제 connectionId 가 2개가 된 것을 확인할 수 있다

 

server to client

왼쪽 쉘에서 이전과 같이 json action 으로 sendmessage 에 data 로 문자열을 담아 보내면

오른쪽 화면에서도 이를 확인할 수 있다

서버가 우측에 있는 클라이언트에게도 데이터를 푸시한 것

 

세번째 창을 열고 wscat 으로 websocket api 에 접속해준 다음 똑같이 메세지를 서버로 보내보면

다른 클라이언트에게도 모두 동일하게 서버에서 메세지를 푸시해주는 것을 확인할 수 있다

 

실습 정리

cloudformation

스택 삭제

 

 

 

355. API Gateway - Architecture

api gateway 로 실행할 수 있는 마이크로 서비스 아키텍처

 

API Gateway 덕분에 회사의 마이크로 서비스를 모두 단일 인터페이스에서 표시할 수 있음

백엔드 내 여러 리소스와 함께 API endpoint 를 사용할 수 있음

- 클라이언트로부터 모든 복잡성을 숨길 수 있음

 

모든 방법을 통해서 하위 라우트를 정의하고 위와 같은 서비스에 연결하도록 단일 URL 을 사용하는 api gateway 를 사용

route53 을 이용해 도메인을 등록+분리 할 수 있음

- 위 도메인을 기반으로 SSL 인증서를 적용할 수 있음

API Gateway 내에서 포워딩 및 트랜스포메이션 규칙을 적용하여 백엔드에 전송하기 전 수신 데이터를 수정할 수도 있음

 

마이크로 서비스를 통합하고 외부 통합 URL 을 제공하는 것이 api gateway 활용 목적

라우팅 서비스와 데이터 변환, SSL 인증서 지정 등 복잡한 면은 모두 클라이언트가 볼 수 없도록 숨김

위 작업들은 모두 api gateway level 에서 작업할 수 있음