# GitClassic read-only access to CodeCommit, template v1.
#
# Creates ONE IAM role in your account that GitClassic (AWS account 692859917589)
# can use, for at most an hour at a time, to show your CodeCommit repositories:
# files, branches, commits, diffs and pull requests. Every permission is a read.
# It can't clone a repository (no codecommit:GitPull) or change anything.
#
# - GitClassic never receives access keys. It asks AWS STS for a short-lived session
# on this role, and only when the request carries your connection's ExternalId.
# - Each session is stamped with the GitClassic user's email (sts:SetSourceIdentity),
# so every call shows up in your CloudTrail under the person who made it.
# - RepoPrefix limits it to repositories whose names start with that prefix.
# - To revoke access, delete this stack. It takes effect immediately.
#
# Plain-English version: https://gitclassic.com/security
AWSTemplateFormatVersion: '2010-09-09'
Description: >-
GitClassic read-only access (v1). One IAM role that GitClassic can use to view
your CodeCommit repositories and pull requests. Delete this stack to revoke access.
Parameters:
ConnectionId:
Type: String
Description: Identifies this connection in GitClassic. Filled in for you.
AllowedPattern: '[0-9a-f]{8}'
ExternalId:
Type: String
Description: GitClassic must present this value to use the role. Filled in for you.
AllowedPattern: '[0-9a-f]{32}'
RepoPrefix:
Type: String
Default: ''
Description: Only repositories whose names start with this. Leave empty for every repository.
AllowedPattern: '[\w.-]{0,100}'
Resources:
ViewerRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub 'gitclassic-viewer-${ConnectionId}'
Description: Read-only CodeCommit access for GitClassic (gitclassic.com). Delete the CloudFormation stack to revoke.
MaxSessionDuration: 3600
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
# GitClassic may use this role only with your ExternalId, and only when the
# session names the GitClassic user it's for (so CloudTrail always can).
- Sid: GitClassicWithExternalId
Effect: Allow
Principal:
AWS: 'arn:aws:iam::692859917589:root'
Action: sts:AssumeRole
Condition:
StringEquals:
sts:ExternalId: !Ref ExternalId
'Null':
sts:SourceIdentity: 'false'
# Lets that session carry the user's email as its source identity. On its
# own it grants nothing: it only applies within an AssumeRole allowed above.
- Sid: NameTheUser
Effect: Allow
Principal:
AWS: 'arn:aws:iam::692859917589:root'
Action: sts:SetSourceIdentity
Policies:
- PolicyName: gitclassic-viewer
PolicyDocument:
Version: '2012-10-17'
Statement:
# List your repositories and the regions they could be in
- Sid: ListRepositories
Effect: Allow
Action:
- codecommit:ListRepositories
- account:ListRegions
Resource: '*'
# View repositories and branches
- Sid: ViewRepositories
Effect: Allow
Action:
- codecommit:BatchGetRepositories
- codecommit:GetRepository
- codecommit:ListBranches
- codecommit:GetBranch
Resource: !Sub 'arn:aws:codecommit:*:${AWS::AccountId}:${RepoPrefix}*'
# Read files and folders
- Sid: ReadCode
Effect: Allow
Action:
- codecommit:GetFolder
- codecommit:GetFile
- codecommit:GetBlob
Resource: !Sub 'arn:aws:codecommit:*:${AWS::AccountId}:${RepoPrefix}*'
# Read commits and what changed in them
- Sid: ReadHistory
Effect: Allow
Action:
- codecommit:GetCommit
- codecommit:BatchGetCommits
- codecommit:GetDifferences
- codecommit:ListFileCommitHistory
Resource: !Sub 'arn:aws:codecommit:*:${AWS::AccountId}:${RepoPrefix}*'
# Read pull requests
- Sid: ReadPullRequests
Effect: Allow
Action:
- codecommit:ListPullRequests
- codecommit:GetPullRequest
- codecommit:DescribePullRequestEvents
- codecommit:GetCommentsForPullRequest
- codecommit:GetCommentsForComparedCommit
- codecommit:GetComment
- codecommit:GetCommentReactions
- codecommit:GetPullRequestApprovalStates
- codecommit:EvaluatePullRequestApprovalRules
- codecommit:GetPullRequestOverrideState
- codecommit:GetMergeOptions
- codecommit:GetMergeConflicts
- codecommit:DescribeMergeConflicts
- codecommit:BatchDescribeMergeConflicts
Resource: !Sub 'arn:aws:codecommit:*:${AWS::AccountId}:${RepoPrefix}*'
# Read repositories encrypted with your own KMS key
- Sid: DecryptViaCodeCommit
Effect: Allow
Action:
- kms:Decrypt
Resource: '*'
Condition:
StringLike:
'kms:ViaService': 'codecommit.*.amazonaws.com'
Tags:
- Key: gitclassic:connection
Value: !Ref ConnectionId
- Key: gitclassic:template-version
Value: '1'
Outputs:
RoleArn:
Description: The role GitClassic uses. GitClassic finds it on its own; nothing to copy.
Value: !GetAtt ViewerRole.Arn
# GitClassic editor access to CodeCommit, template v2.
#
# OPTIONAL. Creates a second IAM role, used only when someone on your team makes a
# change in GitClassic: commenting on, approving, merging, opening or closing a
# pull request; editing, adding or deleting a file (one commit at a time);
# creating a branch; or creating a repository. Viewing keeps using the read-only
# role, which this doesn't change.
#
# - Same rules as the read-only role: no access keys, your ExternalId required,
# at most an hour per session, and every session names the GitClassic user who
# took the action, so each change shows up in CloudTrail and in CodeCommit under
# that person.
# - RepoPrefix limits it to repositories whose names start with that prefix
# (including the names of repositories it creates).
# - ProtectedBranches (comma-separated, e.g. main,release): AWS refuses direct
# commits to those branches, so changes to them go through a pull request.
# Merging an approved pull request into them still works.
# - It can't push with git, force-push, rewrite history, delete branches or
# repositories, rename repositories, or change approval rules, and merges still
# have to meet your approval rules.
# - Issues and boards live in one DynamoDB table in your account, created here
# (gitclassic-issues-<ConnectionId>, on-demand, point-in-time recovery on). The
# role can use only that table. Deleting this stack KEEPS the table and your
# issues; delete the table yourself if you want them gone.
# - To turn editing off, delete this stack. Viewing keeps working.
#
# Plain-English version: https://gitclassic.com/security#editor
AWSTemplateFormatVersion: '2010-09-09'
Description: >-
GitClassic editor access (v2). An optional role that lets GitClassic work on pull
requests, commit edits made in its editor, create branches and repositories, and keep issues and
boards in a DynamoDB table in this account, when a user asks. Delete this stack to turn editing off
(the issues table is kept).
Parameters:
ConnectionId:
Type: String
Description: Identifies this connection in GitClassic. Filled in for you.
AllowedPattern: '[0-9a-f]{8}'
ExternalId:
Type: String
Description: GitClassic must present this value to use the role. Filled in for you.
AllowedPattern: '[0-9a-f]{32}'
RepoPrefix:
Type: String
Default: ''
Description: Only repositories whose names start with this. Leave empty for every repository.
AllowedPattern: '[\w.-]{0,100}'
ProtectedBranches:
Type: String
Default: ''
Description: Branches that only change through pull requests (comma-separated, e.g. main,release). Leave empty to allow direct commits everywhere.
AllowedPattern: '(|[\w./-]+(,[\w./-]+)*)'
CreateIssuesTable:
Type: String
Default: 'true'
AllowedValues: ['true', 'false']
Description: "'false' only when the issues table from an earlier editor stack is still in this account (GitClassic fills this in)."
Conditions:
HasProtectedBranches: !Not [!Equals [!Ref ProtectedBranches, '']]
CreatesIssuesTable: !Equals [!Ref CreateIssuesTable, 'true']
Resources:
EditorRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub 'gitclassic-editor-${ConnectionId}'
Description: Editing for GitClassic (gitclassic.com). Delete the CloudFormation stack to turn it off.
MaxSessionDuration: 3600
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
# GitClassic may use this role only with your ExternalId, and only when the
# session names the GitClassic user it's for (so CloudTrail always can).
- Sid: GitClassicWithExternalId
Effect: Allow
Principal:
AWS: 'arn:aws:iam::692859917589:root'
Action: sts:AssumeRole
Condition:
StringEquals:
sts:ExternalId: !Ref ExternalId
'Null':
sts:SourceIdentity: 'false'
# Lets that session carry the user's email as its source identity. On its
# own it grants nothing: it only applies within an AssumeRole allowed above.
- Sid: NameTheUser
Effect: Allow
Principal:
AWS: 'arn:aws:iam::692859917589:root'
Action: sts:SetSourceIdentity
Policies:
- PolicyName: gitclassic-editor
PolicyDocument:
Version: '2012-10-17'
Statement:
# Comment on pull requests
- Sid: CommentOnPullRequests
Effect: Allow
Action:
- codecommit:PostCommentForPullRequest
- codecommit:PostCommentReply
- codecommit:PostCommentForComparedCommit
- codecommit:UpdateComment
- codecommit:DeleteCommentContent
- codecommit:PutCommentReaction
Resource: !Sub 'arn:aws:codecommit:*:${AWS::AccountId}:${RepoPrefix}*'
# Approve pull requests
- Sid: ApprovePullRequests
Effect: Allow
Action:
- codecommit:UpdatePullRequestApprovalState
Resource: !Sub 'arn:aws:codecommit:*:${AWS::AccountId}:${RepoPrefix}*'
# Merge pull requests
- Sid: MergePullRequests
Effect: Allow
Action:
- codecommit:MergePullRequestByFastForward
- codecommit:MergePullRequestBySquash
- codecommit:MergePullRequestByThreeWay
Resource: !Sub 'arn:aws:codecommit:*:${AWS::AccountId}:${RepoPrefix}*'
# Open, close and edit pull requests
- Sid: ManagePullRequests
Effect: Allow
Action:
- codecommit:CreatePullRequest
- codecommit:UpdatePullRequestStatus
- codecommit:UpdatePullRequestTitle
- codecommit:UpdatePullRequestDescription
Resource: !Sub 'arn:aws:codecommit:*:${AWS::AccountId}:${RepoPrefix}*'
# Commit changes made in GitClassic
- Sid: CommitChanges
Effect: Allow
Action:
- codecommit:PutFile
- codecommit:CreateCommit
- codecommit:DeleteFile
Resource: !Sub 'arn:aws:codecommit:*:${AWS::AccountId}:${RepoPrefix}*'
# Create branches
- Sid: CreateBranches
Effect: Allow
Action:
- codecommit:CreateBranch
Resource: !Sub 'arn:aws:codecommit:*:${AWS::AccountId}:${RepoPrefix}*'
# Create repositories
- Sid: CreateRepositories
Effect: Allow
Action:
- codecommit:CreateRepository
- codecommit:UpdateRepositoryDescription
- codecommit:UpdateDefaultBranch
Resource: !Sub 'arn:aws:codecommit:*:${AWS::AccountId}:${RepoPrefix}*'
# Keep your issues and boards
- Sid: IssuesAndBoards
Effect: Allow
Action:
- dynamodb:GetItem
- dynamodb:BatchGetItem
- dynamodb:Query
- dynamodb:PutItem
- dynamodb:UpdateItem
- dynamodb:DeleteItem
- dynamodb:DescribeTable
Resource:
- !Sub 'arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/gitclassic-issues-${ConnectionId}'
- !Sub 'arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/gitclassic-issues-${ConnectionId}/index/*'
# Write to repositories encrypted with your own KMS key
- Sid: UseKeyViaCodeCommit
Effect: Allow
Action:
- kms:Decrypt
- kms:Encrypt
- kms:GenerateDataKey
Resource: '*'
Condition:
StringLike:
'kms:ViaService': 'codecommit.*.amazonaws.com'
Tags:
- Key: gitclassic:connection
Value: !Ref ConnectionId
- Key: gitclassic:template-version
Value: '2'
# Issues, comments and board status. Kept when this stack is deleted (Retain), so
# turning editing off never loses issues; point-in-time recovery covers mistakes.
IssuesTable:
Type: AWS::DynamoDB::Table
Condition: CreatesIssuesTable
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Properties:
TableName: !Sub 'gitclassic-issues-${ConnectionId}'
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: PK
AttributeType: S
- AttributeName: SK
AttributeType: S
- AttributeName: GSI1PK
AttributeType: S
- AttributeName: GSI1SK
AttributeType: S
KeySchema:
- AttributeName: PK
KeyType: HASH
- AttributeName: SK
KeyType: RANGE
GlobalSecondaryIndexes:
- IndexName: GSI1
KeySchema:
- AttributeName: GSI1PK
KeyType: HASH
- AttributeName: GSI1SK
KeyType: RANGE
Projection:
ProjectionType: ALL
PointInTimeRecoverySpecification:
PointInTimeRecoveryEnabled: true
Tags:
- Key: gitclassic:connection
Value: !Ref ConnectionId
# Only while ProtectedBranches is set: no direct commits to those branches.
# An explicit Deny overrides the Allow above.
ProtectedBranchesPolicy:
Type: AWS::IAM::RolePolicy
Condition: HasProtectedBranches
Properties:
RoleName: !Ref EditorRole
PolicyName: gitclassic-editor-protected-branches
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: NoDirectCommitsToProtectedBranches
Effect: Deny
Action:
- codecommit:PutFile
- codecommit:CreateCommit
- codecommit:DeleteFile
Resource: '*'
Condition:
StringEqualsIfExists:
'codecommit:References': !Split
- ','
- !Sub
- 'refs/heads/${Joined}'
- Joined: !Join [',refs/heads/', !Split [',', !Ref ProtectedBranches]]
'Null':
'codecommit:References': 'false'
Outputs:
RoleArn:
Description: The role GitClassic uses for changes. GitClassic finds it on its own; nothing to copy.
Value: !GetAtt EditorRole.Arn