Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
- name: Verify committed Action bundle
run: git diff --exit-code -- dist
- name: Check shell scripts
run: shellcheck scripts/*.sh
run: shellcheck scripts/*.sh test/scripts/*.sh
- name: Verify reproducible image artifact
run: |
scripts/package-runner-image.sh
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@
- Lifecycle supervisor with fresh Docker startup and self-termination.
- Direct AWS CLI bootstrap, image build tooling, CI, release SBOMs, and
examples.
- One-command Classic PAT and static IAM-user Quickstart, with OIDC and GitHub
App credentials retained as the advanced path.
39 changes: 20 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,37 @@ The Action implements and tests:
- typed GitHub and AWS adapters with mocked-boundary integration tests.

The production AL2023 runner image is implemented and validated locally and
through the AWS image build hooks with production `overlay2`. Private-repository
end-to-end validation remains a release gate.
through the AWS image build hooks with production `overlay2`. The complete
private-repository workflow is validated for success, job failure, cancellation,
startup timeout, service containers, and the maximum-duration backstop.

## Minimal setup
## Quickstart

The setup is two direct scripts. It does not require an infrastructure
framework:
Install the AWS CLI, GitHub CLI, `jq`, Docker, and Node.js 24. Authenticate both
CLIs, create a classic GitHub PAT with the `repo` scope, then run:

```bash
export AWS_REGION=us-east-1
export GITHUB_REPOSITORY=OWNER/PRIVATE_REPOSITORY

scripts/bootstrap-aws.sh
scripts/build-microvm-image.sh
scripts/setup-quickstart.sh
```

The first command idempotently creates the private S3 artifact bucket,
CloudWatch log groups, GitHub OIDC provider, and three least-privilege IAM
roles. It saves the discovered resource values to `build/aws-setup.json`. The
second command consumes that file automatically and saves the active image
details to `build/microvm-image.json`.
The script creates the AWS resources and runner image, configures the
repository, creates a dedicated IAM user, rotates its static access key directly
into GitHub Actions secrets, and prompts for the classic PAT. It does not use an
infrastructure framework or write the AWS secret access key to disk.

## Usage
The Quickstart IAM user deliberately includes bootstrap, image build, and runner
lifecycle permissions. Use it only with private repositories and trusted
workflow changes. See [advanced credentials](docs/advanced-credentials.md) to
replace both long-lived credentials with GitHub OIDC and a GitHub App.

The workflow needs an existing active MicroVM image, a least-privilege MicroVM
execution role, AWS credentials obtained through GitHub OIDC, and a short-lived
GitHub App installation token with repository Administration write access.
## Usage

Copy [examples/basic.yml](examples/basic.yml) into a private repository's
`.github/workflows/` directory, configure the referenced variables and secret,
then pin this Action and its dependencies to reviewed immutable commits.
Copy [examples/basic.yml](examples/basic.yml) into the private repository's
`.github/workflows/` directory. The Quickstart script configures every variable
and secret referenced by this workflow.

The start job emits a unique label for one target job. The runner is JIT-only
and single-use. Its supervisor self-terminates after that job; the explicit stop
Expand Down Expand Up @@ -74,6 +74,7 @@ installation.
Detailed guides:

- [installation](docs/installation.md)
- [advanced credentials](docs/advanced-credentials.md)
- [security model](docs/security.md)
- [operations and quotas](docs/operations.md)
- [testing and release gates](docs/testing.md)
Expand Down
4 changes: 2 additions & 2 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ inputs:
required: true
github-token:
description:
GitHub App installation token or compatible fine-grained PAT used to
create a repository JIT runner
Classic PAT with repo scope, compatible fine-grained PAT, or GitHub App
installation token used to create a repository JIT runner
required: false
image-id:
description: Lambda MicroVM image ARN or identifier
Expand Down
54 changes: 54 additions & 0 deletions docs/advanced-credentials.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Advanced credentials

The advanced path replaces the Quickstart's static AWS access key and classic
GitHub PAT with short-lived credentials. Runner behavior and AWS resources are
otherwise identical.

## 1. Create the AWS resources and image

Use local AWS credentials that can create IAM roles, an IAM OIDC provider, an S3
bucket, and CloudWatch log groups:

```bash
export AWS_REGION=us-east-1
export GITHUB_REPOSITORY=OWNER/PRIVATE_REPOSITORY

scripts/bootstrap-aws.sh
scripts/build-microvm-image.sh
scripts/configure-github.sh
```

The bootstrap creates a GitHub OIDC launch role trusted only for the
repository's `main` branch. Set `GITHUB_DEFAULT_BRANCH` for another branch, or
set `GITHUB_OIDC_SUBJECT` to an exact GitHub Environment or ref subject. Do not
use a wildcard subject for untrusted pull-request refs.

No IAM user or stored AWS access key is required by GitHub in this mode.

## 2. Create a GitHub App

Create and install a GitHub App only on the runner repository. Grant repository
Administration read/write permission so it can create, inspect, and delete JIT
runners.

Record its App ID and download its private key, then configure them:

```bash
gh variable set RUNNER_APP_ID --body APP_ID
gh secret set RUNNER_APP_PRIVATE_KEY < path/to/app.private-key.pem
```

The helper can configure these values with the other repository settings:

```bash
RUNNER_APP_ID=APP_ID \
RUNNER_APP_PRIVATE_KEY_FILE=path/to/app.private-key.pem \
scripts/configure-github.sh
```

## 3. Configure the workflow

Copy [the advanced workflow](../examples/advanced.yml) into
`.github/workflows/microvm-runner.yml`. It requests `id-token: write`, assumes
the repository-scoped AWS launch role, and mints a short-lived GitHub App
installation token for each start job.
120 changes: 45 additions & 75 deletions docs/installation.md
Original file line number Diff line number Diff line change
@@ -1,103 +1,73 @@
# Installation

Version 1 is for private repositories with trusted workflow changes. It requires
an ARM64-capable Lambda MicroVM Region and an AWS account with enough MicroVM
memory quota for at least one 4 GiB runner.
an ARM64-capable Lambda MicroVM Region and enough regional MicroVM memory quota
for at least one 4 GiB runner.

## 1. Create the AWS resources
## Quickstart

Use local AWS credentials that can create IAM roles, an IAM OIDC provider, an S3
bucket, and CloudWatch log groups:
Install these local prerequisites:

```bash
export AWS_REGION=us-east-1
export GITHUB_REPOSITORY=OWNER/PRIVATE_REPOSITORY

scripts/bootstrap-aws.sh
```

This direct, idempotent script creates:

- one private, encrypted, versioned S3 artifact bucket;
- build and runtime CloudWatch log groups with 30-day retention;
- the account-level GitHub Actions OIDC provider if it is absent;
- an image build role;
- a restricted MicroVM runtime role;
- a GitHub OIDC launch role trusted only for the repository's `main` branch.
- AWS CLI with credentials allowed to create IAM, S3, CloudWatch Logs, and
Lambda MicroVM resources;
- GitHub CLI authenticated to the target repository;
- `jq`, Docker, and Node.js 24.

It writes the resulting values to `build/aws-setup.json`. Run it again to
reconcile the same resources.

For a different default branch, set `GITHUB_DEFAULT_BRANCH`. For a GitHub
Environment or another exact OIDC subject, set `GITHUB_OIDC_SUBJECT` explicitly.
Do not use a wildcard subject for untrusted pull-request refs.

No IAM user or stored AWS access key is needed by GitHub.

## 2. Build the MicroVM image

The build command reads `build/aws-setup.json` automatically:
Create a classic GitHub personal access token with the `repo` scope. Then clone
this repository and run:

```bash
scripts/build-microvm-image.sh
```

It packages and uploads a content-addressed artifact, creates or updates the
image, waits for validation, activates the successful version, and keeps a
bounded rollback set. The active ARN and version are written to
`build/microvm-image.json`.

## 3. Create a GitHub App

Create and install a GitHub App only on the runner repository. Grant repository
Administration read/write permission so it can create, inspect, and delete JIT
runners.

Record its App ID and download its private key. A compatible fine-grained PAT
can be passed directly, but short-lived installation tokens are preferred.

## 4. Configure the GitHub repository

With `gh auth status` working, set the generated AWS and image values:
export AWS_REGION=us-east-1
export GITHUB_REPOSITORY=OWNER/PRIVATE_REPOSITORY

```bash
scripts/configure-github.sh
scripts/setup-quickstart.sh
```

Then set the GitHub App credentials:
Paste the classic PAT when prompted. Alternatively, provide it for unattended
setup:

```bash
gh variable set RUNNER_APP_ID --body APP_ID
gh secret set RUNNER_APP_PRIVATE_KEY < path/to/app.private-key.pem
GH_PERSONAL_ACCESS_TOKEN=TOKEN scripts/setup-quickstart.sh
```

Alternatively, configure everything in the helper invocation:
The script:

```bash
RUNNER_APP_ID=APP_ID \
RUNNER_APP_PRIVATE_KEY_FILE=path/to/app.private-key.pem \
scripts/configure-github.sh
```
1. creates or reconciles the S3 bucket, CloudWatch log groups, and image build
and runtime IAM roles;
2. packages, uploads, validates, and activates the runner image;
3. configures the repository variables;
4. creates a dedicated `lambda-microvm-github-runner-quickstart` IAM user;
5. grants that user bootstrap, image build, and runner lifecycle permissions;
6. rotates its access key directly into the `AWS_ACCESS_KEY_ID` and
`AWS_SECRET_ACCESS_KEY` GitHub Actions secrets;
7. sets the PAT as `GH_PERSONAL_ACCESS_TOKEN`.

The helper creates these repository variables:
The secret access key is never written to the setup output or printed.
Re-running the script reconciles resources, builds a new image version, and
rotates the dedicated access key.

- `MICROVM_AWS_REGION`;
- `MICROVM_LAUNCH_ROLE_ARN`;
- `MICROVM_EXECUTION_ROLE_ARN`;
- `MICROVM_RUNTIME_LOG_GROUP`;
- `MICROVM_RUNNER_IMAGE_ARN`;
- `MICROVM_RUNNER_IMAGE_VERSION`.
> **Quickstart security boundary:** These are long-lived credentials with broad
> product permissions. Use them only in private repositories where workflow
> changes are trusted. Never expose them to untrusted `pull_request_target`
> workflows.

Copy [the basic workflow](../examples/basic.yml) into
`.github/workflows/microvm-runner.yml`. Pin every third-party Action and this
Action to reviewed immutable commits before production use.
`.github/workflows/microvm-runner.yml`. Pin Actions to reviewed immutable
versions before production use.

## 5. Verify
## Verify

Run the workflow manually and confirm:

1. start emits a unique label and MicroVM ID;
2. the target runs on ARM64 and `docker info`, Buildx, and Compose succeed;
2. the target runs on ARM64 and Docker, Buildx, and Compose succeed;
3. the JIT runner processes only that job;
4. the MicroVM reaches `TERMINATED`;
5. no GitHub token or JIT payload appears in Actions or CloudWatch logs.
5. no GitHub token, AWS credential, or JIT payload appears in logs.

## Advanced credentials

For short-lived credentials, use GitHub OIDC for AWS and a GitHub App
installation token instead. The standalone bootstrap enables the OIDC provider
and launch role by default. See [advanced credentials](advanced-credentials.md)
and [the advanced workflow](../examples/advanced.yml).
19 changes: 19 additions & 0 deletions docs/operations.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# Operations

## Quickstart credential rotation

Re-run the credential helper to rotate the dedicated IAM user's access key and
replace both GitHub Actions secrets:

```bash
export GITHUB_REPOSITORY=OWNER/REPOSITORY
scripts/configure-quickstart-credentials.sh
```

The helper installs the new secret pair before deleting the previous key. Rotate
the classic PAT separately with:

```bash
gh secret set GH_PERSONAL_ACCESS_TOKEN --repo "${GITHUB_REPOSITORY}"
```

Delete the dedicated IAM user and PAT when the integration is no longer used.

## Quotas

MicroVM API and memory quotas are shared per AWS account and Region. The
Expand Down
18 changes: 12 additions & 6 deletions docs/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,26 @@ and trusted workflow changes only. Public fork pull requests are unsupported.

## Credentials

- Start uses a short-lived GitHub App installation token. The token is masked
before validation or external work.
- Quickstart stores a classic PAT with `repo` scope and a dedicated IAM user's
access key as GitHub Actions secrets. The IAM user can reconcile this
product's bootstrap resources, build images, and manage runner MicroVMs.
- Quickstart is limited to private repositories with trusted workflow changes.
Rotate or delete both credentials when they are no longer needed.
- Advanced setup uses a short-lived GitHub App installation token and obtains
AWS credentials through GitHub OIDC.
- GitHub tokens are masked before validation or external work.
- The encoded JIT configuration and compressed payload are masked and never
included in errors, outputs, or supervisor logs.
- GitHub-hosted start and stop jobs obtain AWS credentials through OIDC.
- The default MicroVM execution role can write its logs and terminate runner
MicroVMs. It has no application deployment permissions.
- The runtime role's only unscoped resource permission is
`lambda:TerminateMicrovm`, because that API does not expose a per-instance IAM
resource ARN. No other Lambda or application action is granted by it.
- Deployment jobs should assume a separate role through GitHub OIDC.
- Deployment jobs should use a separate identity and must not inherit the
Quickstart IAM user's bootstrap permissions.

The GitHub App private key never enters the MicroVM. No long-lived AWS key is
required or documented.
The classic PAT, AWS secret access key, and GitHub App private key never enter
the MicroVM.

## Network

Expand Down
9 changes: 5 additions & 4 deletions docs/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
```bash
npm ci
npm run check
shellcheck scripts/*.sh
shellcheck scripts/*.sh test/scripts/*.sh
scripts/package-runner-image.sh
npm run test:image
npm audit --audit-level=high
```

`npm run check` covers strict TypeScript, 58 Action tests, 17 supervisor tests,
and the bundled Action. Supervisor tests also run successfully under the image's
Python 3.9 runtime.
`npm run check` covers strict TypeScript, 58 Action tests, Quickstart IAM
credential creation and rotation tests, 17 supervisor tests, and the bundled
Action. Supervisor tests also run successfully under the image's Python 3.9
runtime.

`npm run test:image` requires an ARM64 Docker host. It verifies:

Expand Down
Loading
Loading