8000 Add GitHub Action - assertion (#7) · nginxinc/compliance-rules@600edca · GitHub
[go: up one dir, main page]

Skip to content

Commit 600edca

Browse files
authored
Add GitHub Action - assertion (#7)
* WIP - initial version for testing Signed-off-by: Jakub Jarosz <j.jarosz@f5.com> * add step for getting dependencies Signed-off-by: Jakub Jarosz <j.jarosz@f5.com> * get path to binary Signed-off-by: Jakub Jarosz <j.jarosz@f5.com> * WIP - update assertion-reusable workflow Signed-off-by: Jakub Jarosz <j.jarosz@f5.com> * add assertion action Signed-off-by: Jakub Jarosz <j.jarosz@f5.com> * add workflow Signed-off-by: Jakub Jarosz <j.jarosz@f5.com> * remove obsolete workflow Signed-off-by: Jakub Jarosz <j.jarosz@f5.com> * WIP - assertion flow Signed-off-by: Jakub Jarosz <j.jarosz@f5.com> * add more documentation Signed-off-by: Jakub Jarosz <j.jarosz@f5.com> * add data flow diagram Signed-off-by: Jakub Jarosz <j.jarosz@f5.com> * remove unused binaries Signed-off-by: Jakub Jarosz <j.jarosz@f5.com> * wip - assertion action test Signed-off-by: Jakub Jarosz <j.jarosz@f5.com> * update documentation Signed-off-by: Jakub Jarosz <j.jarosz@f5.com> * cleanup debug steps Signed-off-by: Jakub Jarosz <j.jarosz@f5.com> * add new assertion action binary Signed-off-by: Jakub Jarosz <j.jarosz@f5.com> * increase assertion doc storage time to 7 days Signed-off-by: Jakub Jarosz <j.jarosz@f5.com> --------- Signed-off-by: Jakub Jarosz <j.jarosz@f5.com>
1 parent a27656f commit 600edca

File tree

10 files changed

+325
-0
lines changed

10 files changed

+325
-0
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# ns-assertion-action
2+
3+
`ns-assertion-action` is a GitHub Action for generating assertion documents.
4+
5+
The `ns-assertion-action` generates the assertion document for the Go binary built in the pipeline.
6+
7+
## Data flow
8+
9+
![assertion](img/assertion3.png)
10+
11+
## Prerequisites
12+
13+
The action takes the input string representing output from the `go version -m <binary>` command.
14+
The command retrospects the Go binary and lists included Go packages.
15+
16+
## Configuration
17+
18+
### Required input data
19+
20+
The action require text input data representing raw output from the Go command `go version -m <binary>`.
21+
22+
Example:
23+
24+
```yaml
25+
- name: Generate Assertion Document
26+
id: assertiondoc
27+
uses: nginxinc/compliance-rules/.github/actions/assertion@feat/assertion
28+
with:
29+
artifact-name: ptdcli_${{ github.ref_name }}
30+
artifact-digest: 'test-digest'
31+
build-type: 'github'
32+
builder-id: 'github.com'
33+
builder-version: '0.1.0-xyz'
34+
invocation-id: ${{ github.run_id }}.${{ github.run_number }}.${{ github.run_attempt }}
35+
artifactory-user: ${{ secrets.ARTIFACTORY_USER }}
36+
artifactory-api-token: ${{ secrets.ARTIFACTORY_TOKEN }}
37+
artifactory-url: ${{ secrets.ARTIFACTORY_URL }}
38+
artifactory-repo: 'f5-nginx-go-local-approved-dependency'
39+
assertion-doc-file: assertion_ptdcli_${{ github.ref_name }}.json
40+
build-content-path: ${{ steps.godeps.outputs.goversionm }}
41+
42+
```
43+
44+
### Required coniguration parameters
45+
46+
## Troubleshooting
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: 'Assertion document'
2+
description: 'Generate assertion document'
3+
inputs:
4+
artifactory-api-token:
5+
description: 'API Key for accessing Artifactory to read packages info and upload signed assertion documents'
6+
required: true
7+
artifactory-user:
8+
description: 'Artifactory user with permission to read and write'
9+
required: true
10+
artifactory-url:
11+
description: 'Artifactory URL'
12+
required: true
13+
artifactory-repo:
14+
description: 'Artifactory Repository'
15+
required: true
16+
artifact-name:
17+
description: 'Build artifact name'
18+
required: true
19+
artifact-digest:
20+
description: 'SHA256 Hash of the build artifact'
21+
required: true
22+
build-type:
23+
description: 'The indicator for where we build the artifact. One of gitlab, github or gitswarm'
24+
required: true
25+
builder-id:
26+
description: 'The build image indicator, an identifier for the build container'
27+
required: true
28+
builder-version:
29+
description: 'version'
30+
required: true
31+
build-content-path:
32+
description: 'The path where we store content of the output from `go version -m <binary-name>` command'
33+
assertion-doc-file:
34+
description: 'Filepath where to save conent of the assertion document'
35+
invocation-id:
36+
description: 'What event ID triggered the workflow'
37+
required: true
38+
started-on:
39+
description: 'Pipeline start time'
40+
required: true
41+
finished-on:
42+
description: 'Pipeline end time'
43+
required: true
44+
outputs:
45+
assertion-document:
46+
description: "Generated assertion document"
47+
#value: ${{ steps.doc.outputs.assertion-doc }}
48+
runs:
49+
using: node20
50+
main: invoke_binary.js
9.57 MB
Binary file not shown.
9.49 MB
Binary file not shown.
90.6 KB
Loading
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
const childProcess = require('child_process')
2+
const os = require('os')
3+
const process = require('process')
4+
5+
const VERSION = 'd4b2f9c'
6+
7+
function chooseBinary() {
8+
const platform = os.platform()
9+
const arch = os.arch()
10+
11+
if (platform === 'linux' && arch === 'x64') {
12+
return `assertiongha-linux-amd64-${VERSION}`
13+
}
14+
if (platform === 'linux' && arch === 'arm64') {
15+
return `assertiongha-linux-arm64-${VERSION}`
16+
}
17+
18+
console.error(`Unsupported platform (${platform}) and architecture (${arch})`)
19+
process.exit(1)
20+
}
21+
22+
function main() {
23+
const binary = chooseBinary()
24+
const mainScript = `${__dirname}/${binary}`
25+
const spawnSyncReturns = childProcess.spawnSync(mainScript, { stdio: 'inherit' })
26+
const status = spawnSyncReturns.status
27+
if (typeof status === 'number') {
28+
process.exit(status)
29+
}
30+
process.exit(1)
31+
}
32+
33+
if (require.main === module) {
34+
main()
35+
}

.github/actions/sign/action.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Signs and Store Assertion Document
2+
description: Run Smoke Tests for the project
3+
4+
inputs:
5+
assertion-doc:
6+
description: Assertion Document in JSON format
7+
required: true
8+
9+
runs:
10+
using: composite
11+
steps:
12+
- name: Install Cosign
13+
uses: sigstore/cosign-installer@d58896d6a1865668819e1d91763c7751a165e159 # v3.9.2
14+
15+
- name: Generate Checksum
16+
id: sign
17+
run: |
18+
cosign_binary=${COSIGN_BIN:-"cosign"}
19+
sha256sum ${{ inputs.assertion-doc }} >> "${{ inputs.assertion-doc }}_checksum.txt"
20+
checksum_file="${{ inputs.assertion-doc }}_checksum.txt"
21+
${cosign_binary} sign-blob "${checksum_file}" --output-signature="${checksum_file}.sig" --output-certificate="${checksum_file}.pem" -y
22+
tar -cvf assertion.tar assertion*
23+
echo "assertiontar=$(find -type f -name "assertion.tar" | head -n 1)" >> $GITHUB_OUTPUT
24+
shell: bash
25+
26+
- name: Store assertion document
27+
uses: actions/upload-artifact@v4
28+
with:
29+
name: assertion
30+
path: ${{ steps.sign.outputs.assertiontar }}
31+
retention-days: 7

.github/workflows/assertion.yml

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
name: Reusable assertion document generator
2+
3+
on:
4+
workflow_call:
5+
secrets:
6+
ARTIFACTORY_USER:
7+
required: true
8+
ARTIFACTORY_TOKEN:
9+
required: true
10+
ARTIFACTORY_URL:
11+
required: true
12+
# Inputs must include all env vars required by ns-assertion-action
13+
# Refer to action documentation: https://github.com/nginxinc/ns-assertion-action
14+
inputs:
15+
artifact-name:
16+
required: true
17+
type: string
18+
artifact-digest:
19+
required: true
20+
type: string
21+
builder-id:
22+
required: true
23+
type: string
24+
build-type:
25+
required: true
26+
type: string
27+
builder-version:
28+
required: true
29+
type: string
30+
build-artifact-name:
31+
required: true
32+
type: string
33+
build-artifact-path:
34+
required: true
35+
type: string
36+
build-go-binary-path:
37+
required: true
38+
type: string
39+
invocation-id:
40+
required: true
41+
type: string
42+
43+
44+
permissions:
45+
contents: read
46+
47+
defaults:
48+
run:
49+
shell: bash
50+
51+
jobs:
52+
check-dependencies:
53+
name: Checking Dependencies
54+
runs-on: ubuntu-24.04
55+
steps:
56+
- name: Checkout Repository
57+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
58+
with:
59+
fetch-depth: 0
60+
61+
- name: Setup Go Environment
62+
uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
63+
with:
64+
go-version: 'stable'
65+
cache: false
66+
67+
generate-assertion-doc:
68+
name: Generate Assertion Doc
69+
needs: check-dependencies
70+
runs-on: ubuntu-24.04
71+
steps:
72+
- name: Checkout Repository
73+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
74+
with:
75+
fetch-depth: 0
76+
77+
78+
# - name: Get packages from Go binary
79+
# id: parse_binary
80+
# run: |
81+
# echo "Generating list of dependencies"
82+
# echo ${{ inputs.build-artifact-path }}
83+
84+
- name: Generate assertion document
85+
id: generate_doc
86+
uses: ./.github/actions/assertion
87+
with:
88+
artifact-name: ${{ inputs.artifact-name }}
89+
artifact-digest: ${{ inputs.artifact-digest }}
90+
builder-id: ${{ inputs.builder-id }}
91+
build-type: ${{ inputs.build-type }}
92+
builder-version: ${{ inputs.builder-version }}
93+
build-artifact-name: ${{ inputs.build-artifact-name }}
94+
build-go-binary-path: ${{ inputs.build-go-binary-path }}
95+
invocation-id: ${{ inputs.invocation-id }}

README.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,71 @@ uses: nginxinc/compliance-rules/.github/workflows/codeql.yml@<git_tag>
116116
1. CodeQL analyses the `ProjectABC` code.
117117
1. Depends on the results the pipeline fails or passes.
118118
1. The GitHub repository (`ProjectA`) must be configured to reject PRs (prevent from merging with the `main` branch) if the codeql detects issues and the pipeline fails.
119+
120+
## Configure Assertion Document Workflow
121+
122+
### Data flow
123+
124+
![assertion](img/assertion3.png)
125+
126+
#### GitHub Action Assertion - Configuration
127+
128+
In your project release workflow add a step for generating the assertion document.
129+
130+
The assertion action require input var `build-content-path` that represents a text file with content from the `go version -m <binary>` command where `binary` represents compiled Go binary, for example `agent`.
131+
132+
The full list of required variables:
133+
134+
- `artifact-name` - unique name of the binary built in the pipeline
135+
- `artifact-digest` - calculated digest
136+
- `build-type` - github or gitlab
137+
- `builder-id` - github.com
138+
- `builder-version`
139+
- `invocation-id` - unique id for the build pipeline
140+
- `artifactory-user`
141+
- `artifactory-api-token`
142+
- `artifactory-url`
143+
- `artifactory-repo` - Artifactory repository used for pulling build dependencies, for example 'f5-nginx-go-local-approved-dependency'
144+
- `assertion-doc-file` - file generated by the action `assertion_${{ unique identifier }}.json`
145+
- `build-content-path` - file containing output from `go version -m` command executed against the binary
146+
147+
After successful run the action produces an assertion document in JSON format. The document needs to be signed and stored for further processing.
148+
149+
Example:
150+
151+
```yaml
152+
- name: Generate Assertion Document
153+
id: assertiondoc
154+
uses: nginxinc/compliance-rules/.github/actions/assertion@main
155+
with:
156+
artifact-name: ptdcli_${{ github.ref_name }}
157+
artifact-digest: 'test-digest'
158+
build-type: 'github'
159+
builder-id: 'github.com'
160+
builder-version: '0.1.0-xyz'
161+
invocation-id: ${{ github.run_id }}.${{ github.run_number }}.${{ github.run_attempt }}
162+
artifactory-user: ${{ secrets.ARTIFACTORY_USER }}
163+
artifactory-api-token: ${{ secrets.ARTIFACTORY_TOKEN }}
164+
artifactory-url: ${{ secrets.ARTIFACTORY_URL }}
165+
artifactory-repo: 'f5-nginx-go-local-approved-dependency'
166+
assertion-doc-file: assertion_ptdcli_${{ github.ref_name }}.json
167+
build-content-path: ${{ steps.godeps.outputs.goversionm }}
168+
```
169+
170+
#### GitHub Action Sign - Configuration
171+
172+
The `Sign` action takes a path to the generated assertion document, signs the document and stores it in GitHub.
173+
174+
The list of required variables:
175+
176+
- `assertion-doc` - path to the file generated by the `Assertion` GH Action - (`assertion-doc-file`)
177+
178+
Example:
179+
180+
```yaml
181+
- name: Sign and Store Assertion Document
182+
id: sign
183+
uses: nginxinc/compliance-rules/.github/actions/sign@feat/assertion
184+
with:
185+
assertion-doc: ${{ steps.verify_assertion.outputs.assertiondocument }}
186+
```

img/assertion3.png

90.6 KB
Loading

0 commit comments

Comments
 (0)
0