[컴] AWS 의 instance에서 IAM role 사용

security credential, IAM role

AWS 의 instance에서 IAM role 사용

AWS의 instance에서 IAM role 을 사용할 수 있다. 예를 들어 EC2에서 s3를 사용할때 access key 를 발급받고, 그것을 instance 에 넣고, 그것을 application 이 사용하게 된다. 그런데 이 IAM role 을 사용하면, 실제적으로 application 이 access key 를 사용하는 것과 비슷하게 주기적으로 refresh 되는 security token 을 사용하게 된다.

그래서 IAM 을 사용하는 것은 이전에 access key 를 만들고, 그것을 넣어주는 작업을 좀 더 간편하게 해준다.


+-------------------------------------------+
| EC2 instance                              |
|    - iam/security-credentials/<role-name> |
|  +-------------+                          |
|  | Application |                          |
|  +-------------+                          |
+----------|---^----------------------------+
           |   |                          |
           |   |                          V
           |   |                       +---------+     +------------+
           |   |                       | Profile |---> | IAM role   |               
 role name |   |                       +---------+     | + policy   |
           |   |                                       | + policy   |
           |   |                                       +------------+
           V   |         
+------------------------------+
| Security Token Service(STS)  |
+------------------------------+

  • IAM role에 policy 를 만들어서 permission 을 명시하게 된다. resource-level 로 permission들을 적용할 수 있다.
  • IAM role 을 만들때 trusted entities 에 이 role을 사용할 수 있는 aws service 를 정의해주게 된다.
  • 이 IAM role을 ’instance의 profile’에 할당할 수 있다. 이 profile 은 1개의 IAM role 만 담을 수 있다.
    • 현재 run 하고 있는 instance 에도 attach 할 수 있다.
  • IAM console에서 IAM role 을 만들면, IAM console 은 instance profile 을 자동으로 생성한다.
  • 이 IAM role 에 policy 가 있다. 이 policy 에 어떤 action/resource 에 어떤 permission 이 허락되는지를 표시하게 된다.
  • instance 에 있는 application 은 STS 에다가 security credential 을 retrieve 한다.(아래 AssumeRole api 참고)
    • application 에서 사용하는 AWS SDK 에서 이 작업을 해주게 된다.
    • instance metadata item(iam/security-credentials/<role-name>) 을 보고 해당하는 security credential 을 retrieve 한다.
    • 이러한 security credentials은 임시적이며 자동으로 교체된다. 이전 credential이 만료되기 최소 5분 전에 새 credential을 사용할 수 있게 한다.

Retrieve instance metadata - Amazon Elastic Compute Cloud : aws는 http://169.254.169.254/latest/meta-data/ 에 각 instance 들의 meta-data들이 있다.

security credential 을 요청하는 command

아래는 s3access 라는 IAM role 에 대한 security credential 을 요청하는 command이다.

# s3access 라는 IAM role 에 대한 security credential 을 요청하는 command
#
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" -v http://169.254.169.254/latest/meta-data/iam/security-credentials/s3access


{
  "Code" : "Success",
  "LastUpdated" : "2012-04-26T16:39:16Z",
  "Type" : "AWS-HMAC",
  "AccessKeyId" : "ASIAIOSFODNN7EXAMPLE",
  "SecretAccessKey" : "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
  "Token" : "token",
  "Expiration" : "2017-05-17T15:09:54Z"
}

만약 instance 에서 AWS SDK를 사용해서 application 을 만들었다면, AWS SDK 가 자동으로 credential 들을 ec2 instance metadata service 로 부터 가져가서 사용하게 된다. (iam/security-credentials/<role-name>)

AssumeRole api

이 api 는 STS(security token service) 에서 제공한다.

이 api 를 호출하면 credential 을 return 해준다.

sts_client = boto3.client('sts')

assumed_role_object=sts_client.assume_role(
    RoleArn="arn:aws:iam::account-of-role-to-assume:role/name-of-role",
    RoleSessionName="AssumeRoleSession1"
)

credentials=assumed_role_object['Credentials']

s3_resource=boto3.resource(
    's3',
    aws_access_key_id=credentials['AccessKeyId'],
    aws_secret_access_key=credentials['SecretAccessKey'],
    aws_session_token=credentials['SessionToken'],
)

terraform code

terraform 으로 구성하면 아래와 같다.

설명:

  • ec2 가 사용할 수 있는 IAM role 을 만들고,
  • 그 role 에 s3 mycorp-myapp bucket 을 사용할 수 있는 권한을 준다.
  • 그리고 instance profile 을 이용해서 ec2 에 attach 한다.
// ----------------------------
//
// IAM Role
//
// ----------------------------

resource "aws_iam_role" "tf-myapp-s3" {
  name = "myapp-s3"
  assume_role_policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Sid    = "exmyapp"
        Action = "sts:AssumeRole",
        Effect = "Allow",
        Principal = {
          // entities that can use this role
          Service = "ec2.amazonaws.com"
        }
      }
    ]
  })
  tags = {
    Name = "my-app"
  }
}

resource "aws_iam_role_policy" "tf-myapp-s3" {
  name = "myapp-s3"
  role = aws_iam_role.tf-myapp-s3.name
  policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Action = "s3:ListBucket",
        Effect = "Allow",
        Resource = [
          "arn:aws:s3:::mycorp-myapp",
          "arn:aws:s3:::mycorp-myapp/*"
        ],
      },
      {
        Action = [
          "s3:DeleteBucket",
        ],
        Effect = "Deny",
        Resource = [
          "arn:aws:s3:::mycorp-myapp",
        ]
      }
    ]
  })
}


// ----------------------------
//
// instance profile
//
// ----------------------------
resource "aws_iam_instance_profile" "tf-myapp-s3" {
  name = "myapp-s3"

  role = aws_iam_role.tf-myapp-s3.name
}



// ----------------------------
//
// EC2
//
// ----------------------------
resource "aws_instance" "tf-myapp" {
  ...

  iam_instance_profile = aws_iam_instance_profile.tf-myapp-s3.name
  ...
}

Reference

댓글 없음:

댓글 쓰기