Skip to content

Commit

Permalink
Release 2.1.0
Browse files Browse the repository at this point in the history
`webauthn-server-core`:

Changes:

- Log messages on attestation certificate path validation failure now include
  the attestation object.

Deprecations:

- Deprecated method `AssertionResult.getCredentialId(): ByteArray`. Use
  `.getCredential().getCredentialId()` instead.
- Deprecated method `AssertionResult.getUserHandle(): ByteArray`. Use
  `.getCredential().getUserHandle()` instead.

New features:

- Added method `FidoMetadataDownloader.refreshBlob()`.
- Added function `COSEAlgorithmIdentifier.fromPublicKey(ByteArray)`.
- Added method `AssertionResult.getCredential(): RegisteredCredential`.
- Added support for the `"tpm"` attestation statement format.
- Added support for ES384 and ES512 signature algorithms.
- Added property `policyTreeValidator` to `TrustRootsResult`. If set, the given
  predicate function will be used to validate the certificate policy tree after
  successful attestation certificate path validation. This may be required for
  some JCA providers to accept attestation certificates with critical
  certificate policy extensions. See the JavaDoc for
  `TrustRootsResultBuilder.policyTreeValidator(Predicate)` for more information.
- Added enum value `AttestationConveyancePreference.ENTERPRISE`.
- (Experimental) Added constant `AuthenticatorTransport.HYBRID`.

Fixes:

- Fixed various typos and mistakes in JavaDocs.
- Moved version constraints for test dependencies from meta-module
  `webauthn-server-parent` to unpublished test meta-module.
- `yubico-util` dependency removed from downstream compile scope.
- Fixed missing JavaDoc on `TrustRootsResult` getters and builder setters.

`webauthn-server-attestation`:

Changes:

- The `AuthenticatorToBeFiltered` argument of the `FidoMetadataService` runtime
  filter now omits zero AAGUIDs.
- Promoted log messages in `FidoMetadataDownloader` about BLOB signature failure
  and cache corruption from DEBUG level to WARN level.

Fixes:

- Fixed various typos and mistakes in JavaDocs.
- `FidoMetadataDownloader` now verifies the SHA-256 hash of the cached trust
  root certificate, as promised in the JavaDoc of `useTrustRootCacheFile` and
  `useTrustRootCache`.
- BouncyCastle dependency dropped.
- Guava dependency dropped (but still remains in core module).
- If BLOB download fails, `FidoMetadataDownloader` now correctly falls back to
  cache if available.
  • Loading branch information
emlun committed Oct 12, 2022
2 parents 16e0acb + 4ddf825 commit 3468431
Show file tree
Hide file tree
Showing 119 changed files with 6,481 additions and 4,541 deletions.
49 changes: 49 additions & 0 deletions .github/actions/pit-results-badge/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Create Shields.io badge from PIT mutation test results
author: Emil Lundberg <emil@yubico.com>
description: |
Parses a [PIT][pitest] report file and outputs a [Shields.io][shields]
[endpoint badge][endpoint] definition file.
[endpoint]: https://shields.io/endpoint
[pitest]: https://pitest.org/
[shields]: https://shields.io/
inputs:
cache-seconds:
default: 3600
description: Passed through as cacheSeconds to Shields.io.

label:
default: "mutation coverage"
description: Label for the left side of the badge.

mutations-file:
default: build/reports/pitest/mutations.xml
description: Path to the PIT report XML file.

output-file:
required: true
description: Path to write output file to.

runs:
using: "composite"

steps:
- name: Install yq (and xq)
shell: bash
run: pip install yq

- name: Create coverage badge
shell: bash
run: |
cat ${{ inputs.mutations-file }} \
| xq '.mutations.mutation
| (map(select(.["@detected"] == "true")) | length) / length
| {
schemaVersion: 1,
label: "${{ inputs.label }}",
message: "\(. * 100 | floor | tostring) %",
color: "hsl(\(. * 120 | floor | tostring), 100%, 40%)",
cacheSeconds: ${{ inputs.cache-seconds }},
}' \
> ${{ inputs.output-file }}
56 changes: 56 additions & 0 deletions .github/actions/pit-results-comment/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Post PIT mutation test results comment
author: Emil Lundberg <emil@yubico.com>
description: |
Parses a [PIT][pitest] report file, compares it to a previous report,
and posts a summary as a commit comment to the commit that triggered the workflow.
[pitest]: https://pitest.org/
inputs:
mutations-file:
default: build/reports/pitest/mutations.xml
description: Path to the PIT report XML file.

prev-commit:
default: ''
description: |
The full commit SHA of the previous run of this action.
If set, the comment will include a link to the previous commit.
prev-mutations-file:
required: true
description: Path to the PIT report XML file from the previous run of this action.

token:
default: ${{ github.token }}
description: GITHUB_TOKEN or a PAT with permission to write commit comments.

runs:
using: "composite"

steps:
- name: Install yq (and xq)
shell: bash
run: pip install yq

- name: Post results comment
shell: bash
run: |
RESULTS_COMMENT_FILE=$(mktemp)
NEW_STATS_FILE=$(mktemp)
PREV_STATS_FILE=$(mktemp)
./.github/actions/pit-results-comment/compute-stats.sh "${{ inputs.mutations-file }}" > "${NEW_STATS_FILE}"
if [[ -f "${{ inputs.prev-mutations-file }}" ]]; then
./.github/actions/pit-results-comment/compute-stats.sh "${{ inputs.prev-mutations-file }}" > "${PREV_STATS_FILE}"
else
echo 'Previous mutations file not found, using current as placeholder.'
cp "${NEW_STATS_FILE}" "${PREV_STATS_FILE}"
fi
./.github/actions/pit-results-comment/stats-to-comment.sh "${PREV_STATS_FILE}" "${NEW_STATS_FILE}" "${{ inputs.prev-commit }}" > "${RESULTS_COMMENT_FILE}"
curl -X POST \
-H "Authorization: Bearer ${{ inputs.token }}" \
${{ github.api_url }}/repos/${{ github.repository }}/commits/${{ github.sha }}/comments -d @"${RESULTS_COMMENT_FILE}"
10 changes: 10 additions & 0 deletions .github/actions/pit-results-comment/compute-stats.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash

xq '.mutations.mutation
| group_by(.mutatedClass | split(".") | .[:-1])
| INDEX(.[0].mutatedClass | split(".") | .[:-1] | join("."))
| map_values({
detected: (map(select(.["@detected"] == "true")) | length),
mutations: length,
})
' "${1}"
79 changes: 79 additions & 0 deletions .github/actions/pit-results-comment/stats-to-comment.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/bin/bash

make-contents() {
cat << EOF
## Mutation test results
Package | Coverage | Stats | Prev | Prev |
------- | --------:|:-----:| ----:|:----:|
EOF

jq -s '.[0] as $old | .[1] as $new
| {
packages: (
$old | keys
| map({
("`\(.)`"): {
before: {
detected: $old[.].detected,
mutations: $old[.].mutations,
},
after: {
detected: $new[.].detected,
mutations: $new[.].mutations,
},
percentage_diff: (($new[.].detected / $new[.].mutations - $old[.].detected / $old[.].mutations) * 100 | round),
},
})
| add
),
overall: {
before: {
detected: [($old[] | .detected)] | add,
mutations: [($old[] | .mutations)] | add,
},
after: {
detected: [($new[] | .detected)] | add,
mutations: [($new[] | .mutations)] | add,
},
percentage_diff: (
(
([($new[] | .detected)] | add) / ([($new[] | .mutations)] | add)
- ([($old[] | .detected)] | add) / ([($old[] | .mutations)] | add)
) * 100 | round
),
},
}
| { ("**Overall**"): .overall } + .packages
| to_entries
| .[]
| def difficon:
if .after.detected == .after.mutations then ":trophy:"
elif .percentage_diff > 0 then ":green_circle:"
elif .percentage_diff < 0 then ":small_red_triangle_down:"
else ":small_blue_diamond:"
end;
def triangles:
if . > 0 then ":small_red_triangle:"
elif . < 0 then ":small_red_triangle_down:"
else ":small_blue_diamond:"
end;
"\(.key) | **\(.value.after.detected / .value.after.mutations * 100 | floor) %** \(.value | difficon) | \(.value.after.detected) \(.value.after.detected - .value.before.detected | triangles) / \(.value.after.mutations) \(.value.after.mutations - .value.before.mutations | triangles)| \(.value.before.detected / .value.before.mutations * 100 | floor) % | \(.value.before.detected) / \(.value.before.mutations)"
' \
"${1}" "${2}" --raw-output

if [[ -n "${3}" ]]; then
cat << EOF
Previous run: ${3}
EOF

cat << EOF
Detailed reports: [workflow run #${GITHUB_RUN_NUMBER}](/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID})
EOF
fi

}

make-contents "$@" | python -c 'import json; import sys; print(json.dumps({"body": sys.stdin.read()}))'
10 changes: 10 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,13 @@ updates:
directory: "/"
schedule:
interval: "daily"

ignore:
# Spotless patch updates are too noisy
- dependency-name: "spotless-plugin-gradle"
update-types: ["version-update:semver-patch"]

- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
45 changes: 34 additions & 11 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,41 +1,58 @@
# This name is shown in the status badge in the README
name: build

on: [push, pull_request]
on:
push:
branches-ignore:
- 'tmp**'
pull_request:
branches-ignore:
- 'tmp**'

jobs:
test:
name: JDK ${{matrix.java}}
name: JDK ${{ matrix.java }} ${{ matrix.distribution }}

runs-on: ubuntu-latest
strategy:
matrix:
java: [8, 11, 16]
java: [8, 11, 17, 18]
distribution: [temurin]
include:
- java: 17
distribution: zulu
- java: 17
distribution: microsoft

outputs:
report-java: 17
report-dist: temurin

steps:
- name: Check out code
uses: actions/checkout@v1
uses: actions/checkout@v3

- name: Set up JDK
uses: actions/setup-java@v1
uses: actions/setup-java@v3
with:
java-version: ${{ matrix.java }}
distribution: ${{ matrix.distribution }}

- name: Run tests
run: ./gradlew cleanTest test

- name: Archive HTML test report
if: ${{ always() }}
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: test-reports-java${{ matrix.java }}-html
name: test-reports-java${{ matrix.java }}-${{ matrix.distribution }}-html
path: "*/build/reports/**"

- name: Archive JUnit test report
if: ${{ always() }}
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: test-reports-java${{ matrix.java }}-xml
name: test-reports-java${{ matrix.java }}-${{ matrix.distribution }}-xml
path: "*/build/test-results/**/*.xml"

- name: Build JavaDoc
Expand All @@ -47,11 +64,17 @@ jobs:
runs-on: ubuntu-latest
if: ${{ always() && github.event_name == 'pull_request' }}

permissions:
checks: write
pull-requests: write

steps:
- name: Download artifacts
uses: actions/download-artifact@v2
uses: actions/download-artifact@v3
with:
name: test-reports-java${{ needs.test.outputs.report-java }}-${{ needs.test.outputs.report-dist }}-xml

- name: Publish test results
uses: EnricoMi/publish-unit-test-result-action@v1
uses: EnricoMi/publish-unit-test-result-action@v2
with:
files: "**/*.xml"
16 changes: 12 additions & 4 deletions .github/workflows/code-formatting.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# This name is shown in the status badge in the README
name: code-formatting

on: [push, pull_request]
on:
push:
branches-ignore:
- 'tmp**'
pull_request:
branches-ignore:
- 'tmp**'

jobs:
test:
Expand All @@ -10,16 +16,18 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
java: [11]
java: [17]
distribution: [temurin]

steps:
- name: Check out code
uses: actions/checkout@v1
uses: actions/checkout@v3

- name: Set up JDK
uses: actions/setup-java@v1
uses: actions/setup-java@v3
with:
java-version: ${{ matrix.java }}
distribution: ${{ matrix.distribution }}

- name: Check code formatting
run: ./gradlew spotlessCheck
20 changes: 14 additions & 6 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ name: "Code scanning - action"

on:
push:
branches-ignore: 'dependabot/**'
branches-ignore:
- 'dependabot/**'
- 'tmp**'
pull_request:
branches-ignore:
- 'tmp**'
schedule:
- cron: '0 12 * * 2'

Expand All @@ -12,17 +16,21 @@ jobs:

runs-on: ubuntu-latest

permissions:
security-events: write

steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3

- uses: actions/setup-java@v1
- uses: actions/setup-java@v3
with:
java-version: '11'
java-version: 17
distribution: temurin

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
with:
languages: java

Expand All @@ -31,4 +39,4 @@ jobs:
./gradlew jar
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2
Loading

1 comment on commit 3468431

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mutation test results

Package Coverage Stats Prev Prev
Overall 81 % 🔹 1234 🔺 / 1517 🔺 81 % 1113 / 1373
com.yubico.fido.metadata 67 % 🟢 215 🔺 / 318 🔺 66 % 202 / 305
com.yubico.internal.util 37 % 🔹 36 🔹 / 97 🔹 37 % 36 / 97
com.yubico.webauthn 87 % 🔻 549 🔺 / 628 🔺 88 % 453 / 512
com.yubico.webauthn.attestation 92 % 🔻 13 🔺 / 14 🔺 100 % 5 / 5
com.yubico.webauthn.data 93 % 🔹 387 🔺 / 413 🔺 94 % 383 / 407
com.yubico.webauthn.extension.appid 100 % 🏆 13 🔹 / 13 🔹 100 % 13 / 13
com.yubico.webauthn.extension.uvm 87 % 🔹 21 🔹 / 24 🔹 87 % 21 / 24
com.yubico.webauthn.meta 0 % 🔹 0 🔹 / 10 🔹 0 % 0 / 10

Previous run: 70d6d17

Detailed reports: workflow run #178

Please sign in to comment.