외부 시스템 접근 제어
사용자 접근 및 마이크로서비스 간 상호 접근 외에도, 외부 타사 시스템도 시스템 내부의 마이크로서비스에 접근해야 할 수 있습니다. 예를 들어 이전 블로그의 온라인 상점 예시에서, 외부 추천 서비스가 상점의 상품 카탈로그 정보를 얻기 위해 시스템에 연결해야 할 수 있습니다. 내부 서비스 간의 접근과 비교하여 외부 시스템의 접근은 엄격한 보안 제어가 필요합니다.
계정을 통한 제어
외부 시스템을 위한 사용자 계정을 생성하여 일반 사용자처럼 외부 시스템의 계정을 관리하고, 해당 계정을 사용하여 외부 시스템에 대한 인증 및 권한 제어를 수행할 수 있습니다.
이 방식의 문제는 사용자 관련 민감한 데이터를 처리하기 어렵다는 것입니다. 외부 시스템 자체도 마이크로서비스 시스템의 사용자 계정이므로, 해당 외부 시스템은 해당 계정 자체의 데이터와 일부 민감하지 않은 공용 데이터만 접근할 수 있으며, 사용자 관련 데이터는 접근할 수 없습니다. 예를 들어 온라인 상점의 경우, 외부 시스템은 이 방식을 사용하여 상품 카탈로그 정보에 접근할 수 있지만, 사용자 구매 기록, 사용자 잔액 등의 정보에는 접근할 수 없어야 합니다.
API 토큰
API 토큰(API Key라고도 함)은 사용자 민감 데이터에 대한 접근을 제어할 수 있습니다. 마이크로서비스 애플리케이션은 API 토큰 생성 인터페이스를 제공하며, 사용자는 로그인 후 자신의 API 토큰을 생성하고, 타사 애플리케이션에서 해당 API 토큰을 사용하여 마이크로서비스 API에 접근할 수 있습니다. 이 경우 일반적으로 타사 애플리케이션은 해당 토큰 소유자 자신의 데이터만 접근할 수 있으며, 다른 사용자의 민감한 개인 데이터는 접근할 수 없습니다.
예를 들어 Github는 개인 API 토큰 기능을 제공하며, 사용자는 Github 개발자 설정 인터페이스에서 토큰을 생성한 다음, 해당 토큰을 사용하여 Github API에 접근할 수 있습니다. 토큰 생성 시, Repo 정보 보기, Repo 삭제, 사용자 정보 보기, 사용자 정보 업데이트 등 해당 토큰이 접근할 수 있는 사용자 데이터를 설정할 수 있습니다.
API 토큰을 사용하여 Github API에 접근하는 예시
curl -u hybridego:fbdf8e8862252ed0f3ba9dba4e328c01ac93aeec https://api.github.com/user시도하지 마세요. 이것은 제 실제 API 토큰이 아닙니다. 단지 시연용입니다 :-)
API 토큰을 사용하는 것이 사용자 이름/비밀번호를 직접 사용하여 API에 접근하는 것보다 좋은 점은 사용자 비밀번호 노출 위험을 줄이고, 비밀번호를 변경할 필요 없이 언제든지 토큰 권한을 회수할 수 있다는 것입니다.
API 토큰은 지정된 사용자 데이터만 접근할 수 있으므로, 사용자가 자신의 데이터를 애플리케이션에서 조작하기 위한 스크립트나 작은 프로그램을 개발하는 데 적합합니다.
OAuth
일부 타사 애플리케이션은 다른 사용자의 데이터에 접근하거나 여러 사용자의 데이터를 통합 처리해야 하는 경우 OAuth를 고려할 수 있습니다. OAuth를 사용하면 타사 애플리케이션이 서비스에 접근할 때, 애플리케이션은 사용자에게 해당 접근 권한을 부여하도록 요청하고, 사용자의 권한 부여 작업 결과에 따라 접근에 사용될 토큰을 생성하여 타사 애플리케이션의 작업 요청에 대한 접근 제어를 수행합니다.
마찬가지로 Github를 예로 들면, Travis CI, GitBook과 같은 일부 타사 애플리케이션은 OAuth를 통해 Github와 통합됩니다. OAuth는 다양한 시나리오에 따라 다른 인증 흐름을 가지며, 일반적인 인증 흐름은 아래 그림과 같습니다.
- 사용자가 OAuth 클라이언트 프로그램에 요청을 보내고, OAuth 클라이언트 프로그램은 해당 요청을 처리할 때 리소스 서버에 있는 사용자 데이터에 접근해야 함을 발견합니다.
- 클라이언트 프로그램은 사용자 요청을 인증 서버로 리디렉션하며, 이 요청에는 콜백 URL이 포함됩니다.
- 인증 서버는 권한 부여 페이지를 반환하여 사용자에게 OAuth 클라이언트의 리소스 요청에 대한 권한을 부여하도록 요구합니다.
- 사용자가 해당 작업에 권한을 부여하면 인증 서버는 요청을 클라이언트 프로그램의 콜백 URL로 리디렉션하고, 권한 부여 코드를 클라이언트 프로그램에 반환합니다.
- 클라이언트 프로그램은 권한 부여 코드를 인증 서버로 보내 토큰을 요청합니다.
- 인증 서버는 권한 부여 코드를 확인한 후 클라이언트 프로그램에 토큰을 발급합니다.
- 클라이언트 프로그램은 발급된 토큰을 사용하여 리소스에 접근하고 사용자 요청을 완료합니다.
참고:
OAuth에서는 기능에 따라 리소스 서버와 인증 서버라는 두 가지 역할을 구분하며, 구현 시 이 두 역할은 종종 동일한 애플리케이션입니다. 이 흐름도의 각 역할을 Github 예시에 대응시키면, 리소스 서버와 인증 서버는 모두 Github이고, 클라이언트 프로그램은 Travis CI 또는 GitBook이며, 사용자는 Travis CI 또는 GitBook을 직접 사용하는 사용자입니다.
어떤 사람들은 이 흐름에서 왜 인증 서버가 직접 토큰을 클라이언트에 반환하지 않고 권한 부여 코드(Authorization Code)를 사용하여 토큰을 신청해야 하는지 의아해할 수 있습니다. OAuth가 이렇게 설계된 이유는 클라이언트 콜백 URL로 리디렉션하는 과정에서 사용자 에이전트(브라우저)를 거치게 되는데, 이 과정에서 토큰이 직접 전달되면 도난당할 위험이 있기 때문입니다. 권한 부여 코드를 사용하는 방식은 토큰 신청 시 클라이언트가 인증 서버와 직접 상호 작용하며, 인증 서버는 클라이언트의 토큰 신청 요청을 처리할 때 클라이언트의 신원도 인증하여 다른 사람이 클라이언트 신원을 위조하여 인증 코드를 사용하여 토큰을 신청하는 것을 방지합니다. 다음은 클라이언트 프로그램이 권한 부여 코드(Authorization Code)를 사용하여 토큰을 신청하는 예시입니다. client_id와 client_secret은 클라이언트의 신원을 확인하는 데 사용됩니다.
POST /oauth/token HTTP/1.1 Host: authorization-server.com grant_type=authorization_code &code=xxxxxxxxxxx &redirect_uri=https://example-app.com/redirect &client_id=xxxxxxxxxx &client_secret=xxxxxxxxxx

또한 OAuth를 논할 때, 마이크로서비스 애플리케이션이 OAuth 클라이언트와 OAuth 서버의 두 가지 다른 시나리오로 사용되는 경우를 구분해야 합니다.
마이크로서비스 자체의 사용자 인증을 구현할 때, OAuth를 사용하여 마이크로서비스의 사용자 인증을 타사 인증 서비스 제공업체에 위임할 수도 있습니다. 예를 들어, 많은 애플리케이션이 사용자 로그인과 위챗 또는 QQ의 OAuth 서비스를 통합했습니다.
타사 애플리케이션 통합과 마이크로서비스 자체 사용자 인증에 OAuth를 사용하는 목적은 다릅니다. 전자는 마이크로서비스의 사용자 개인 데이터 접근 권한을 타사 애플리케이션에 부여하기 위한 것이며, 마이크로서비스는 OAuth 아키텍처에서 인증 및 리소스 서버의 역할을 합니다. 후자는 잘 알려진 인증 제공업체가 제공하는 OAuth 인증 서비스를 통합하고 활용하여 번거로운 등록 작업을 단순화하기 위한 것이며, 마이크로서비스는 OAuth 아키텍처에서 클라이언트의 역할을 합니다.
따라서 오해를 피하기 위해 이 두 가지 다른 시나리오를 구분해야 합니다.
후기
이전 두 편의 글이 공식 계정에 게시된 후, 친구들이 로그인 비밀번호 평문 문제, 재실행 공격 방지, 시간차 공격 방지, 데이터 유출 후 레인보우 테이블 공격 방지 등에 주의해야 한다고 언급했습니다. 물론 보안은 방대한 주제이며, 이 시리즈 글은 마이크로서비스 아키텍처가 애플리케이션 보안에 미치는 영향에 대한 저의 작은 생각만을 설명합니다. 제품 개발 및 운영에서는 보안에 대한 전반적인 고려가 필요하며, 외부 트래픽을 격리하기 위한 완벽한 방화벽 사용, 사용자 비밀번호 저장을 위한 솔트 해시 사용, 암호화 전송을 위한 TLS 사용, SQL 주입 방지를 위한 사용자 입력 엄격 검사, 검증된 범용 암호화 알고리즘 사용 등 업계의 모범 사례를 따르는 것이 가장 좋습니다.
