...
IAM Policy JSON 구조
IAM 정책을 만드는 JSON 파일의 구조는 아래와 같다.
전반적으로 전체 정책에 대한 Optional top-level elements가 있고 이에 여러 개의 Statement 를 추가하는 식으로 이루어져 있다. 그리고 하나의 Statement에는 여러개의 permission 정보가 포함 되어있다.
Optional top-level elements
{
"Version": "2012-10-17",
"Statement": [...]
}
- Version (string) : IAM Policy JSON 문서 양식 버전.
- 버젼은 2008-10-17와 2012-10-17가 있는데 2012년 껄 사용하면 된다.
- Statement (array) : 권한 부여 규칙의 나열
- Id : 정책 식별자를 지정 (옵셔널).
Statement
/* 하나의 정책에 다수의 Statements가 사용된 예 */
{
"Version": "2012-10-17", // “2012–10–17”, “2008–10–17” 값을 가질 수 있다.
"Statement": [
{
"Sid": "FirstStatement", // Statement ID로 statement 를 구분하기 위해서 사용
"Effect": "Allow", // 해당 설정 적용을 Allow / Deny
"Action": [ // 허용할 행위(액션)
"s3:List*",
"s3:Get*"
],
"Resource": [ // Action이 영향을 미치는 리소스 리스트를 지정
"arn:aws:s3:::confidential-data",
"arn:aws:s3:::confidential-data/*"
],
"Condition": {
"Bool": {"aws:MultiFactorAuthPresent": "true"}
} // 조건을 충족되는 경우에만 해당 정책을 적용
}
]
}
Statement 엘리먼트 요소
- 나열되는 요소들의 순서는 중요하지 않다. 예를 들어 Resource 요소는 Action 요소 앞에 올 수 있다.
- 정책에서 Condition 요소는 지정하지 않아도 된다.
- Action/NotAction, Principal/NotPrincipal, Resource/NotResource 는 택일 해야한다.
- SID (string) : Statement ID로 statement 를 구분하기 위해서 사용 (옵셔널)
- Effect : 엑세스를 허용하는지 거부하는지 설정. (Allow / Deny)
- Principal / NotPrincipal : 엑세스를 허용하거나 거부할 대상(사용자, 역할 등)을 지정
- 리소스 기반 정책에서만 사용 (뒤에서 자세히 소개)
- 리소스 기반 정책에서만 사용 (뒤에서 자세히 소개)
- Action / NotAction (string | array) : 서비스의 API Calls를 지정
- 하나 혹은 여러 개의 Action을 지정할 수 있다.
- 각 서비스별로 고유의 서비스 접두사(예: DynamoDB는 dynamodb, S3는 s3)가 있다.
- Action은 (서비스 접두사):(작업) 형식으로 작성 → dynamodb:DeleteItem, s3:GetObject
"Action": [
"s3:PutObject", // S3에 객체를 Put하는 액션
"s3:GetObjectAcl",
"s3:GetObject",
"s3:ListBucket",
"s3:DeleteObject",
"s3:PutObjectAcl"
],
- Resource, NotResource : Action이 영향을 미치는 리소스 리스트를 지정
- 작업이 적용되는 리소스 목록을 지정
- 리소스 기반 정책을 생성하는 경우 선택 사항
이 요소를 포함하지 않으면 작업이 적용되는 리소스는 정책이 연결된 리소스 - 리소스를 특정할 수 없는 일부 서비스에서는, Resource를 비워두는 대신 * 를 입력
{
"Effect": "Allow",
"Action": "dynamodb:*",
"Resource": "arn:aws:dynamodb:::table/users" // dynamodb의 users라는 table에 정책 적용. 이런 형식을 ARN이라고 한다
}
- Condition (object) : 조건을 넣어 줄 수 있다. 즉, 조건을 충족되는 경우에만 해당 정책을 적용시킬 수 있는 개념
조건 연산자 | 설명 |
NumericEquals | 일치 |
NumericNotEquals | 불일치 |
NumericLessThan | "미만" 일치 |
NumericLessThanEquals | "이하" 일치 |
NumericGreaterThan | "초과" 일치 |
NumericGreaterThanEquals | "이상" 일치 |
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::example_bucket",
"Condition": {"NumericLessThanEquals": {"s3:max-keys": "10"}} // NumericLessThanEquals 조건 연산자에 s3:max-keys 키를 사용하여 요청자가 example_bucket에서 한 번에 최대 10개까지 객체를 나열할 수 있다고 지정
}
}
IAM Policy 종류에 따른 JSON 구조
IAM 정책은 사용자에게 부여해서 사용자가 AWS 서비스에 엑세스 하는 구조를 가지지만, 사용자 뿐만 아니라 어플리케이션(리소스)에도 적용할수가 있다.
한마디로 EC2 인스턴스를 마치 유저 처럼 권한을 부여가 가능하다는 소리이다.
따라서 사용자에게 적용하느냐, 어플리케이션에 적용하느냐에 따라 Policy 타입이 나뉘게 된다.
대표적으로 다음 두가지로 나뉜다.
- 자격 증명 기반 정책(Identity-based Policies) : User, Group, Role에 할당하는 IAM 정책
- 리소스 기반 정책(Resource-based Policies) : 리소스(S3 Bucket Policy, SQS Queue Policy, VPC Endpoint Policy ... 등)에 연결하는 정책
그리고 어느 기반 정책이냐에 따라 JSON 구조가 약간 달라지게 된다.
위에서 JSON 구조를 살펴봤듯이, IAM 정책이라는 것은 "(어떤 Principal이) (어떤 Condition을 만족할 때,) 어떤 Resource에 대해서 어떤 Action을 할 수 있게 허용/불허(Effect)한다."라는 의미를 담은 것이다.
그런데 정책에서 주어 역할을 하는 Principal 속성은 정책 타입에 따라서 쓰기도 하고 안쓰기도 한다.
이에 대해서 자세히 알아보자.
자격증명 기반 정책(Id-Based Policy)
자격 증명 기반 정책은 AWS 계정, 사용자, 그룹, 역할 등이 주체가 되어 수행할 수 있는 작업, 리소스 및 조건을 제어하는 정책이다.
IAM 정책에서 조회되는 정책 대부분이 자격 증명 기반 정책이다.
자격 증명 기반 정책은 정책에 연결된 사용자가 곧 보안주체(Principal)이 되므로 Statement 에서 Principal 을 따로 기재하지 않는다는 특징이 있다.
정책에 연결된 보안 주체(AWS 계정, IAM 사용자, 그룹, 역할 등)가 암묵적인 Principal이 되기 때문이다. 그래서 실제로 자격 증명 기반 정책의 JSON 구조를 보면 Principal 속성이 생략되어 있다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": "*"
}
]
}
리소스 기반 정책(Resource-Based Policy)
자격 증명 기반 정책이 사람(유저)에게 연결하는 정책이었다면, 리소스 기반 정책은 AWS 리소스에 연결하는 정책이다.
AWS의 리소스 중에서 일부 서비스에서 사용되며 대표적으로 S3에서 사용되는 S3 버킷 정책이 대표적이다.
자격 증명 정책과는 달리 리소스 기반 정책은 반드시 Principal 속성을 기재한다.
이는 어쩌면 당연한 이치이다.
자격증명 기반 정책은 유저에게 적용하는 정책이다.
자격증명 기반 정책을 해석하자면, "이 정책과 연결된 보안주체는 어떤 대상에 대해 이러한 권한이 부여된다"가 된다.
즉, 정책을 부여한 보안주체가 곧 유저가 되니 굳이 Principal(보안주체) 속성이 필요가 없는 것이다.
그러나 리소스 기반 정책은 AWS 리소스에게 적용되는거라 "이 대상에 대해 이러한 권한이 누구누구에게 부여된다" 가 된다. 즉, 이 누구누구를 Principal 속성을 통해 지정해주어야 된다는 말이다.
{
"Version": "2012-10-17",
"Id": "default",
"Statement": [
{
"Sid": "s3-event-cezary_for_lambda-s3",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::ACCOUNT_ID:user/read-only-console-user" // 어느 IAM 유저에게 정책 적용
]
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:eu-west-1:1234567890:function:lambda-s3",
}
]
}
IAM 정책 유형 비교
자격증명-기반 정책(Id-Based Policy) | 리소스-기반 정책(Resource-Based Policy) | |
연결 대상 | 사용자, 그룹, 역할 등 보안주체(Principal)가 될 수 있는 대상 |
리소스 |
의미 | ( 이 정책이 연결된 보안주체는 ) ( 특정 조건(Condition) 하에 ) 이 리소스(Resource)에 대한 특정 행동(Action)을 허용/불허(Effect) |
( 특정 조건(Condtion)하에 ) 이 리소스(Resource)에 대한 특정 행동(Action)을 특정 보안주체(들)(Principal)에게 허용/불허(Effect) |
특징1 | Principal 속성이 안 들어감 | Principal 속성이 들어감 |
특징2 | IAM Policy 메뉴에서 관리 (혹은 IAM Role에 인라인으로) |
일부 AWS 서비스의 리소스에서 자체 관리 (대표적으로 S3, SQS 등) |
특징3 | 모든 AWS 서비스에 연관 | 일부 공유 자원 성격을 가진 서비스에서 사용 (대표적으로 S3, SQS 등) |
ARN 문법 구조
{
"Version": "2012-10-17",
"Id": "default",
"Statement": [
{
"Sid": "s3-event-cezary_for_lambda-s3",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::ACCOUNT_ID:user/read-only-console-user" // 어느 IAM 유저에게 정책 적용
]
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:eu-west-1:1234567890:function:lambda-s3",
}
]
}
위 정책 JSON 코드에서 Resource 의 값을 보면 arn: 이라고 되어있는걸 볼 수 있다.
ARN은 Amazon Resource Name의 줄임말로서 AWS의 리소스를 고유하게 식별하는 역할을 하는 일종의 아이디 개념이다.
아래는 ARN의 일반적인 형식이다.
arn:partition:service:region:account-id:resource-id
arn:partition:service:region:account-id:resource-type/resource-id
arn:partition:service:region:account-id:resource-type:resource-id
각각에 대해서 살펴보면,
- partition
- aws(표준 리전 그룹) | aws-cn(중국 리전 그룹) | aws-us-gov
- 리소스가 존재하는 AWS 리전의 그룹
- service
- aws service name (ex: s3)
- AWS 서비스를 뜻한다고 보면 된다.
- region
- 리전 (ex: ap-northest-2) 명
- account-id
- aws 계정 id (ex: 123456789012)
- 리소스를 소유하고 있는 AWS 계정의 ID로 하이픈 없이 표기
- resource-id
- 리소스의 이름 | 리소스의 ID | 리소스 경로
- / 를 포함하여 리소스 경로를 포함할 수 있으며 이 때 와일드카드 문자, *도 사용이 가능
구체적인 형식은 리소스마다 다르며, 일부 리소스는 region, account-id가 생략되기도 한다.
예를 들어 S3 버킷일 경우 굳이 정책에 계정 번호와 글로벌이기 때문에 AWS 리전이 필요하지않아 다음과 같이 S3 버킷 ARN에서 생략된다.
arn:aws:s3:::bucket_name
arn:aws:s3:::bucket_name/key_name
// 특정 SQS 대기열
"Resource": "arn:aws:sqs:us-east-2:account-ID-without-hyphens:queue1"
// Bob이라는 IAM 사용자
"Resource": "arn:aws:iam::account-ID-without-hyphens:user/Bob"
// 경로가 /accounting인 IAM 사용자들
"Resource": "arn:aws:iam::account-ID-without-hyphens:user/accounting/*"
// DOC-EXAMPLE-BUCKET 버킷 내에 포함된 모든 Object들
"Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
// 여러 리소스 지정, DynamoDB Table 2개
"Resource": [
"arn:aws:dynamodb:us-east-2:account-ID-without-hyphens:table/books_table",
"arn:aws:dynamodb:us-east-2:account-ID-without-hyphens:table/magazines_table"
]
# 참고자료
https://musma.github.io/2019/11/05/about-aws-iam-policy.html
이 글이 좋으셨다면 구독 & 좋아요
여러분의 구독과 좋아요는
저자에게 큰 힘이 됩니다.