1. 비밀 값 관리

1-1. 비밀 값?

대부분의 애플리케이션은 외부에 절대로 노출돼서는 안되는 비밀 값들을 가지고 있다. 예를 들어 데이터베이스느 접속 정보나 서드파티 서비스를 이용하기 위한 비밀 액세스 키 등이 있다.

즉 비밀 값은 유출될 경우 서비스의 안전에 위협이 되는 값들을 얘기한다. 그러한 비밀 값을 관리하는 데는 다음과 같은 원칙이 있다.

하나, 비밀 값은 버전 관리 시스템에 업도르되면 안 된다.

둘, 비밀 값은 최소한의 인원만 알고 있어야 한다. 

셋, 비밀 값과 아닌 값은 분리해서 관리해야 한다. 

 

1-2. 관리방법

-. 배포 자동화 툴

AWS의 CodeDeploy, 젠킨스(Jenkins), 셰프(Chef), 앤서블(Ansible)과 같이 유명한 DevOps 서비스들에서는 배포 자동화 기능을 지원한다. 이런 서비스들을 이용해 배포할 때 서버내 암호화된 값을 어플리케이션이 사용할 수 있게 저장해둘 수 있다. 인스턴스를 배포할 때 어플리케이션이 시작되기 이전에 운영체제의 환경변수나 파일에 비밀 값들을 저장해두고 어플리케이션에서는 이 값을 참조해서 쓸 수 있다. 

CodeDeploy가 아닌 외부 서비스를 이용하고 있다면 해당 서비스에서 제공하는 방법을 사용하는 것도 좋다. 단! 해당 서비스에서 비밀 값들에 접근할 수 있는 권한이 세분되어 일부 사용자들만 그 비밀 값을 읽을 수 있는지 반드시 확인해야 한다.

 

-. Blackbox

 비밀 값들을 담고 있는 파일을 암호화해서 VCS에 올리는 방법도 있다. 많이 사용되는 OSS로는 Blackbox가 있다.

Blackbox는 Stack Overflow로 유명한 사이트를 만드는 Stack Exchange에서 만든 툴로서 GPG(GNU Privacy Guard)라는 암호화 프로그램을 이용해 비밀 값들이 담긴 파일들을 암호화 한다.

즉 Blackbox는 GPG를 이용해 암호화, 복호화, 관리자 관리 등의 작업을 쉽게 이용할 수 있게 만든 쉘 스크립트의 모음이다.

자세한 내용은 Blackbox 프로젝트 홈페이지에서 찾아볼 수 있다.

주소) https://github.com/StackExchange/blackbox

 

-. Vault

Vault는 클라우드 인프라 자동화 제품들을 만드는 HashiCorp에서 만든 오픈소스 프로젝트다. 이 툴은 비밀을 관리하는 데 필요한 거의 모든 기능을 제공한다.

  1. 비밀 값을 함호화 해서 저장
  2. API에 접속할 수 있는 임시 토큰 발금
  3. 키 롤링
  4. 외부 서비스(IAM,SSH,DB 등)에서 사용하는 권한 시스템 사용
  5. 기록 감사
  6. 암복호화 API
  7. 등등..

Vault는 외부로부터 API로 통신하기 때문에 서버 어플리케이션과 같이 실행돼야 한다.

어플리케이션은 HTTP API를 통해 Vault에 인증을 요청한다. (Vault 시스템에 로그인한다고 이해하면 편하다) 인증이 완료되면 Vault API를 이용할 수 있고 일정 시간이 지나면 만료되는 토큰을 응답으로 준다. 크다음 어플리케이션에서 새로운 비밀 값을 저장하거나 읽어오기 위해 API로 토큰과 함께 요청하면 Vault에서는 저장 백엔드에 해당 값을 추가하거나 읽어와서 응답으로 넘긴다.

Vault는 접속하는 어플리케이션마다 접근할 수 있는 비밀을 다르게 설정할 수 있는 권한 정책도 지정할 수 있다. 그리고 모든 API 요청 이력을 저장하고 있어서 해당 이력을 감사하는 데도 편리하다. 

주소) https://www.vaultproject.io/

 

1-3. AWS Secrets Manager

Secrets Manager는 AWS에서 제공하는 비밀 값 관리 서비스이다. 비밀 값들을 저장해두고 어플리케이션에서 AWS의 API를 호출해서 받아가 사용하는 방식이다.

-. 동작 절차

  1. 관리자가 Secrets Manger에 비밀을 만들고 그 비밀 안에 여러 Key, value 비밀 값들을 등록한다.
  2. 비밀 값들은 AWS KMS(Key Management Service)라는 키 관리 서비스를 통해 암호화된다.
  3. 비밀 값들을 사용하는 서버에서 AWS CLI나 SDK를 이용해 특정 IAM 사용자로 Secrets Manger에 비밀 값을 요청한다.
  4. IAM에서 요청한 사용자에게 해당 비밀을 조회할 수 있는 권한이 있다고 판단하면 Secrets Manager가 비밀의 값을 복호화해서 응답으로 준다.
  5. 어플리케이션에서는 받은 비밀 값을 사용한다.

 

* KMS

암호화하는 데 사용하는 키를 관리할 수 있는 서비스. 여기에 키를 등록해두면 다른 AWS 서비스에서 암호화를 진행해야 할 필요가 있을 때 이 키를 가져다가 암호화를 진행할 수 있음.

 

* AWS CLI(Command Line Interface) / SDK(Software Development Kit)

AWS 콘솔에서 할 수 있는 모든 기능을 명령줄에서 실행할 수 있게 해주는 툴. 명령줄로 실행할 수 있다는 것으 사람뿐만 아니라 AWS의 기능들을 조작할 수 있는 프로그램을 만들 수 있다는 것을 뜻 함. 

SDK는 CLI와 비슷하지만 명령줄이 아닌 다양한 프로그래밍 언어에서 사용하기 쉽게 만들어져 있다는 차이점이 있다.

 

Secrets Manager는 비밀이라는 단위 안에 여러 개의 키/값 쌍을 저장할 수 있기 때문에 어플리케이션이나 환경별로 비밀 값들을 관리하기가 쉽다. 또한 각 값에 대한 변경 이력도 볼 수 있으며 누군가 삭제했더라도 일정 기간 동안에는 완전히 삭제되지 않고 보존되고 있으므로 더욱 안전하게 관리할 수 있다.

자세한 내용은 https://aws.amazon.com/ko/secrets-manager/ 에서 확인할 수 있다. 요금은 요금페이지(https://aws.amazon.com/ko/secrets-manager/pricing/)에서 확인할 수 있다.

* 현재 비용은 아래와 같이 표시되었다..

보안 암호당 $0.40/월
API 호출 10,000건당 $0.05
30일 무료 평가판 제공

2. 실습 - Secrets Manager

* 실습을 진행하기 위해서는 AWS CLI를 위한 사용자가 생성이 되어있어야 한다. 그리고 해당 계정에 [SecretsManagerReadWrite]와 [AWSKeyManagementServicePowerUser] 권한이 부여돼 있어야 한다.

  1. [IAM] 서비스 검색 후 이동
  2. 좌측 메뉴에서 [사용자] -> [사용자 추가] 클릭
  3. 사용자 이름은 자유(CLI를 위한 사용자라는 표시가 있으면 좋습니다), 액세스 유형은 [프로그래밍 방식 액세스] 선택
  4. 권한은 [기존 정책 직접 연결] -> [AmazonEC2FullAccess],  [SecretsManagerReadWrite], [AWSKeyManagementServicePowerUser] 검색 후 선택
  5. 사용자를 만들고 생성이 완료되면 액세스 키 ID와 비밀 액세스 키가 제공 된다. 비밀 엑세스 키는 [표시] 버튼을 눌러 확인하거나 [.csv 다운로드] 버튼을 통해 저장해둘 수 있다.
  6. #AWS CLI 설치
    #윈도우 사용자의 경우 공식 홈페이지에서 제공하는 설치파일을 받아 진행
    pip install awscli
    
    #설치 확인
    aws --version
    #aws-cli/1.15.71 ~~ 이런 문구가 제대로 나와야 함
    
    #AWS CLI는 콘솔에 접속하는 대신 API를 호출하는 것이기 때문에 어떤 사용자로 로그인해서 사용하는지 명시해 두어야 한다. 그러기 위해서는 사용자 정보를 로컬 머신에 저장해두어야 한다.
    aws configure
    
    # Key ID : 액세스 사용자의 ID
    # Key : 액세스 key
    # region : 본인의 생성 리전
    # format : 응답으로 보여줄 데이터 포멧

2-1. 비밀 생성하기

-. [Secrets Manager] 서비스 검색 후 이동 -> [새 보안 암호 저장] 클릭 -> [비밀 유형 : 다른 유형의 비밀] 선택 예시로 아래와 같이 진행

* [RDS 데이터베이스 자격 증명]이나 [기타 데이터베이스 자격 증명]을 선택하면 AWS RDS(Relational Database Service)라는 AWS의 관계형 DB 관리 서비스나 외부 DB의 계정과 암호도 관리할 수 있다. 추가로 자동으로 암호를 주기적으로 변경할 수도 있다.

* 암호화 키 선택하는 부분은 우리가 이 값들을 어떤 키로 암호화할 것인지 선택하는 부분이다. 더 강력한 보안을 위해 KMS에서 만들어 둔 키들을 사용할 수 있으나 이번에는 기본적으로 제공되는 키인 DefaultEncryptionKey를 사용하겠다.

 

-. 생성하려는 비밀의 이름과 간단한 설명(선택사항)을 지정.

보안이름 : prod/aws-exercise

* 이름 같은 경우에는 규칙을 "/"로 나누어 관리하면 편리하다.

 

-. 자동 교체 구성은 키를 자동으로 교체할지 설정할 수 있는 단계다. 보안의 이유로 키는 꼭 주기적으로 교체해줘야 한다. 모든 어플리케이션에서 Secrets Manager의 비밀 값을 가져다 읽도록 설정했다면 Lambda 함수를 이용해 주기적으로 새로운 키를 발급해서 교체할 수 있는 기능을 제공한다. 지금은 이 기능이 필요하지 않으니 비활성화를 선택하겠다.

 

-. 이렇게 설정된 비밀은 AWS CLI나 AWS SDK를 사용해 어플리케이션 코드에서 가져다 쓸 수 있다. AWS에서는 Java, JavaScript, C#, Python으로 작성된 샘플코드를 제공한다.

 

-. 저장을 완료하고... 이제 비밀을 사용해 보도록 하겠다.

  AWS CLI는 명령중에서 실행하는 것이기 때문에 직접 명령어를 실행하거나 쉘 스크립트를 이요할 때 유용하다. AWS SDK는 Java, JavaScript, Python등 대부분의 언어를 지원하기 때문에 어플리케이션에서 사용해야 하는 경우 사용하는 것이 유용하다. 우리는 JavaScript로 된 샘플 코드를 사용해 비밀 값을 가져와 보겠다.

 

-. [EC2] -> [exercise-instance] 실행, SSH 접속

#프로젝트를 받을 경로로 이동
#프로젝트 내려 받기
git clone https://github.com/deopard/aws-exercise-a.git
cd aws-exercise-a/

#Secrets Manager가 적용돼 있는 코드를 사용하기 위해 브랜치 변경.
git checkout secrets-manager

#코드 확인
vi app.js

#위 부분에 본인의 Key ID와 Key를 입력. #보안이름도 본인의 설정에 맞게 바꿔주어야 함. 제공 되는 파일의 기본 값 : production/aws-exercise

#파일의 아래쪽을 보면 Secrets Manager에서 비밀 값들을 읽어온 후, 해당 값들을 포함해서 응답을 생성하는 것을 알 수 있다. 

#파일 저장
#의존성 라이브러리 설치
npm install

#nginx 재기동!!!

 

-. 이제 퍼블릭 IP로 인스턴스에 요청을 날려본다.

위와 같이 결과가 제대로 보이는 것을 알 수 있다.