서버리스 IAM 정책 커스터마이징
서버리스 IAM 정책 커스터마이징
Serverless Framework는 AWS CLI 프로필에 연결된 IAM 자격 증명의 정책을 사용해 배포를 진행합니다. 이전 IAM 사용자 생성 챕터에서 Serverless Framework가 프로젝트를 배포할 때 사용할 사용자를 만들었습니다. 이 사용자에게는 AdministratorAccess 권한이 부여되었습니다. 이는 Serverless Framework와 프로젝트가 AWS 계정에 완전한 접근 권한을 갖는다는 의미입니다. 신뢰할 수 있는 환경에서는 괜찮지만, 팀으로 작업하는 경우 프로젝트를 사용하는 사람에 따라 접근 수준을 세밀하게 조정하고 싶을 수 있습니다.
이번 챕터에서는 Serverless Framework가 사용할 IAM 정책을 커스터마이징하는 방법을 살펴보겠습니다.
필요한 권한은 다음과 같은 영역으로 나눌 수 있습니다:
- Serverless Framework가 필요한 권한
- Serverless Framework 플러그인이 필요한 권한
- Lambda 코드가 필요한 권한
AdministratorAccess 정책을 부여하면 프로젝트가 항상 필요한 권한을 갖게 됩니다. 하지만 최소한의 권한만 부여하는 IAM 정책을 만들고 싶다면 IAM 정책을 커스터마이징해야 합니다.
기본적인 서버리스 프로젝트는 다음 AWS 서비스에 대한 권한이 필요합니다:
- CloudFormation: 변경 세트 생성 및 스택 업데이트
- S3: 서버리스 아티팩트 및 Lambda 소스 코드 업로드 및 저장
- CloudWatch Logs: Lambda 실행 로그 저장
- IAM: Lambda IAM 역할에 대한 정책 관리
- API Gateway: API 엔드포인트 관리
- Lambda: Lambda 함수 관리
- EC2: VPC 내에서 Lambda 실행
- CloudWatch Events: CloudWatch 이벤트 트리거 관리
간단한 IAM 정책 템플릿
아래와 같은 간단한 IAM 정책을 정의하고 부여할 수 있습니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"cloudformation:*",
"s3:*",
"logs:*",
"iam:*",
"apigateway:*",
"lambda:*",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSubnets",
"ec2:DescribeVpcs",
"events:*"
],
"Resource": [
"*"
]
}
]
}
이 정책은 IAM 사용자 생성 챕터의 기존 정책 직접 연결 단계에서 생성 중인 IAM 사용자에게 연결할 수 있습니다.
정책 생성 버튼을 클릭합니다.
그리고 직접 정책 생성 섹션에서 선택을 클릭합니다.
여기서 새 정책의 이름을 지정하고, 위에서 생성한 정책을 정책 문서 필드에 붙여넣습니다.
마지막으로 정책 생성을 클릭합니다. 이제 IAM 사용자를 생성할 때 이전에 사용했던 AdministratorAccess 대신 이 정책을 선택할 수 있습니다.
이 정책은 Serverless Framework 프로젝트에 위에 나열된 모든 리소스에 대한 접근 권한을 부여합니다. 하지만 각 AWS 서비스의 특정 액션과 특정 리소스로 제한하여 더 세부적으로 설정할 수도 있습니다.
고급 IAM 정책 템플릿
아래는 배포 중인 서버리스 프로젝트에 대한 접근을 제한하는 더 세밀한 정책 템플릿입니다. <region>
, <account_no>
, <service_name>
을 여러분의 프로젝트에 맞게 변경해야 합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"apigateway:GET",
"apigateway:PATCH",
"apigateway:POST",
"apigateway:PUT"
],
"Resource": [
"arn:aws:apigateway:<region>::/apis"
]
},
{
"Effect": "Allow",
"Action": [
"apigateway:GET",
"apigateway:PATCH",
"apigateway:POST",
"apigateway:PUT"
],
"Resource": [
"arn:aws:apigateway:<region>::/apis/*"
]
},
{
"Effect": "Allow",
"Action": [
"cloudformation:CancelUpdateStack",
"cloudformation:ContinueUpdateRollback",
"cloudformation:CreateChangeSet",
"cloudformation:CreateStack",
"cloudformation:CreateUploadBucket",
"cloudformation:DeleteStack",
"cloudformation:Describe*",
"cloudformation:EstimateTemplateCost",
"cloudformation:ExecuteChangeSet",
"cloudformation:Get*",
"cloudformation:List*",
"cloudformation:UpdateStack",
"cloudformation:UpdateTerminationProtection"
],
"Resource": "arn:aws:cloudformation:<region>:<account_no>:stack/<service_name>*/*"
},
{
"Effect": "Allow",
"Action": [
"cloudformation:ValidateTemplate"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"ec2:Describe*"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"events:Put*",
"events:Describe*",
"events:List*"
],
"Resource": "arn:aws:events:<region>:<account_no>:rule/<service_name>*"
},
{
"Effect": "Allow",
"Action": [
"iam:AttachRolePolicy",
"iam:CreateRole",
"iam:DeleteRole",
"iam:DeleteRolePolicy",
"iam:DetachRolePolicy",
"iam:GetRole",
"iam:PassRole",
"iam:PutRolePolicy"
],
"Resource": [
"arn:aws:iam::*:role/<service_name>*-lambdaRole"
]
},
{
"Effect": "Allow",
"Action": [
"lambda:*"
],
"Resource": [
"arn:aws:lambda:*:*:function:<service_name>*"
]
},
{
"Effect": "Allow",
"Action": [
"logs:DescribeLogGroups"
],
"Resource": "arn:aws:logs:<region>:<account_no>:log-group::log-stream:*"
},
{
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:DescribeLogStreams",
"logs:FilterLogEvents"
],
"Resource": "arn:aws:logs:<region>:<account_no>:log-group:/aws/lambda/<service_name>*:log-stream:*",
"Effect": "Allow"
},
{
"Effect": "Allow",
"Action": [
"s3:CreateBucket",
"s3:DeleteBucket",
"s3:DeleteBucketPolicy",
"s3:DeleteObject",
"s3:DeleteObjectVersion",
"s3:Get*",
"s3:List*",
"s3:PutBucketNotification",
"s3:PutBucketPolicy",
"s3:PutBucketTagging",
"s3:PutBucketWebsite",
"s3:PutEncryptionConfiguration",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::<service_name>*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::<service_name>*/*"
]
}
]
}
<account_no>
는 여러분의 AWS 계정 ID이며, 이 지침을 따라 확인할 수 있습니다.
또한, <region>
과 <service_name>
은 serverless.yml
에서 다음과 같이 정의됩니다.
service: my-service
provider:
name: aws
region: us-east-1
위의 serverless.yml
에서 <region>
은 us-east-1
이고, <service_name>
은 my-service
입니다.
위의 IAM 정책 템플릿은 서버리스 프로젝트의 이름과 배포된 리전을 기반으로 AWS 서비스에 대한 접근을 제한합니다.
이 정책은 최소한의 Serverless Framework 프로젝트에 충분한 권한을 제공합니다. 그러나 serverless.yml에서 추가 리소스를 프로비저닝하거나, Serverless 플러그인을 설치하거나, 애플리케이션 코드에서 AWS API를 호출하는 경우, 해당 변경 사항을 수용하기 위해 IAM 정책을 업데이트해야 합니다. 이 정책의 출처에 대한 자세한 내용은 Serverless IAM Deployment Policy에 대한 심층 논의를 참조하세요.
For help and discussion
Comments on this chapter