Skip to content

Commit

Permalink
Add Continuous Integration (CI) as GitHub Action
Browse files Browse the repository at this point in the history
Running the tests for this project requires read access to
s3://facia-tool-store/DEV/, so we need to provide the GitHub Action
with AWS credentials for a AWS role that allows that.

We're using https://github.com/aws-actions/configure-aws-credentials
to grant the credentials, and https://github.com/guardian/cdk to
create the AWS Role (as we're adding cdk, we get half a dozen new files
in the new `cdk` folder!).

Specific IAM permissions required
---------------------------------

Even though all the FAPI client does, in terms of S3 API calls,
is call `getObject`, we need more than the `s3:GetObject`
permission. We also need `s3:ListBucket` because FAPI sometimes
has to request objects that don't exist ...and without
`s3:ListBucket`, S3 will throw a `AccessDenied` error even tho'
you're possess the `s3:GetObject permission`:

https://stackoverflow.com/a/56027548/438886

Abusing the repositories field
------------------------------

Try to be specific to grant just this repo permissions

Note that I seem to be having to abuse the `repositories` field a bit (is
this field badly named?) in order to get this
`repo:guardian/facia-scala-client:*` value:

```
          - Action: sts:AssumeRoleWithWebIdentity
            Condition:
              StringLike:
                token.actions.githubusercontent.com:sub: repo:guardian/facia-scala-client:*

```

...which is apparently the format required:

aws-actions/configure-aws-credentials#306 (comment)

Co-authored-by: Akash Askoolum <[email protected]>
  • Loading branch information
rtyley and Akash Askoolum committed Jun 24, 2022
1 parent ca608a4 commit be0504a
Show file tree
Hide file tree
Showing 9 changed files with 8,302 additions and 0 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: CI
on:
pull_request:
workflow_dispatch:
push:
branches:
- main
jobs:
CI:
runs-on: ubuntu-latest
permissions:
id-token: write # Needed to interact with GitHub's OIDC Token endpoint
contents: read
steps:
- uses: actions/checkout@v3
- uses: aws-actions/configure-aws-credentials@v1 # Needed for S3 read access for the tests!
with:
# The AWS role is configured as a GitHUb Repo secret, the value is the cloudformation-output of the
# 'Facia-Scala-Client-CI-Role-Provider' cloudformation stack
role-to-assume: ${{ secrets.AWS_ROLE_FOR_TESTS }}
aws-region: eu-west-1
- uses: coursier/cache-action@v6
- uses: olafurpg/setup-scala@v13
with:
java-version: [email protected]
- name: Build and Test
run: sbt test
11 changes: 11 additions & 0 deletions cdk/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
*.js
!jest.config.js
!jest.setup.js
!.eslintrc.js
*.d.ts
node_modules
dist

# CDK asset staging directory
.cdk.staging
cdk.out
5 changes: 5 additions & 0 deletions cdk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Infrastructure

This directory defines the components to be deployed to AWS.

See [`package.json`](./package.json) for a list of available scripts.
9 changes: 9 additions & 0 deletions cdk/bin/cdk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import 'source-map-support/register';
import { App } from 'aws-cdk-lib';
import { FaciaScalaClientTesting } from '../lib/facia-scala-client-testing';

const app = new App();
new FaciaScalaClientTesting(app, 'FaciaScalaClientTesting-INFRA', {
stack: 'facia-scala-client',
stage: 'INFRA',
});
7 changes: 7 additions & 0 deletions cdk/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"app": "npx ts-node bin/cdk.ts",
"context": {
"aws-cdk:enableDiffNoFail": "true",
"@aws-cdk/core:stackRelativeExports": "true"
}
}
36 changes: 36 additions & 0 deletions cdk/lib/facia-scala-client-testing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {join} from 'path';
import type {GuStackProps} from '@guardian/cdk/lib/constructs/core';
import {GuStack} from '@guardian/cdk/lib/constructs/core';
import type {App} from 'aws-cdk-lib';
import {CfnInclude} from 'aws-cdk-lib/cloudformation-include';
import {GuGithubActionsRole} from "@guardian/cdk/lib/constructs/iam";
import {
GuGithubActionsRepositoryCondition,
GuGithubActionsRoleProps
} from "@guardian/cdk/lib/constructs/iam/roles/github-actions";
import {GuPolicy} from "@guardian/cdk/lib/constructs/iam/policies";
import {GuAllowPolicy, GuAllowPolicyProps} from "@guardian/cdk/lib/constructs/iam/policies/base-policy";

export class FaciaScalaClientTesting extends GuStack {
constructor(scope: App, id: string, props: GuStackProps) {
super(scope, id, props);
let fapiBucketArn = "arn:aws:s3:::facia-tool-store"
new GuGithubActionsRole(this, {
policies: [new GuAllowPolicy(
this,
"fapi-s3-bucket-access",
{
actions: ["s3:GetObject","s3:ListBucket"],
resources: [
fapiBucketArn, // bucket resource specified for s3:ListBucket
`${fapiBucketArn}/DEV/*` // object resource specified for s3:GetObject
]
}
)],
condition: {
githubOrganisation: "guardian",
repositories: "facia-scala-client:*"
}
})
}
}
Loading

0 comments on commit be0504a

Please sign in to comment.