Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: ensure no self-hosted runners for generic generators #3298

Draft
wants to merge 62 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
2d96347
init
ramonpetgrave64 Feb 20, 2024
ddcc650
add octokit/rest
ramonpetgrave64 Feb 23, 2024
5d88260
add ensureOnlyGithubHostedRunners
ramonpetgrave64 Feb 23, 2024
13d7944
add tests
ramonpetgrave64 Feb 23, 2024
085b7fc
cleanup
ramonpetgrave64 Feb 23, 2024
b03db34
typo
ramonpetgrave64 Feb 23, 2024
0da0e24
more cleanup
ramonpetgrave64 Feb 23, 2024
6b62976
stronger error check
ramonpetgrave64 Feb 23, 2024
f46f333
use my forl
ramonpetgrave64 Feb 23, 2024
8f40c6b
rebuild
ramonpetgrave64 Feb 23, 2024
6274116
console log
ramonpetgrave64 Feb 23, 2024
037fc49
redo tests
ramonpetgrave64 Feb 23, 2024
f38f55d
guidance on version tags
ramonpetgrave64 Feb 24, 2024
4d4019d
change builder-repo
ramonpetgrave64 Feb 24, 2024
7010c15
use my fork
ramonpetgrave64 Feb 24, 2024
6facd38
@v1.0.1
ramonpetgrave64 Feb 24, 2024
e38b943
console log
ramonpetgrave64 Feb 27, 2024
2944894
console log
ramonpetgrave64 Feb 27, 2024
ca56348
1.05 check common labels
ramonpetgrave64 Feb 27, 2024
4e08579
all labels and token as secret
ramonpetgrave64 Feb 28, 2024
f679c36
feat: Create pull_request_template.md (#3268)
ramonpetgrave64 Feb 22, 2024
501a3da
Empty-Commit
ramonpetgrave64 Feb 28, 2024
1668fab
with tests
ramonpetgrave64 Feb 28, 2024
6f3bb4c
release ready
ramonpetgrave64 Feb 28, 2024
9a47ed5
better comment
ramonpetgrave64 Feb 28, 2024
4193213
include container workflow
ramonpetgrave64 Feb 28, 2024
225f091
lint
ramonpetgrave64 Feb 28, 2024
b556d7b
lint
ramonpetgrave64 Feb 28, 2024
f897af7
Merge branch 'main' into ramonpetgrave-slsa-build3-check-runners
ramonpetgrave64 Feb 28, 2024
fe7609d
use || github.token
ramonpetgrave64 Feb 29, 2024
4678ead
debug messages
ramonpetgrave64 Feb 29, 2024
7a74ced
checkout the repo in e2e tests
ramonpetgrave64 Feb 29, 2024
fe955ad
checkout this pr
ramonpetgrave64 Feb 29, 2024
41fcc01
my repo for checkout
ramonpetgrave64 Feb 29, 2024
cd06320
typo
ramonpetgrave64 Feb 29, 2024
b95587e
really use my repo
ramonpetgrave64 Feb 29, 2024
6150a30
ref in an env
ramonpetgrave64 Feb 29, 2024
9d14b5f
literal, not env
ramonpetgrave64 Feb 29, 2024
b833b02
no space
ramonpetgrave64 Feb 29, 2024
7b59ecc
actions tester fo rPRs
ramonpetgrave64 Feb 29, 2024
3fc7e0e
core.info, await the ensure, typos
ramonpetgrave64 Feb 29, 2024
2eb7e73
cleanup
ramonpetgrave64 Feb 29, 2024
3428f55
test for main.run
ramonpetgrave64 Feb 29, 2024
e80265d
lint and release
ramonpetgrave64 Feb 29, 2024
93a1ca5
back to main for ../../workflows/pre-submit.e2e.generic.default.yml
ramonpetgrave64 Feb 29, 2024
e3e1988
helpful messages, cleanup
ramonpetgrave64 Feb 29, 2024
484e2e3
cleanup
ramonpetgrave64 Feb 29, 2024
bad40fb
cleanup
ramonpetgrave64 Feb 29, 2024
6de0b8a
init: new action
ramonpetgrave64 Mar 4, 2024
9aa60ff
reorganize messages
ramonpetgrave64 Mar 5, 2024
f7bc052
more obvious errors
ramonpetgrave64 Mar 5, 2024
b06eb0e
same^
ramonpetgrave64 Mar 5, 2024
6e481ee
use the separate action
ramonpetgrave64 Mar 5, 2024
11156a7
revert original checker to main
ramonpetgrave64 Mar 5, 2024
de3a273
celanup
ramonpetgrave64 Mar 5, 2024
a6b84e1
lint
ramonpetgrave64 Mar 5, 2024
aa88858
e2e
ramonpetgrave64 Mar 5, 2024
2a79896
also for is-fork
ramonpetgrave64 Mar 5, 2024
6199195
back to futue main
ramonpetgrave64 Mar 5, 2024
23a4d0b
docs
ramonpetgrave64 Mar 5, 2024
169c4f6
changelog
ramonpetgrave64 Mar 5, 2024
285cf5e
lint
ramonpetgrave64 Mar 5, 2024
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: 2 additions & 0 deletions .github/actions/detect-workflow-js/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ myjob:
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@<tag>
with:
subjects: "${{ needs.build.outputs.digest }}"
secrets:
token: ${{ secrets.my-slsa-gh-token }}
```

However, it is not trivial to determine the repository and ref because the
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dist/
lib/
node_modules/
53 changes: 53 additions & 0 deletions .github/actions/ensure-github-hosted-runners-js/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"plugins": ["@typescript-eslint"],
"extends": ["plugin:github/recommended"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 9,
"sourceType": "module",
"project": "./tsconfig.json"
},
"rules": {
"i18n-text/no-en": "off",
"eslint-comments/no-use": "off",
"import/no-namespace": "off",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}],
"@typescript-eslint/no-require-imports": "error",
"@typescript-eslint/array-type": "error",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/ban-ts-comment": "error",
"camelcase": "off",
"@typescript-eslint/consistent-type-assertions": "error",
"@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
"@typescript-eslint/func-call-spacing": ["error", "never"],
"@typescript-eslint/no-array-constructor": "error",
"@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-extraneous-class": "error",
"@typescript-eslint/no-for-in-array": "error",
"@typescript-eslint/no-inferrable-types": "error",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-assertion": "warn",
"@typescript-eslint/no-unnecessary-qualifier": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/no-useless-constructor": "error",
"@typescript-eslint/no-var-requires": "error",
"@typescript-eslint/prefer-for-of": "warn",
"@typescript-eslint/prefer-function-type": "warn",
"@typescript-eslint/prefer-includes": "error",
"@typescript-eslint/prefer-string-starts-ends-with": "error",
"@typescript-eslint/promise-function-async": "error",
"@typescript-eslint/require-array-sort-compare": "error",
"@typescript-eslint/restrict-plus-operands": "error",
"semi": "off",
"@typescript-eslint/type-annotation-spacing": "error",
"@typescript-eslint/unbound-method": "error"
},
"env": {
"node": true,
"es6": true
}
}
99 changes: 99 additions & 0 deletions .github/actions/ensure-github-hosted-runners-js/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Dependency directory
node_modules

# Rest pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
jspm_packages/

# TypeScript v1 declaration files
typings/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
.env.test

# parcel-bundler cache (https://parceljs.org/)
.cache

# next.js build output
.next

# nuxt.js build output
.nuxt

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# OS metadata
.DS_Store
Thumbs.db

# Ignore built ts files
__tests__/runner/*
lib/**/*
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dist/
lib/
node_modules/
68 changes: 68 additions & 0 deletions .github/actions/ensure-github-hosted-runners-js/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Copyright 2023 SLSA Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

SHELL := /bin/bash
ACTION_NAME = $(shell basename "$$(pwd)")

.PHONY: help
help: ## Shows all targets and help from the Makefile (this message).
@echo "$(ACTION_NAME) Makefile"
@echo "Usage: make [COMMAND]"
@echo ""
@grep --no-filename -E '^([/a-z.A-Z0-9_%-]+:.*?|)##' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = "(:.*?|)## ?"}; { \
if (length($$1) > 0) { \
printf " \033[36m%-20s\033[0m %s\n", $$1, $$2; \
} else { \
if (length($$2) > 0) { \
printf "%s\n", $$2; \
} \
} \
}'

node_modules/.installed: package.json package-lock.json
npm ci
touch node_modules/.installed

.PHONY: action
action: node_modules/.installed ## Builds the action.
npm run build

.PHONY: package
package: action ## Builds the distribution package.
npm run package

.PHONY: clean
clean:
rm -rf dist lib node_modules

## Tools
#####################################################################

.PHONY: format
format: node_modules/.installed ## Formats code.
npm run format

## Testing
#####################################################################

.PHONY: unit-test
unit-test: node_modules/.installed ## Runs all unit tests.
# NOTE: Make sure the package builds.
npm run build
npm run test

.PHONY: lint
lint: node_modules/.installed ## Runs eslint.
npm run lint
89 changes: 89 additions & 0 deletions .github/actions/ensure-github-hosted-runners-js/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# ensure-github-hosted-runners-js

Github action runners can be either github-hosted or self-hosted.

`ensure-github-hosted-runners-js` is a Github Action that ensures that no self-hosted

Check failure on line 5 in .github/actions/ensure-github-hosted-runners-js/README.md

View workflow job for this annotation

GitHub Actions / markdownlint

MD009/no-trailing-spaces Trailing spaces [Detail: "Expected: 0 or 2; Actual: 1", Context: ""]
runners are used for any adjacent jobs in the workflow.

It does this by comparing the `runs-on` labels in the job specs with the

Check failure on line 8 in .github/actions/ensure-github-hosted-runners-js/README.md

View workflow job for this annotation

GitHub Actions / markdownlint

MD009/no-trailing-spaces Trailing spaces [Detail: "Expected: 0 or 2; Actual: 1", Context: ""]
labels of the repository's known self-hosted runner labels.

## Why?

SLSA Build 3 is intends for builds to be performed on trusted build platforms, which
means only using github-hosted runners.

All of our language-specific builder workflows both build code and produce provenance.
They are run using Github Reusable Workflows, which we know will always run on github-hoastwed runners.
Therefore we can trust that both the build artifacts and provenance were produce on
github-hosted runners.

But our generic workflows do not perform actual builds. Instead they accept the build artifacts
produced by the the user's own jobs, which the user could specify to run on self-hosted runners.

## Caveats

### Administration:read permissions

This action requires the user to supply their own token with extra permissions, rather than the

Check failure on line 28 in .github/actions/ensure-github-hosted-runners-js/README.md

View workflow job for this annotation

GitHub Actions / markdownlint

MD009/no-trailing-spaces Trailing spaces [Detail: "Expected: 0 or 2; Actual: 1", Context: ""]
default token that Github will automatically supply to workflows. We will have our calling workflows
pass the token along.

1. Create a new Token for your repository, with:
1. actions:read

Check failure on line 33 in .github/actions/ensure-github-hosted-runners-js/README.md

View workflow job for this annotation

GitHub Actions / markdownlint

MD005/list-indent Inconsistent indentation for list items at the same level [Detail: "Expected: 0; Actual: 2", Context: ""]

Check failure on line 33 in .github/actions/ensure-github-hosted-runners-js/README.md

View workflow job for this annotation

GitHub Actions / markdownlint

MD029/ol-prefix Ordered list item prefix [Detail: "Expected: 2; Actual: 1; Style: 1/2/3", Context: ""]
2. administration:read

Check failure on line 34 in .github/actions/ensure-github-hosted-runners-js/README.md

View workflow job for this annotation

GitHub Actions / markdownlint

MD005/list-indent Inconsistent indentation for list items at the same level [Detail: "Expected: 0; Actual: 2", Context: ""]

Check failure on line 34 in .github/actions/ensure-github-hosted-runners-js/README.md

View workflow job for this annotation

GitHub Actions / markdownlint

MD029/ol-prefix Ordered list item prefix [Detail: "Expected: 3; Actual: 2; Style: 1/2/3", Context: ""]
2. Add the token as a Repository Secret, `my-slsa-gh-token`, for example

Check failure on line 35 in .github/actions/ensure-github-hosted-runners-js/README.md

View workflow job for this annotation

GitHub Actions / markdownlint

MD029/ol-prefix Ordered list item prefix [Detail: "Expected: 4; Actual: 2; Style: 1/2/3", Context: ""]
3. Supply token to the action

Check failure on line 36 in .github/actions/ensure-github-hosted-runners-js/README.md

View workflow job for this annotation

GitHub Actions / markdownlint

MD029/ol-prefix Ordered list item prefix [Detail: "Expected: 5; Actual: 3; Style: 1/2/3", Context: ""]

The generic generator workflows will expect this token when they pass
along to this action, so you can also use them like

```yaml
jobs:
detect-workflow:
runs-on: ubuntu-latest
uses: slsa-framework/slsa-github-generator/.github/workflows/[email protected]@<git hash>
secrets:
token: ${{ secrets.my-slsa-gh-token }}
```

### Race conditon

We acknowledge that a malicious repository woner could still workaround this mechanism.
At the start of a workflow, they could have one Job run with `runs-on: my-vps` that targets one of

Check failure on line 53 in .github/actions/ensure-github-hosted-runners-js/README.md

View workflow job for this annotation

GitHub Actions / markdownlint

MD009/no-trailing-spaces Trailing spaces [Detail: "Expected: 0 or 2; Actual: 1", Context: ""]
their self-hosted runbners. Then, after that Job completes, but before the slsa-framework job starts,
they could use ther github UI to remove that particual `my-vps` label from their self-hosted runner.
This action would not detect that the first job did actually run on a slef-hosted runners.

### Considered mitigations

#### What about using a list of known github-hosted runner labels?

Github does not publish a difnitive list. But an even greater problem is that the user could assign their
runner any of Github's common labels. They could label their self-hosted runner with `ubuntu-latest`, for example.


#### What about using the Job's runner ID?

Github's List Jobs for Workflow Run also returns the assigned runner IDs for the job. We had considered
using these IDs against the known self-hsoted runner IDs, but it still does not solve the race codnition problem
because a user may delete their self-hosted runner before this action executes. And Github does not publish
a list of github-hosted runner IDs.

TODO: usage docs

## Usage

First create a Token and Secret described [above](#administrationread-permissions)

```yaml
jobs:
detect-workflow:
runs-on: ubuntu-latest
steps:
- name: Detect the repository and ref
id: detect
uses: slsa-framework/slsa-github-generator/.github/actions/ensure-github-hosted-runners@<git hash>
with:
token: ${{ secrets.my-slsa-gh-token }}
```
Loading
Loading