Skip to content

Commit 91f60f2

Browse files
feat: Adding delegated repo setup (#2196)
* feat: Adding delegated repo setup * Update docs/2.0/docs/pipelines/guides/setup-delegated-repo.mdx Co-authored-by: Lewis Christie <[email protected]> --------- Co-authored-by: Lewis Christie <[email protected]>
1 parent 52d4841 commit 91f60f2

File tree

4 files changed

+221
-2
lines changed

4 files changed

+221
-2
lines changed

docs/2.0/docs/accountfactory/guides/delegated-repositories.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import PersistentCheckbox from '/src/components/PersistentCheckbox';
33

44
:::note
5-
Delegated Repositories are only available to DevOps Foundations Enterprise customers.
5+
Vending Delegated Repositories by Account Factory is only available to DevOps Foundations Enterprise customers.
66
:::
77

88
## Introduction
@@ -64,7 +64,7 @@ Select Run Workflow on the right, and paste the JSON payload into the input. Run
6464

6565
The result of the Account Factory Workflow run will be a new Pull Request, adding a new YAML file in the `_new-account-requests` directory.
6666

67-
If everything looks as expected you can merge the pull request. Once the commit is on your main branch Pipelines will begin running a `terragrunt apply` that will create the new account in AWS.
67+
If everything looks as expected you can merge the pull request. Once the commit is on your main branch Pipelines will begin running a `terragrunt apply` that will create the new account in AWS.
6868

6969
You can view the workflow run on the main branch. Provisioning the account(s) can take around 10 minutes to complete. Once the account has been created another Pull Request will be created in the `infrastructure-live-root` repository to baseline the new account.
7070

docs/2.0/docs/pipelines/concepts/security.md

Whitespace-only changes.
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
import CustomizableValue from '/src/components/CustomizableValue'
2+
3+
# Setup a Delegated Repository
4+
5+
:::note
6+
[Automatic vending of delegated repositories by Account Factory](../../accountfactory/guides/delegated-repositories.md) is an Enterprise-only feature.
7+
8+
If you are an Enterprise customer, Account Factory will automatically provision delegated repositories for you, and you may not need to follow the steps in this guide. The steps in this guide are for customers who are looking to manually set up delegated repositories, or for customers who are looking to understand how the process works from the perspective of Pipelines.
9+
:::
10+
11+
## Introduction
12+
13+
Infrastructure management delegation is a first-class concept in DevOps Foundations. To learn more about delegated repositories, click [here](../../accountfactory/architecture/#delegated-repositories).
14+
15+
Reasons you might want to delegate management of infrastructure includes:
16+
17+
- A different team is autonomously working on parts of infrastructure relevant to a specific account.
18+
- A GitHub Actions workflow in a repository needs to be able to make limited changes to infrastructure in a specific account.
19+
20+
e.g. A repository has application code relevant to a container image that needs to be built and pushed to AWS ECR before it can be used in a Kubernetes cluster via a new deployment.
21+
22+
The following guide assumes that you have already gone through [Pipelines Setup & Installation](../installation/prerequisites/awslandingzone.md).
23+
24+
## Step 1 - Ensure the delegated account is set up
25+
26+
Ensure that the account you want to delegate management for is set up. This includes the following:
27+
28+
1. The account is created in AWS.
29+
2. An OIDC provider is set up in the account.
30+
3. The account has the following roles provisioned:
31+
- `infrastructure-live-access-control-plan`
32+
- `infrastructure-live-access-control-apply`
33+
34+
If the account was provisioned normally using Account Factory, these roles should already be set up.
35+
36+
If you want more information about exactly how this works, read [GitHub OIDC docs](https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services).
37+
38+
## Step 2 - Ensure that the `infrastructure-live-access-control` repository is provisioned.
39+
40+
The [infrastructure-live-access-control](../architecture/security-controls.md#infrastructure-access-control) repository is an optionally provisioned part of DevOps Foundations, and it's the recommended way of delegating access to infrastructure.
41+
42+
If you don't have this repository set up, you can follow the steps in the [infrastructure-live-root-template](https://github.com/gruntwork-io/infrastructure-live-root-template) to provision it.
43+
44+
This repository will be where you manage the IAM access that your delegated repository will have.
45+
46+
## Step 3 - Provision the delegated role
47+
48+
To provision a role that can be assumed by the delegated repository, you will want to add it to the `infrastructure-live-access-control` repository.
49+
50+
:::tip
51+
Typically, CI roles created for Pipelines are created in pairs, one for the `plan` stage and one for the `apply` stage. This is because the `plan` stage should have more limited permissions than the `apply` stage, as plans typically only need read-only access.
52+
53+
If you are creating a role to do something like push a container image to ECR on push to the repository, you may only need a single role.
54+
:::
55+
56+
Use Terragrunt Scaffold to create the new role in your `infrastructure-live-access-control` repository.
57+
58+
```bash
59+
# Assuming your `infrastructure-live-access-control` repository is named exactly that,
60+
# and the account you want to provision your new role in is called `acme`.
61+
mkdir acme/_global/ecr-push-role
62+
cd acme/_global/ecr-push-role
63+
terragrunt scaffold '[email protected]:gruntwork-io/terraform-aws-security.git//modules/github-actions-iam-role?ref=v0.73.2'
64+
```
65+
66+
This will give you a placeholder `terragrunt.hcl` file for a new role in your repository that you can customize to your needs.
67+
68+
Alternatively, you can copy and paste the following:
69+
70+
:::note
71+
Note the value of `allowed_sources`, which should be the organization, name, and ref of the repository you are delegating to.
72+
73+
If you would like to make it so that all refs in a repository can assume this role, you can use `["*"]` as the value on the right hand side.
74+
:::
75+
76+
```hcl
77+
terraform {
78+
source = "[email protected]:gruntwork-io/terraform-aws-security.git//modules/github-actions-iam-role?ref=v0.73.2"
79+
}
80+
81+
# Include the root `terragrunt.hcl` configuration, which has settings common across all environments & components.
82+
include "root" {
83+
path = find_in_parent_folders()
84+
}
85+
86+
# Include the component configuration, which has settings that are common for the component across all environments
87+
include "envcommon" {
88+
path = "${dirname(find_in_parent_folders("common.hcl"))}/_envcommon/landingzone/delegated-pipelines-plan-role.hcl"
89+
merge_strategy = "deep"
90+
}
91+
92+
inputs = {
93+
github_actions_openid_connect_provider_arn = "arn:aws:iam::${get_aws_account_id()}:oidc-provider/token.actions.githubusercontent.com"
94+
github_actions_openid_connect_provider_url = "https://token.actions.githubusercontent.com"
95+
96+
# ----------------------------------------------------------------------------------------------------------------
97+
# This is the map of repositories to refs that are allowed to assume this role.
98+
#
99+
# Note that for a plan role, typically the only additional permissions that are required are read permissions that
100+
# grant Terragrunt permission to read the existing state in provisioned infrastructure, such that a plan of proposed
101+
# updates can be generated.
102+
#
103+
# Also note that all refs are allowed to assume this role, as the plan role is typically assumed in refs used
104+
# as sources for pull requests. Assign permissions keeping this in mind.
105+
#
106+
# Read more on least privilege below.
107+
# ----------------------------------------------------------------------------------------------------------------
108+
109+
allowed_sources = {
110+
"$$ORGANIZATION$$/$$REPO$$" : ["$$REF$$"]
111+
}
112+
113+
# ----------------------------------------------------------------------------------------------------------------
114+
# Least privilege is an important best practice, but can be a very difficult practice to engage in.
115+
#
116+
# The `envcommon` include above provides the minimal permissions required to interact with TF state, however
117+
# any further permissions are up to the user to define as needed for a given workflow.
118+
#
119+
# These permissions are meant to be continuously refined in a process of iteratively granting additional permissions
120+
# as needed to have workflows updated in CI correctly, and then removing excess permissions through continuous review.
121+
#
122+
# A common pattern used to refine permissions is to run a pipeline with a best guess at the permissions required, or
123+
# no permissions at all, and then review acccess denied errors and add the necessary permissions to have the pipeline
124+
# run successfully.
125+
#
126+
# As workload patterns become more commonplace, this repo will serve as a reference for the permissions required to
127+
# run similar workloads going forward.
128+
# ----------------------------------------------------------------------------------------------------------------
129+
130+
iam_policy = {
131+
# Role workload permissions go here
132+
}
133+
}
134+
```
135+
136+
Note the `envcommon` include, which includes the common minimal configurations recommended for delegated roles in DevOps Foundations.
137+
138+
You will likely need to expand the `iam_policy` block to include the permissions required for your specific workflow.
139+
140+
For example, if you would like permissions to push to ECR, you might add the following:
141+
142+
```hcl
143+
iam_policy = {
144+
"ECRPushPermissions" = {
145+
effect = "Allow"
146+
actions = [
147+
"ecr:CompleteLayerUpload",
148+
"ecr:UploadLayerPart",
149+
"ecr:InitiateLayerUpload",
150+
"ecr:BatchCheckLayerAvailability",
151+
"ecr:PutImage",
152+
"ecr:BatchGetImage"
153+
]
154+
resources = "arn:aws:ecr:region:${$$ACCOUNT_ID$$}:repository/$$REPOSITORY_NAME$$"
155+
},
156+
"ECRAuthorizationToken" = {
157+
effect = "Allow",
158+
actions = ["ecr:GetAuthorizationToken"]
159+
resources = ["*"]
160+
}
161+
}
162+
```
163+
164+
## Step 4 - Apply the role
165+
166+
Once you have customized the role to your needs, you can apply it by creating a pull request in the `infrastructure-live-access-control` repository.
167+
168+
```bash
169+
git add .
170+
git commit -m "feat: Add ECR push role for acme account"
171+
git push
172+
gh pr create --base main --title "feat: Add ECR push role for acme account" --body "This PR adds the ECR push role for the acme account."
173+
```
174+
175+
Inspect the pull request, verify the plan, then merge the pull request to get it applied.
176+
177+
## Step 5 - Set up the delegated repository
178+
179+
Depending on what the repository needs to do in CI, your GitHub Actions workflow may be as simple as a file like the following placed in `.github/workflows/ci.yml`:
180+
181+
```yaml
182+
name: CI
183+
on: [push]
184+
185+
permissions:
186+
id-token: write
187+
contents: read
188+
189+
jobs:
190+
build:
191+
runs-on: ubuntu-latest
192+
steps:
193+
- uses: actions/checkout@v4
194+
195+
- uses: aws-actions/configure-aws-credentials@v4
196+
with:
197+
role-to-assume: arn:aws:ecr:$$REGION$$:$$ACCOUNT_ID$$:repository/$$REPOSITORY_NAME$$
198+
role-session-name: acme-ecr-push
199+
aws-region: $$AWS_REGION$$
200+
201+
- name: Login to Amazon ECR
202+
id: login-ecr
203+
uses: aws-actions/amazon-ecr-login@v2
204+
205+
- name: Build, tag, and push docker image to Amazon ECR
206+
env:
207+
REGISTRY: ${{ steps.login-ecr.outputs.registry }}
208+
REPOSITORY: $$IMAGE_NAME$$
209+
IMAGE_TAG: ${{ github.sha }}
210+
run: |
211+
docker build -t $REGISTRY/$REPOSITORY:$IMAGE_TAG .
212+
docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG
213+
```
214+

sidebars/docs.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,11 @@ const sidebar = [
309309
type: "doc",
310310
id: "2.0/docs/pipelines/guides/terragrunt-env-vars",
311311
},
312+
{
313+
label: "Setup a Delegated Repository",
314+
type: "doc",
315+
id: "2.0/docs/pipelines/guides/setup-delegated-repo",
316+
},
312317
],
313318
},
314319
{

0 commit comments

Comments
 (0)