ソースコードを管理するリポジトリを本格的に運用しようと思うと、リポジトリへの操作に対して制限をかける必要が出てきます。AWS CodeCommitはデフォルトに提供する機能に限りがあり、リポジトリに対する制限をかけるためにいろいろと設定が必要になります。
今回はAWS CodeCommitに対する操作制限をかける方法について調査しました。
ブランチへの操作制限
ブランチへの操作制限は、専用のIAMポリシーを作成し、それをIAMユーザー・グループに紐づけることで実現できます。制限できる内容としては、特定ブランチに対する git push
や削除、マージの手法などです。
※参考
今回はシンプルに main
ブランチへの直接Pushが実行できないようIAMポリシーを作成し、それを testgroup
というIAMグループに付与することで、グループ内のIAMユーザーに操作制限を加えました。
IAMポリシーはjsonで書かれた例が多く見つかりましたが、今回はCloudFormationからYaml形式で書いた例を載せておきます。以下のようなYamlファイルを使ってリソースを作成しました。
Resources: CodeCommit: Type: AWS::CodeCommit::Repository Properties: RepositoryName: !Ref RepoName RepositoryDescription: test repo IAMPolicy: Type: 'AWS::IAM::ManagedPolicy' Properties: Description: prohibit direct push to codecommit Path: / PolicyDocument: Version: "2012-10-17" Statement: - Effect: Deny Action: 'codecommit:GitPush' Resource: '*' Condition: "StringEqualsIfExists": "codecommit:References": - "refs/heads/main" "Null": "codecommit:References": - "false" IAMUser: Type: AWS::IAM::User Properties: Groups: - !Ref IAMGroup UserName: !Ref UserName LoginProfile: Password: !Ref UserPassword PasswordResetRequired: "false" IAMGroup: Type: AWS::IAM::Group Properties: GroupName: !Ref GroupName ManagedPolicyArns: - !Ref IAMPolicy - "arn:aws:iam::aws:policy/AWSCodeCommitPowerUser"
※参考
- AWS CodeCommitを使った感想
- [アップデート]CodeCommitでプルリクエストの承認ルールワークフローを試してみた
- GitHub - sqlxpert/aws-tag-sched-ops: aws_tag_sched_ops.yaml
承認ルールテンプレート
承認ルールテンプレートはCodeCommitの機能として備わっており、マネジメントコンソールから作成・管理することができます。
また承認ルールテンプレートの作成は、公式には提供されていないものの、CloudFormationの拡張機能を利用し、コミュニティの公開するパッケージを利用することで、CloudFormationテンプレートからの作成が可能になります。
今回はあまり紹介する例の見当たらなかった、CloudFormationのほうで作ってみました。登録するリソースタイプは Community::CodeCommit::ApprovalRuleTemplate
Community::CodeCommit::RepositoryAssociation
の2つです。
まずCloudFormationを利用する準備をするため、実行用のロールの作成とCloudFormationタイプの登録を行います。
# IAMロールの作成 $ aws cloudformation create-stack \ --template-url https://community-resource-provider-catalog.s3.amazonaws.com/community-codecommit-approvalruletemplate-resource-role-0.1.0.yml \ --stack-name community-codecommit-approvalruletemplate-resource-role \ --capabilities CAPABILITY_IAM $ aws cloudformation create-stack \ --template-url https://community-resource-provider-catalog.s3.amazonaws.com/community-codecommit-repositoryassociation-resource-role-0.1.0.yml \ --stack-name community-codecommit-repositoryassociation-resource-role \ --capabilities CAPABILITY_IAM # CloudFormationタイプの登録 $ aws cloudformation register-type \ --region "ap-northeast-1" \ --type-name "Community::CodeCommit::ApprovalRuleTemplate" \ --schema-handler-package "s3://community-resource-provider-catalog/community-codecommit-approvalruletemplate-0.1.0.zip" \ --type RESOURCE \ --execution-role-arn <ApprovalRuleTemplate用のロールARNを指定> $ aws cloudformation register-type \ --region "ap-northeast-1" \ --type-name "Community::CodeCommit::RepositoryAssociation" \ --schema-handler-package "s3://community-resource-provider-catalog/community-codecommit-repositoryassociation-0.1.0.zip" \ --type RESOURCE \ --execution-role-arn <RepositoryAssociation用のロールARNを指定>
タイプ登録後は以下のようにコマンドを実行し、登録の進行状況を確認できます。 aws cloudformation register-type
コマンド実行後に RegistrationToken
という出力があるので、そこに表示されたトークンを指定します。
$ aws cloudformation describe-type-registration --registration-token <RegistrationToken> { "ProgressStatus": "IN_PROGRESS", "Description": "Deployment is currently in DEPLOY_STAGE of status IN_PROGRESS; ", "TypeArn": "arn:aws:cloudformation:ap-northeast-1:111111111111:type/resource/Community-CodeCommit-ApprovalRuleTemplate", "TypeVersionArn": "arn:aws:cloudformation:ap-northeast-1:111111111111:type/resource/Community-CodeCommit-ApprovalRuleTemplate/00000005" } $ aws cloudformation describe-type-registration --registration-token <RegistrationToken> { "ProgressStatus": "COMPLETE", "Description": "Deployment is currently in DEPLOY_STAGE of status COMPLETED; ", "TypeArn": "arn:aws:cloudformation:ap-northeast-1:111111111111:type/resource/Community-CodeCommit-ApprovalRuleTemplate", "TypeVersionArn": "arn:aws:cloudformation:ap-northeast-1:111111111111:type/resource/Community-CodeCommit-ApprovalRuleTemplate/00000005" }
なお、CloudFormationタイプはバージョン情報を含んでおり、何度か登録を繰り返すとバージョンが更新されます。ただしデフォルトで利用するタイプを明示的に変更しないと、CloudFormationからリソースを作成する際に使われるバージョンが古いものになるため、バージョンの変更が必要な場合は、以下のようにバージョンの確認と更新を行います。
# バージョン一覧の取得 $ aws cloudformation list-type-versions --type RESOURCE --type-name "Community::CodeCommit::RepositoryAssociation" { "TypeVersionSummaries": [ { "Type": "RESOURCE", "TypeName": "Community::CodeCommit::RepositoryAssociation", "VersionId": "00000001", "IsDefaultVersion": true, "Arn": "arn:aws:cloudformation:ap-northeast-1:111111111111:type/resource/Community-CodeCommit-RepositoryAssociation/00000001", "TimeCreated": "2022-01-06T15:02:17.280000+00:00", "Description": "Resource that allows for the association of a particular approval rule template to CodeCommit repositories." }, (中略) { "Type": "RESOURCE", "TypeName": "Community::CodeCommit::RepositoryAssociation", "VersionId": "00000005", "IsDefaultVersion": false, "Arn": "arn:aws:cloudformation:ap-northeast-1:111111111111:type/resource/Community-CodeCommit-RepositoryAssociation/00000005", "TimeCreated": "2022-01-07T13:27:06.992000+00:00", "Description": "Resource that allows for the association of a particular approval rule template to CodeCommit repositories." } ] } # デフォルトバージョンの指定 $ aws cloudformation set-type-default-version \ --version-id 00000005 \ --type-name Community::CodeCommit::RepositoryAssociation \ --type RESOURCE
これで承認ルールテンプレートをCloudFormationから作成できるようになったので、以下のようなファイルを使って作成します。
RuleTemplate: Type: Community::CodeCommit::ApprovalRuleTemplate Properties: Name: !Ref RuleTemplateName Description: test rule Content: Version: "2018-11-08" DestinationReferences: - "refs/heads/main" Statements: - Type: "Approvers" NumberOfApprovalsNeeded: 1 ApprovalPoolMembers: - "*" RepoAssociation: Type: Community::CodeCommit::RepositoryAssociation Properties: ApprovalRuleTemplateArn: !Ref RuleTemplate RepositoryNames: - !GetAtt CodeCommit.Name
※参考
- AWS Doc - AWS CodeCommit: Create an approval rule for a pull request
- AWS Doc - AWS CloudFormation: Using the AWS CloudFormation registry
- GitHub - org-formation/aws-resource-providers: code-commit
- GitHub - org-formation/aws-resource-providers:AWS::CodeCommit::ApprovalRuleTemplate コメント
実際の利用
ここまでで必要なリソースの作成が完了したので、作成した testuser
というIAMユーザーからCodeCommitへの操作を行います。
※リソースの作成に利用したYamlファイルはこちら。
sample-file.yaml
AWSTemplateFormatVersion: '2010-09-09' Description: codecommit Parameters: RepoName: Type: String Default: "testrepo" UserName: Type: String Default: "testuser" UserPassword: Type: String Default: "testuser@1234" GroupName: Type: String Default: "testgroup" RuleTemplateName: Type: String Default: "testrule" Resources: CodeCommit: Type: AWS::CodeCommit::Repository Properties: RepositoryName: !Ref RepoName RepositoryDescription: test repo IAMPolicy: Type: 'AWS::IAM::ManagedPolicy' Properties: Description: prohibit direct push to codecommit Path: / PolicyDocument: Version: "2012-10-17" Statement: - Effect: Deny Action: 'codecommit:GitPush' Resource: '*' Condition: "StringEqualsIfExists": "codecommit:References": - "refs/heads/main" "Null": "codecommit:References": - "false" IAMUser: Type: AWS::IAM::User Properties: Groups: - !Ref IAMGroup UserName: !Ref UserName LoginProfile: Password: !Ref UserPassword PasswordResetRequired: "false" IAMGroup: Type: AWS::IAM::Group Properties: GroupName: !Ref GroupName ManagedPolicyArns: - !Ref IAMPolicy - "arn:aws:iam::aws:policy/AWSCodeCommitPowerUser" RuleTemplate: Type: Community::CodeCommit::ApprovalRuleTemplate Properties: Name: !Ref RuleTemplateName Description: test rule Content: Version: "2018-11-08" DestinationReferences: - "refs/heads/main" Statements: - Type: "Approvers" NumberOfApprovalsNeeded: 1 ApprovalPoolMembers: - "*" RepoAssociation: Type: Community::CodeCommit::RepositoryAssociation Properties: ApprovalRuleTemplateArn: !Ref RuleTemplate RepositoryNames: - !GetAtt CodeCommit.Name
まずはIAMユーザー画面に移動し、CodeCommitへのアクセス情報を取得します。次にCodeCommitで利用するファイルを適当に用意します。
ローカルの環境から testuser
を使ってCodeCommitリポジトリの取得を行います。
$ git clone https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/testrepo Cloning into 'testrepo'... Username for 'https://git-codecommit.ap-northeast-1.amazonaws.com': testuser-at-111111111111 Password for 'https://testuser-at-111111111111@git-codecommit.ap-northeast-1.amazonaws.com': remote: Counting objects: 3, done. Unpacking objects: 100% (3/3), done. $ cd testrepo/ $ git branch * main
ここで README.md
を適当に編集し、 main
ブランチへ直接Pushをしてみます。するとエラーが発生し、 main
への直接Pushができないことが確認できます。
$ vi README.md $ cat README.md # testrepo 20220108 $ git add . $ git commit -m "initial commit" [main 9390f5b] initial commit 1 file changed, 3 insertions(+), 1 deletion(-) $ git push origin main Username for 'https://git-codecommit.ap-northeast-1.amazonaws.com': testuser-at-111111111111 Password for 'https://testuser-at-111111111111@git-codecommit.ap-northeast-1.amazonaws.com': Counting objects: 3, done. Writing objects: 100% (3/3), 262 bytes | 131.00 KiB/s, done. Total 3 (delta 0), reused 0 (delta 0) To https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/testrepo ! [remote rejected] main -> main (You don't have permission to push changes to this branch.) error: failed to push some refs to 'https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/testrepo'
ここでは test-branch
というブランチから、変更をコミットします。
$ git checkout -b test-branch Switched to a new branch 'test-branch' $ git push origin test-branch Username for 'https://git-codecommit.ap-northeast-1.amazonaws.com': testuser-at-111111111111 Password for 'https://testuser-at-111111111111@git-codecommit.ap-northeast-1.amazonaws.com': Counting objects: 3, done. Writing objects: 100% (3/3), 262 bytes | 131.00 KiB/s, done. Total 3 (delta 0), reused 0 (delta 0) To https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/testrepo * [new branch] test-branch -> test-branch
CodeCommitの画面に移動し、Pull Requestを作成します。すると承認ルールテンプレートに記載した内容の通り、1件の承認がないとマージができないよう表示されます。
ここで別のユーザーで再ログインし、承認を行うことで、マージが可能になります。
※参考