Amazon Web Service
IAM은 AWS에서 핵심이 되는 부분 중 하나입니다. AWS에 있는 다양한 객체들에게 어떤 일을 할 수 있고 어떤 일을 할 수 없는지 권한을 부여하기 때문입니다. 특히 빌드 및 배포를 위한 파이프라인, 로그 데이터 수집을 위한 데이터 파이프라인 등 AWS의 여러 객체들을 묶어서 자동화를 구축하게 된다면 각각의 객체가 가져야 할 권한을 할당해 주는 일은 매우 중요합니다. 그리고 이런 권한 할당 작업은 Role을 통해서 진행됩니다.
그래서 이번 글에서는 IAM에 있는 Role에 대한 대략적인 내용을 살펴보고 EC2 인스턴스에 직접 특정 권한을 주어서 IAM Role의 변경에 따라 EC2 인스턴스의 작업이 어떻게 변하는지 살펴보겠습니다.
IAM은 Identity and Access Management의 약자로 AWS의 각 객체에 (사용자, 서비스 등등) 권한을 주는 서비스입니다. ( 참고 : https://docs.aws.amazon.com/ko_kr/IAM/latest/UserGuide/introduction.html ) 각 권한은 역할이라는 상위 개념으로 모여지게 되고 이렇게 정의된 역할을 각 객체에 할당합니다. 그리고 이 역할을 IAM Role이라고 부릅니다.
먼저 Role은 Policy로 구성됩니다. Policy는 서비스 별로 할 수 있는 작업을 정의한 규칙입니다. Policy 자체도 여러 개의 Policy가 모여서 더 큰 Policy가 될 수 있으며, AWS가 미리 생성해 놓은 Policy (AWS Managed)와 사용자가 직접 생성한 Policy (Customer Managed)로 구분할 수 있습니다.
아래 그림을 한 번 살펴보겠습니다. 위에서 이야기한 것처럼 Role은 1개 이상의 Policy들을 조합하여 생성합니다. 그리고 한 개의 Policy는 다수의 Role에 연결될 수 있습니다. 그럴 경우 해당 Policy를 수정하게 되면 연결되어 있는 모든 Role에도 변화가 생깁니다.
만약 S3에 업로드하고 다운로드하는 서비스가 필요하다면 S3 Updater라는 Role을 만들고 해당 Role에 S3:GetObject와 S3:PutObject라는 Policy를 연결해 줍니다. 그럼 해당 서비스는 S3에 업/다운로드하는 권한을 가지게 됩니다.
그럼 간단한 예제를 만들어 가면서 살펴보겠습니다.
먼저 아무런 Role도 가지지 않은 EC2 인스턴스를 만들어 보겠습니다. AWS 콘솔이 아닌 Terraform을 이용해서 만들어 보겠습니다.
아래 코드는 Amazon Linux 2 AMI를 이용해서 아무런 Role을 가지지 않는 EC2 인스턴스를 생성하는 코드입니다.
각 요소들은 변수 처리되어 있으니 각자의 환경에 맞게 수정하면 됩니다.
이렇게 생성된 EC2 인스턴스에 SSH로 접근한 후 아래와 같이 S3와 관련된 AWS CLI를 입력해 보겠습니다.
aws s3 ls
그럼 아래와 같이 에러가 발생합니다.
[ec2-user@ip-10-200-5-58 ~]$ aws s3 ls
Unable to locate credentials. You can configure credentials by running "aws configure".
어떻게 보면 당연한 결과 일 겁니다. 이 EC2 인스턴스에는 S3를 조회할 수 있는 어떠한 권한도 없으며 AWS CLI를 사용하기 위한 Access Key도 아무것도 설정되어 있는 게 없습니다.
그럼 이번엔 이 EC2 인스턴스에 S3의 요소들을 조회할 수 있는 Role을 부여해 보겠습니다. 그럼 명령어의 결과가 어떻게 달라질까요?
이번에도 Terraform을 이용해서 Role을 부여해 보겠습니다. 먼저 IAM Role을 생성하는 Terraform 코드입니다.
위에서 이야기했던 것과는 약간 다르게 Profile이라는 것이 추가되었습니다. EC2 인스턴스에게 역할을 주기 위해서는 Role을 Profile이라는 것으로 한 번 더 감싸 줍니다.
그리고 앞에서 EC2 인스턴스 생성을 위해 만들었던 코드에는 iam_instance_profile이라는 항목을 추가해 줍니다. ( 참고 : https://www.terraform.io/docs/providers/aws/r/iam_instance_profile.html )
그리고 다시 한번 Terraform을 적용한 후 서버에서 aws s3 ls 명령을 입력하게 되면 아래와 같이 현재 S3의 버킷들을 조회할 수 있게 됩니다.
[ec2-user@ip-10-200-10-184 ~]$ aws s3 ls
2019-03-22 10:09:04 assets
2019-03-22 10:09:02 assets-logs
지금까지의 과정을 통해서 우리는 EC2 인스턴스에 S3 버킷을 조회할 수 있는 Role을 부여했고 그에 따라서 EC2 인스턴스가 성공적으로 S3 버킷을 조회하는 것을 확인했습니다.
여기에는 매우 중요한 사실이 한 가지 숨어 있는데, 바로 AWS CLI를 사용하기 위해 별도의 Access Key가 필요 없었다는 것입니다.
보통 자동화 시스템을 구성하게 되면 SDK나 CLI를 성공적으로 호출하기 위해 API용 Access Key를 만들게 되는데요, 이렇게 EC2 인스턴스에 Role을 통해서 권한을 주게 되면 별도의 API용 Access Key가 필요하지 않게 됩니다. 이는 소스 코드 배포 시에도 적합한 Role만 부여한다면 자동화 시스템 구성을 위해 별도의 API용 Access Key키가 필요하지 않다는 것을 의미하며 보안적으로도 매우 중요한 의미를 가집니다.
이런 Role 부여가 가장 빛을 발하는 곳이 바로 AWS Lambda입니다.
AWS Lambda를 이용해서 주기적으로 AWS의 다른 서비스와 통신하는 함수를 작성했다고 했을 때, 정상적인 동작을 하게 하기 위해 API용 Access Key를 함께 배포하는 것이 아니라 Lambda 자체에 연동하는 서비스에 접근할 수 있는 Role로 부여해 주기만 하면 됩니다.
이를 통해 코드 작성하는 그 자체에 집중할 수 있게 해 줍니다.
그럼 마지막으로 간단하게 어떻게 동작하게 되는 것인지 살펴보겠습니다.
Role을 통해 EC2 인스턴스에게 권한을 주게 되면 meta-data 항목 중에 아래와 같이 identity-credentials/ec2/security-credentials가 생깁니다.
[ec2-user@ip-10-200-10-184 ~]$ curl http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentialse
{
"Code" : "Success",
"LastUpdated" : "2019-04-20T13:26:03Z",
"Type" : "AWS-HMAC",
"AccessKeyId" : "XXXXXXXX",
"SecretAccessKey" : "XXXXXXXX",
"Token" : "XXXXXXXX",
"Expiration" : "2019-04-20T19:44:29Z"
}
그래서 해당 EC2 인스턴스에서 돌아가는 AWS SDK 혹은 CLI는 이 값을 바탕으로 권한을 부여받고 통신을 하게 됩니다. 사실은 사용자가 직접 Access Key를 생성해서 넣어주어야 하는 부분이 자동으로 채워지게 되는 것입니다. 그리고 이 값들은 AWS Token 서버를 통해서 자동으로 갱신되고 유지되기 때문에 사용자는 이에 대해 전혀 신경 쓰지 않아도 됩니다.
지금까지 IAM Role을 이용해서 EC2 인스턴스에 권한을 부여하고 이를 통해서 EC2 인스턴스의 동작이 어떻게 변하는지 살펴봤습니다. IAM Role은 AWS의 서비스를 사용하기 위해 꼭 익혀야 하는 개념이며 중요한 부분입니다. 특히 Lambda와 같이 자동화를 구축할 경우 IAM Role을 이용해서 적합한 권한을 부여하게 되면 별도의 인증을 위한 부분을 고려하지 않아도 되기 때문에 더 편하게 자동화 시스템을 구축할 수 있게 됩니다.
자동화 시스템을 구축 중이라면 IAM Role을 꼭 잊지 않고 챙기시길 바랍니다. 감사합니다.