IAM許可境界ポリシーとは
管理ポリシーを使用してアイデンティティベースのポリシーがIAMエンティティに付与できるアクセス許可の境界により、エンティティは、アイデンティティベースのポリシーとそのアクセス許可の境界の両方で許可されているアクションのみ実行できる。
??
まぁ簡潔にいうと下記の模様
IAMポリシー & 許可境界ポリシー = 許可権限
※アンド条件のためどちらにも許可が含まれていないと許可されない
やること
S3と2つのLambdaを作成し、1つ目のLambdaにはS3からオブジェクトを取得できるポリシーを付与、2つ目のLambdaには1つ目と同じポリシーを付与し境界ポリシーでは取得ポリシーは付与しない形で作成し、1つ目のLambdaではS3からオブジェクトを取得でき、2つ目のLambdaでは取得できないという検証を行う。
実践
1.環境作成
1-1.下記CloudFormationを実行
AWSTemplateFormatVersion: '2010-09-09' Parameters: BucketName: Type: String Description: 'The name of the S3 bucket' Default: 'my-default-s3-bucket' Resources: MyBucket: Type: 'AWS::S3::Bucket' Properties: BucketName: !Ref BucketName LambdaS3GetBoundaryPolicy: Type: 'AWS::IAM::ManagedPolicy' Properties: PolicyDocument: Version: '2012-10-17' Statement: - Effect: 'Allow' Action: - 'logs:*' - 's3:ListBucket' Resource: '*' LambdaExecutionRole: Type: 'AWS::IAM::Role' Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: 'Allow' Principal: Service: 'lambda.amazonaws.com' Action: 'sts:AssumeRole' Policies: - PolicyName: 'LambdaS3AccessPolicy' PolicyDocument: Version: '2012-10-17' Statement: - Effect: 'Allow' Action: - 's3:GetObject' Resource: - !Sub 'arn:aws:s3:::${BucketName}/*' LambdaExecutionRoleWithBoundary: Type: 'AWS::IAM::Role' Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: 'Allow' Principal: Service: 'lambda.amazonaws.com' Action: 'sts:AssumeRole' Policies: - PolicyName: 'LambdaS3AccessPolicy' PolicyDocument: Version: '2012-10-17' Statement: - Effect: 'Allow' Action: - 's3:GetObject' Resource: - !Sub 'arn:aws:s3:::${BucketName}/*' PermissionsBoundary: !Ref LambdaS3GetBoundaryPolicy LambdaFunction1: Type: 'AWS::Lambda::Function' Properties: FunctionName: 'LambdaFunction1' Handler: 'index.handler' Role: !GetAtt LambdaExecutionRole.Arn Code: ZipFile: | import boto3 import os def handler(event, context): s3 = boto3.client('s3') bucket_name = os.environ['BUCKET_NAME'] key = 'test.txt' try: response = s3.get_object(Bucket=bucket_name, Key=key) data = response['Body'].read().decode('utf-8') print('Data:', data) except Exception as e: print('Error:', str(e)) Runtime: 'python3.9' Environment: Variables: BUCKET_NAME: !Ref BucketName LambdaFunction2: Type: 'AWS::Lambda::Function' Properties: FunctionName: 'LambdaFunction2' Handler: 'index.handler' Role: !GetAtt LambdaExecutionRoleWithBoundary.Arn Code: ZipFile: | import boto3 import os def handler(event, context): s3 = boto3.client('s3') bucket_name = os.environ['BUCKET_NAME'] key = 'test.txt' try: response = s3.get_object(Bucket=bucket_name, Key=key) data = response['Body'].read().decode('utf-8') print('Data:', data) except Exception as e: print('Error:', str(e)) Runtime: 'python3.9' Environment: Variables: BUCKET_NAME: !Ref BucketName
※1つ目のLambdaのロールには許可境界ポリシーはなし
※2つ目のLambdaのロールには許可境界ポリシーはあり
ただし許可境界ポリシーにはGetがないためオブジェクトは取得できない想定
2.準備
2-1.「test.txt」という名前のファイルを適当に作成し、作成したS3バケットにアップロード
3.Lambda実行
3-1.Lambda1でテストを実行し、test.txtの中身が取得できることを確認
※テストの中身はデフォルトで可
3-2.Lambda2でテストを実行し、AccessDenyでデータが取得できないことを確認
感想
ポリシーに追加したらよさそうだが、数が多くなると許可境界ポリシーが役に立つらしい。