# 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
