Skip to content

Compare public keys on trusted leaf certs, to prevent use of alternate certs with the same/forged serial numbers #21949

Compare public keys on trusted leaf certs, to prevent use of alternate certs with the same/forged serial numbers

Compare public keys on trusted leaf certs, to prevent use of alternate certs with the same/forged serial numbers #21949

Workflow file for this run

name: CI
on:
pull_request:
# The default types for pull_request are [opened, synchronize, reopened]. This is insufficient
# for our needs, since we're skipping stuff on PRs in draft mode.By adding the ready_for_review
# type, when a draft pr is marked ready, we run everything, including the stuff we'd have
# skipped up until now.
types: [opened, synchronize, reopened, ready_for_review]
push:
branches:
- main
- release/**
workflow_dispatch:
concurrency:
group: ${{ github.head_ref || github.run_id }}-ci
cancel-in-progress: true
jobs:
setup:
runs-on: ${{ github.repository == 'hashicorp/vault' && 'ubuntu-latest' || fromJSON('["self-hosted","linux","small"]') }}
outputs:
app-changed: ${{ steps.changed-files.outputs.app-changed }}
checkout-ref: ${{ steps.checkout.outputs.ref }}
compute-small: ${{ steps.metadata.outputs.compute-small }}
compute-test-go: ${{ steps.metadata.outputs.compute-test-go }}
compute-test-ui: ${{ steps.metadata.outputs.compute-test-ui }}
go-tags: ${{ steps.metadata.outputs.go-tags }}
is-draft: ${{ steps.metadata.outputs.is-draft }}
is-enterprise: ${{ steps.metadata.outputs.is-enterprise }}
is-fork: ${{ steps.metadata.outputs.is-fork }}
labels: ${{ steps.metadata.outputs.labels }}
ui-changed: ${{ steps.changed-files.outputs.ui-changed }}
workflow-trigger: ${{ steps.metadata.outputs.workflow-trigger }}
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: ./.github/actions/changed-files
id: changed-files
- uses: ./.github/actions/checkout
id: checkout # make sure we check out correct ref after checking changed files
- uses: ./.github/actions/metadata
id: metadata
- name: Ensure Go modules are cached
uses: ./.github/actions/set-up-go
with:
github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
no-restore: true # don't download them on a cache hit
test-go:
# Run Go tests if the vault app changed
if: needs.setup.outputs.app-changed == 'true'
name: Run Go tests
needs: setup
uses: ./.github/workflows/test-go.yml
with:
# The regular Go tests use an extra runner to execute the binary-dependent tests. We isolate
# them there so that the other tests aren't slowed down waiting for a binary build.
binary-tests: true
checkout-ref: ${{ needs.setup.outputs.checkout-ref }}
go-arch: amd64
go-tags: '${{ needs.setup.outputs.go-tags }},deadlock'
name: standard
runs-on: ${{ needs.setup.outputs.compute-test-go }}
runs-on-small: ${{ needs.setup.outputs.compute-small }}
test-timing-cache-key: go-test-timing-standard
total-runners: 16
secrets: inherit
test-go-testonly:
# Run Go tests tagged with "testonly" if the vault app changed
if: needs.setup.outputs.app-changed == 'true'
name: Run Go tests tagged with testonly
needs: setup
uses: ./.github/workflows/test-go.yml
with:
checkout-ref: ${{ needs.setup.outputs.checkout-ref }}
go-arch: amd64
go-tags: '${{ needs.setup.outputs.go-tags }},deadlock,testonly'
name: testonly
runs-on: ${{ needs.setup.outputs.compute-test-go }}
runs-on-small: ${{ needs.setup.outputs.compute-small }}
testonly: true
test-timing-cache-enabled: false
total-runners: 2 # test runners cannot be less than 2
secrets: inherit
test-go-race:
# Run Go test with the data race detector enabled if the vault app changed and we're out of
# drafts mode.
if: needs.setup.outputs.app-changed == 'true' && needs.setup.outputs.is-draft == 'false'
name: Run Go tests with data race detection
needs: setup
uses: ./.github/workflows/test-go.yml
with:
checkout-ref: ${{ needs.setup.outputs.checkout-ref }}
env-vars: |
{
"VAULT_CI_GO_TEST_RACE": 1
}
extra-flags: '-race'
name: race
go-arch: amd64
go-tags: ${{ needs.setup.outputs.go-tags }}
runs-on: ${{ needs.setup.outputs.compute-test-go }}
runs-on-small: ${{ needs.setup.outputs.compute-small }}
test-timing-cache-key: go-test-timing-race
total-runners: 16
secrets: inherit
test-go-fips:
name: Run Go tests with FIPS configuration
# Run the Go tests with fips if the vault app changed, we're in the context vault enterprise
# and our trigger is a merge to main or releases/* or if the 'fips' label is present on a PR.
if: |
needs.setup.outputs.app-changed == 'true' &&
needs.setup.outputs.is-enterprise == 'true' &&
(needs.setup.outputs.workflow-trigger == 'push' || contains(needs.setup.outputs.labels, 'fips'))
needs: setup
uses: ./.github/workflows/test-go.yml
with:
checkout-ref: ${{ needs.setup.outputs.checkout-ref }}
env-vars: |
{
"GOEXPERIMENT": "boringcrypto"
}
name: fips
go-arch: amd64
go-tags: '${{ needs.setup.outputs.go-tags }},deadlock,cgo,fips,fips_140_2'
runs-on: ${{ needs.setup.outputs.compute-test-go }}
runs-on-small: ${{ needs.setup.outputs.compute-small }}
test-timing-cache-key: go-test-timing-fips
total-runners: 16
secrets: inherit
test-ui:
name: Test UI
# Run the UI tests if our UI has changed, or a 'ui' label is present, or our workflow trigger
# was triggered by a merge to main or releases/*.
if: |
needs.setup.outputs.ui-changed == 'true' ||
needs.setup.outputs.workflow-trigger == 'push' ||
contains(github.event.pull_request.labels.*.name, 'ui')
needs: setup
permissions:
id-token: write
contents: read
runs-on: ${{ fromJSON(needs.setup.outputs.compute-test-ui) }}
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
name: status
with:
ref: ${{ needs.setup.outputs.checkout-ref }}
- uses: ./.github/actions/set-up-go
with:
github-token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
# Setup node.js without caching to allow running npm install -g yarn (next step)
- uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
with:
node-version-file: './ui/package.json'
- run: npm install -g yarn
# Setup node.js with caching using the yarn.lock file
- uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
with:
node-version-file: './ui/package.json'
cache: yarn
cache-dependency-path: ui/yarn.lock
- uses: browser-actions/setup-chrome@52f10de5479c69bcbbab2eab094c9d373148005e # v1.4.0
- name: ui-dependencies
working-directory: ./ui
run: |
yarn install --frozen-lockfile
npm rebuild node-sass
- if: needs.setup.outputs.is-enterprise == 'true'
id: vault-auth
name: Authenticate to Vault
run: vault-auth
- if: needs.setup.outputs.is-enterprise == 'true'
id: secrets
name: Fetch secrets
uses: hashicorp/vault-action@9f522b85981b491eab9a52c144d15aedbd0bf371 # v2.8.0
with:
url: ${{ steps.vault-auth.outputs.addr }}
caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }}
token: ${{ steps.vault-auth.outputs.token }}
secrets: |
kv/data/github/hashicorp/vault-enterprise/github-token username-and-token | PRIVATE_REPO_GITHUB_TOKEN;
kv/data/github/hashicorp/vault-enterprise/license license_1 | VAULT_LICENSE;
- if: needs.setup.outputs.is-enterprise == 'true'
name: Set up Git
run: git config --global url."https://${{ steps.secrets.outputs.PRIVATE_REPO_GITHUB_TOKEN }}@github.com".insteadOf https://github.com
- name: build-go-dev
run: |
rm -rf ./pkg
mkdir ./pkg
make prep dev
- name: test-ui
env:
VAULT_LICENSE: ${{ steps.secrets.outputs.VAULT_LICENSE }}
run: |
export PATH="${PWD}/bin:${PATH}"
# Run Ember tests
cd ui
mkdir -p test-results/qunit
yarn ${{ needs.setup.outputs.is-enterprise == 'true' && 'test' || 'test:oss' }}
- if: always()
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
with:
name: test-results-ui
path: ui/test-results
- if: always()
uses: test-summary/action@fee35d7df20790255fe6aa92cf0f6d28092ecf2f # v2.2
with:
paths: "ui/test-results/qunit/results.xml"
show: "fail"
tests-completed:
needs:
- setup
- test-go
- test-go-testonly
- test-go-race
- test-go-fips
- test-ui
if: always()
runs-on: ${{ github.repository == 'hashicorp/vault' && 'ubuntu-latest' || fromJSON('["self-hosted","linux","small"]') }}
permissions: write-all # Ensure we have id-token:write access for vault-auth.
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
# Determine the overall status of our required test jobs.
- name: Determine status
id: status
run: |
# Determine the overall status of the job. We allow fips and race tests to fail so we
# don't consider their result here.
#
# Encode the needs context into JSON, filter out unrequired workflows, shape the result
# into a more useful schema. Determine the overall status by comparing the total number of
# successful results with the number of required jobs.
if results=$(jq -rec 'del(.["test-go-fips"], .["test-go-race"]) as $required
| $required | keys as $jobs
| reduce $jobs[] as $job ([]; . + [{job: $job}+$required[$job]])' <<< '${{ toJSON(needs) }}'
); then
# Determine if all of our required jobs have succeeded.
if jq -rec 'length as $expected
| [.[] | select((.result == "success") or (.result == "skipped"))] | length as $got
| $expected == $got' <<< "$results"; then
msg="All required test jobs succeeded!"
result="success"
else
msg="One or more required test jobs failed!"
result="failed"
fi
else
msg="Failed to decode and filter test results"
result="failed"
results="''"
fi
{
echo "msg=${msg}"
echo "result=${result}"
echo "results<<EOFRESULTS"$'\n'"${results}"$'\n'EOFRESULTS
} | tee -a "$GITHUB_OUTPUT"
- if: needs.setup.outputs.is-enterprise == 'true'
id: vault-auth
name: Vault Authenticate
run: vault-auth
- if: needs.setup.outputs.is-enterprise == 'true'
id: secrets
name: Fetch Vault Secrets
uses: hashicorp/vault-action@9f522b85981b491eab9a52c144d15aedbd0bf371 # v2.8.0
with:
url: ${{ steps.vault-auth.outputs.addr }}
caCertificate: ${{ steps.vault-auth.outputs.ca_certificate }}
token: ${{ steps.vault-auth.outputs.token }}
secrets: |
kv/data/github/${{ github.repository }}/github_actions_notifications_bot token | SLACK_BOT_TOKEN;
- id: slackbot-token
run:
echo "slackbot-token=${{ needs.setup.outputs.is-enterprise != 'true' && secrets.SLACK_BOT_TOKEN || steps.secrets.outputs.SLACK_BOT_TOKEN }}" >> "$GITHUB_OUTPUT"
- if: |
always() &&
needs.setup.outputs.workflow-trigger == 'push' &&
(
needs.test-go.result == 'failure' ||
needs.test-go-race.result == 'failure' ||
needs.test-go-race.outputs.data-race-result == 'failure' ||
needs.test-go-testonly.result == 'failure' ||
needs.test-ui.result == 'failure'
)
name: Notify build failures in Slack
uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0
# We intentionally aren't using the following here since it's from an internal repo
# uses: hashicorp/cloud-gha-slack-notifier@730a033037b8e603adf99ebd3085f0fdfe75e2f4 #v1
env:
SLACK_BOT_TOKEN: ${{ steps.slackbot-token.outputs.slackbot-token }}
with:
channel-id: "C05AABYEA9Y" # sent to #feed-vault-ci-official, use "C05Q4D5V89W"/test-vault-ci-slack-integration for testing
payload: |
{
"text": "CE test failures on ${{ github.ref_name }}",
"text": "${{ github.repository }} build failures on ${{ github.ref_name }}",
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": ":rotating_light: ${{ github.repository }} test failures on ${{ github.ref_name }} :rotating_light:",
"emoji": true
}
},
{
"type": "divider"
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "${{ needs.test-go.result != 'failure' && ':white_check_mark:' || ':x:' }} Go tests\n${{ needs.test-go-race.result != 'failure' && ':white_check_mark:' || ':x:' }} Go race tests\n\t\t${{ needs.test-go-race.outputs.data-race-result != 'success' && ':x:' || ':white_check_mark:' }} Data races detected\n${{ needs.test-go-testonly.result != 'failure' && ':white_check_mark:' || ':x:' }} Go testonly tests\n${{ needs.test-ui.result != 'failure' && ':white_check_mark:' || ':x:' }} UI tests"
},
"accessory": {
"type": "button",
"text": {
"type": "plain_text",
"text": "View Failing Workflow",
"emoji": true
},
"url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
}
}
]
}
# Only create the PR summary if it's a pull request and it is not a fork as we need access
# to secrets.
- if: ${{ needs.setup.outputs.is-fork == 'false' }}
name: Download failure summaries
uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1
with:
pattern: failure-summary-*.md
path: failure-summaries
merge-multiple: true
- if: ${{ needs.setup.outputs.is-fork == 'false' }}
id: prepare-failure-summary
name: Prepare failure summary
run: |
# Sort all of the summary table rows and push them to a temp file.
temp_file_name=temp-$(date +%s)
cat failure-summaries/*.md | sort >> "$temp_file_name"
# If there are test failures, present them in a format of a GitHub Markdown table.
if [ -s "$temp_file_name" ]; then
# Here we create the headings for the summary table
{
echo "| Test Type | Package | Test | Elapsed | Runner Index | Logs |"
echo "| --------- | ------- | ---- | ------- | ------------ | ---- |"
cat "$temp_file_name"
} >> "$GITHUB_STEP_SUMMARY"
else
if [ "${{ steps.status.outputs.result }}" == 'success' ]; then
echo "### All required Go tests passed! :white_check_mark:" >> "$GITHUB_STEP_SUMMARY"
fi
fi
{
echo 'table-test-results<<EOFTABLE'
cat "$temp_file_name"
echo EOFTABLE
} | tee -a "$GITHUB_OUTPUT"
- name: Create comment
if: github.head_ref != '' && needs.setup.outputs.is-fork == 'false'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
RUN_ID: ${{ github.run_id }}
REPO: ${{ github.event.repository.name }}
RESULT: ${{ steps.status.outputs.result }}
TABLE_DATA: ${{ steps.prepare-failure-summary.outputs.table-test-results }}
run: ./.github/scripts/report-ci-status.sh
- if: always() && steps.status.outputs.result != 'success'
name: Check for failed status
run: |
echo "${{ steps.status.outputs.msg }}: ${{ steps.status.outputs.results }}"
exit 1