Computer >> 컴퓨터 >  >> 프로그램 작성 >> Ruby

EC2에서 애플리케이션 비밀을 관리하는 방법

애플리케이션을 EC2에 배포할 때 autoscaling 그룹을 사용하는 것이 좋습니다. Autoscaling 그룹을 사용하면 수동 개입 없이 애플리케이션이 수요에 맞게 확장 및 축소하거나 실패한 인스턴스에서 복구할 수 있습니다. 그러나 작동하도록 하려면 부팅이 완료된 후 모든 인스턴스가 라이브 트래픽을 처리할 준비가 완전히 되어 있어야 합니다. 새 서버에서 약간의 변경을 수행하거나 준비가 되기 전에 capistrano를 통해 초기 배포를 수행하는 데 익숙한 경우에는 앱을 서버에 배포하는 것보다 약간 더 많은 노력이 필요합니다.

예를 들어, Rails를 사용하여 구축된 사용자 대면 웹 애플리케이션이 있습니다. 부팅이 완료되면 각 인스턴스는 해당 Rails가 준비되어 있고 로드 밸런서가 전달한 요청에 응답하기를 기다려야 합니다. 이를 위해 먼저 사용자 정의 앱, nginx 등과 함께 Ansible을 통해 프로비저닝된 인스턴스의 스냅샷을 생성하여 AMI on.따라서 앱과 모든 종속 항목이 제자리에 있으면 무엇이 남아 있습니까?

애플리케이션 비밀:배포자의 골칫거리

애플리케이션 시크릿은 도전 과제를 제시합니다. 노출될 수 있는 위치(예:git repo)에 저장되지 않도록 하고 싶지만 앱이 실행 중일 때 사용할 수 있어야 합니다. 그리고 자동 크기 조정 덕분에 필요할 때 앱에 배치하기 위해 사람을 의지할 수 없습니다.

이 문제에 대한 한 가지 대답은 Hashicorp의 Vault입니다. 앱이 필요할 때까지 비밀을 비밀로 유지하는 이 문제를 해결하기 위해 특별히 작성된 환상적인 소프트웨어입니다. 그러나 단점은 Vault를 프로비저닝하고 관리해야 한다는 것입니다. 계속 실행해야 하는 또 다른 서비스입니다.

또 다른 옵션은 비밀을 공유 스토리지(S3, 당연히)에 저장하고 인스턴스만 해당 버킷 및/또는 키에 액세스할 수 있도록 하는 것입니다. 이는 제한된 S3 리소스에 대한 액세스 권한을 부여하는 정책을 추가할 수 있는 IAM 역할을 사용하여 수행할 수 있습니다. 그러나 모든 비밀을 S3에 일반 텍스트로 저장하면 원치 않는 노출에 노출될 수 있습니다. 해당 버킷 또는 전 세계에 대한 액세스 권한이 있는 다른 사람이 실수로 해당 데이터를 사용할 수 있도록 할 수 있습니다.

S3몬을 저장하기 전에 비밀을 암호화하고 필요할 때 앱에서 로드하고 해독할 수 있다면 좋지 않을까요?

비밀 요소:Amazon의 키 관리 서비스

Amazon의 KMS(Key Management Service)는 암호화 키와 상호 작용하기 위한 API를 제공합니다. IAM 역할 및 theAws::S3::Encryption 모듈과 결합하면 몇 줄의 코드만으로 애플리케이션에 암호를 로드하면서 S3에서 암호화된 상태를 유지합니다.

자세히 알아보기 전에 비밀을 저장하기 위해 KMS와 S3를 사용하여 환상적인 게시물을 작성한 Don Mills에게 감사해야 합니다. S3의 비밀과 함께 키 정보를 저장하는 대신 IAM 역할에 따라 KMS 키를 별도로 추적하여 그의 접근 방식을 약간 변경했습니다.

KMS는 데이터를 암호화 및 해독하는 데 사용할 수 있는 마스터 암호화 키를 생성하고 제공합니다. 암호화를 요청하면 KMS에서 마스터 키를 기반으로 임시 키를 전달하며 해당 임시 키는 암호화 또는 복호화에 사용할 수 있습니다.

키를 생성하려면 IAM 콘솔로 이동하여 암호화 키 링크를 선택합니다. 키를 생성할 때 이 키를 사용할 수 있는 IAM 사용자 또는 역할을 지정하라는 메시지가 표시됩니다. Autoscaling 그룹의 일부가 될 EC2 인스턴스에 할당할 역할을 선택합니다. 키의 ARN을 기록해 두십시오. 나중에 사용하게 될 것입니다.

루 만들기:KMS와 IAM을 동등하게 만들기

키를 생성했으면 IAM 콘솔을 사용하여 선택한 IAM 역할을 편집합니다. 다음과 같은 정책을 연결하여 보안 비밀이 저장될 버킷에 대한 액세스 권한을 부여합니다.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1476277816000",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:PutObjectAcl",
                "s3:HeadObject"
            ],
            "Resource": [
                "arn:aws:s3:::yourbucket/secrets.yml"
            ]
        }
    ]
}

키가 구성되고 정책이 역할에 연결되면 Aws::S3::Encryption::Client 인스턴스를 통해 KMS 및 S3와 상호 작용할 수 있습니다. 다음은 비밀 파일을 검색하고 해당 내용을 환경 변수에 로드하는 몇 가지 샘플 코드입니다. /P>

begin
  es3 = Aws::S3::Encryption::Client.new(kms_key_id: ENV['KMS_KEY_ID'])
  YAML.load(es3.get_object(bucket: "yourbucket", key: "secrets.yml").body.read).each do |k, v|
    ENV[k] ||= v # Don't override local ENV settings
  end
rescue ArgumentError
  # Raised when no KMS_KEY_ID was found in ENV, so there's nothing to do
rescue Aws::S3::Errors::NoSuchKey
  # No secrets file was found, so there's nothing to do
end

먼저 KMS 키의 ID로 새 개체를 인스턴스화합니다. 키에 대한 ARN(키 생성 시 IAM 콘솔에 표시됨)은 KMS_KEY_ID 환경 변수에 저장됩니다. 여기서 생성자에 keyID를 전달하면 임시 암호 해독 키 가져오기가 처리됩니다. KMS와 통신하는 데 사용하는 것보다 별도의 자격 증명 세트를 사용하여 S3와 통신하려는 경우 여기에서 Aws::S3::Client 인스턴스를 옵션으로 지정할 수 있습니다. 하지만 이전에 IAM 역할을 설정한 경우에는 Aws::S3::Encryption::Client가 IAM 역할에서 제공한 자격 증명을 사용하여 새 Aws::S3::Client 인스턴스를 생성하므로 필요하지 않습니다.

암호화된 S3 클라이언트가 준비되면 #get_object를 사용하여 S3에서 데이터를 가져오고 KMS에서 제공한 키를 사용하여 암호를 해독합니다. 데이터가 있으면 데이터로 원하는 작업을 수행할 수 있습니다. 데이터는 YAML이므로 응용 프로그램 코드에서 사용할 키/값 쌍을 로드하고 ENV에 넣습니다.

이 코드를 Rails 애플리케이션의 이니셜라이저 파일에 넣기만 하면 됩니다. 글쎄, S3에 비밀이 저장되면, 즉. :) 올바른 IAM 역할로 실행 중인 인스턴스에 IRB 콘솔이 있다고 가정하면 다음과 같이 비밀 정보를 저장할 수 있습니다.

# Encrypt the data from /path/to/secrets.yml and store it on S3
Aws::S3::Encryption::Client.new(kms_key_id: ENV['KMS_KEY_ID']).
  put_object(bucket: "yourbucket", key: "secrets.yml", body: File.read("/path/to/secrets.yml"))

즉시 제공

이제 보안 암호를 암호화된 상태로 유지하면서 Autoscaling 그룹에 추가되는 모든 새 인스턴스에 항상 보안 암호를 사용할 수 있습니다. 모두 승리! :)