stratospheric-dev / stratospheric

All you need to know to get your Spring Boot application into production with AWS πŸƒ
https://stratospheric.dev
Apache License 2.0
262 stars 187 forks source link

Setting up the Technical GitHub Actions IAM User #185

Closed Partyschaum closed 1 year ago

Partyschaum commented 1 year ago

What can we improve?

Hi,

I want to enable/automate the deployment of the project to my personal AWS account. In the appendix you mention to create an IAM user for this but not how to achieve this.

I am facing the following problems:

Any help appreciated! πŸ™

[^1]: I obtained the list of AWS managed policies with aws iam list-policies | jq -r '.Policies[] | .PolicyName'

Version

Revision 1.9 (2022-10-04)

Suggested Changes

Please give some explanation on how to create this IAM user, either by providing a CloudFormation stack (YAML/JSON file or in code using CDK) or with a short step by step guide for the AWS console.

BjoernKW commented 1 year ago

Thanks for the feedback! Could you please try and use these AWS-managed policies instead?

The AWS-managed AmazonEC2ContainerServiceFullAccess policy has been phased out (see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/security-iam-awsmanpol-amazonecs-full-access-migration.html )

Both Permissive_CloudFormation_permissions and Manage_Cognito_user_pools are custom policies we've set up ourselves (and which therefore won't work out of the box; so, thanks again for notifying us about this issue). The default AWS policies mentioned above are somewhat more permissive in that they allow actions which are probably not required by our setup, but they're easier to get started with than by setting up those custom policies in the IAM console individually.

I know this runs against the principle of least privilege. Hence, we'll consider describing these more restrictive permission sets in a future edition of the ebook. Anyway, the next minor release of the ebook will contain a modified list of policies including the ones mentioned above.

Partyschaum commented 1 year ago

Thank you so much for the fast response. πŸ’š πŸš€

It works now. πŸ‘

Partyschaum commented 1 year ago

Moin,

I just wanted to give you additional feedback on this. Today I tried to push images to my private ECR repository and got An error occurred (AccessDeniedException) when calling the GetAuthorizationToken operation: User: arn:aws:iam::***:user/github is not authorized to perform: ecr:GetAuthorizationToken on resource: * because no identity-based policy allows the ecr:GetAuthorizationToken action.

After some google-foo I found an example on Accessing One Amazon ECR Repository which I then applied to the CF stack for my GitHub user. I'm not sure if those rights are too broad but it made the login and pushing images to the private ECR repository finally possible.

Maybe you want to add this to the next minor release of the ebook too. πŸ‘

    val managedGroupPolicies = listOf(
        "AmazonEC2FullAccess",
        "AmazonECS_FullAccess",
        "AmazonCognitoPowerUser",
        "AWSCloudFormationFullAccess",
        "AWSLambda_FullAccess",
    ).map { ManagedPolicy.fromAwsManagedPolicyName(it) }

    val gitHubActionsGroup = Group(
        gitHubActionsStack,
        "GitHubActionsGroup",
        GroupProps.builder()
            .groupName(gitHubActionsGroupName)
            .managedPolicies(managedGroupPolicies)
            .build()
    ).also {
        it.addToPolicy(
            PolicyStatement.Builder.create()
                .sid("GetAuthorizationToken")
                .effect(Effect.ALLOW)
                .actions(listOf("ecr:GetAuthorizationToken"))
                .resources(listOf("*"))
                .build()
        )
        it.addToPolicy(
            PolicyStatement.Builder.create()
                .sid("ListImagesInRepository")
                .effect(Effect.ALLOW)
                .actions(listOf("ecr:ListImages"))
                .resources(listOf("*"))
                .build()
        )
        it.addToPolicy(
            PolicyStatement.Builder.create()
                .sid("ManageRepositoryContents")
                .effect(Effect.ALLOW)
                .actions(
                    listOf(
                        "ecr:BatchCheckLayerAvailability",
                        "ecr:GetDownloadUrlForLayer",
                        "ecr:GetRepositoryPolicy",
                        "ecr:DescribeRepositories",
                        "ecr:ListImages",
                        "ecr:DescribeImages",
                        "ecr:BatchGetImage",
                        "ecr:InitiateLayerUpload",
                        "ecr:UploadLayerPart",
                        "ecr:CompleteLayerUpload",
                        "ecr:PutImage",
                    )
                )
                .resources(listOf("*"))
                .build()
        )
    }

    val gitHubActionsUser = User(
        gitHubActionsStack,
        "GitHubActionsUser",
        UserProps.builder()
            .userName(gitHubActionsUserName)
            .managedPolicies(managedGroupPolicies)
            .groups(listOf(gitHubActionsGroup))
            .build()
    )
BjoernKW commented 1 year ago

Thanks for the additional feedback! The ecr:GetAuthorizationToken permissions is part of the AmazonEC2ContainerRegistryFullAccess policy, which I didn't mention in my comment (but which is listed in the appendix of the ebook).