diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml index e427962e..6e70cdcb 100644 --- a/.github/workflows/auto-merge.yml +++ b/.github/workflows/auto-merge.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Dependabot metadata id: metadata - uses: dependabot/fetch-metadata@cd6e996708b8cfe0b639401134a3b9a3177be7b2 # v1.5.1 + uses: dependabot/fetch-metadata@c9c4182bf1b97f5224aee3906fd373f6b61b4526 # v1.6.0 with: github-token: "${{ secrets.GITHUB_TOKEN }}" - name: Enable auto-merge for Dependabot PRs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ae85c2d3..1a07ab45 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout source - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3 + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3 - name: Setup node uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 with: @@ -56,7 +56,7 @@ jobs: shell: ${{ matrix.platform.shell }} steps: - name: Checkout source - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3 + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3 - name: Setup node uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9fb9b34f..21bf718b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: id-token: write steps: - name: Checkout source - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3 + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3 - name: Setup node uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 @@ -36,7 +36,7 @@ jobs: run: npm ci - name: Create Release Pull Request - uses: changesets/action@d89c1de63c7f28ac47ec85ed395f5f1d045d4697 # v1.4.4 + uses: changesets/action@f13b1baaa620fde937751f5d2c3572b9da32af23 # v1.4.5 with: publish: npm run release env: diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index ff14c940..66ce4016 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -32,12 +32,12 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.1.0 + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.1.0 with: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@80e868c13c90f172d68d1f4501dee99e2479f7af # v2.1.3 + uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # v2.2.0 with: results_file: results.sarif results_format: sarif @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@83f0fe6c4988d98a455712a27f0255212bba9bd4 # v2.3.6 + uses: github/codeql-action/upload-sarif@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 with: sarif_file: results.sarif diff --git a/.github/workflows/smoke-test.yml b/.github/workflows/smoke-test.yml index 98a23b29..0748284f 100644 --- a/.github/workflows/smoke-test.yml +++ b/.github/workflows/smoke-test.yml @@ -19,7 +19,7 @@ jobs: id-token: write steps: - name: Checkout source - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3 + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3 - name: Setup node uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3 with: diff --git a/README.md b/README.md index 6da9c5a6..484c874c 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,8 @@ JavaScript libraries for interacting with [Sigstore][6] services. * [`sigstore`](./packages/client) - Client library implementing Sigstore signing/verification workflows. * [`@sigstore/cli`](./packages/cli) - Command line interface for signing/verifying artifacts with Sigstore. * [`@sigstore/tuf`](./packages/tuf) - Library for interacting with the Sigstore TUF repository. -* [`@sigstore/rekor-types`](./packages/tuf) - TypeScript types for the Sigstore Rekor REST API. +* [`@sigstore/rekor-types`](./packages/rekor-types) - TypeScript types for the Sigstore Rekor REST API. +* [`@sigstore/mock`](./packages/mock) - Mocking library for Sigstore services. ## Development diff --git a/package-lock.json b/package-lock.json index 7c9c3f9d..29095615 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,20 +12,22 @@ "./packages/*" ], "devDependencies": { - "@changesets/cli": "^2.26.0", - "@tsconfig/node14": "^1.0.3", + "@changesets/cli": "^2.26.2", + "@total-typescript/shoehorn": "^0.1.1", + "@tsconfig/node14": "^14.1.0", "@types/jest": "^29.5.2", - "@types/node": "^20.2.5", - "@typescript-eslint/eslint-plugin": "^5.59.9", - "@typescript-eslint/parser": "^5.59.9", - "eslint": "^8.42.0", + "@types/node": "^20.3.2", + "@typescript-eslint/eslint-plugin": "^5.60.1", + "@typescript-eslint/parser": "^5.60.1", + "eslint": "^8.43.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-prettier": "^4.0.0", "jest": "^29.4.1", "nock": "^13.2.4", "prettier": "^2.6.2", - "ts-jest": "^29.0.5", - "typescript": "^5.1.3" + "shx": "^0.3.3", + "ts-jest": "^29.1.1", + "typescript": "^5.1.6" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -648,12 +650,13 @@ "license": "MIT" }, "node_modules/@changesets/apply-release-plan": { - "version": "6.1.3", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-6.1.4.tgz", + "integrity": "sha512-FMpKF1fRlJyCZVYHr3CbinpZZ+6MwvOtWUuO8uo+svcATEoc1zRDcj23pAurJ2TZ/uVz1wFHH6K3NlACy0PLew==", "dev": true, - "license": "MIT", "dependencies": { "@babel/runtime": "^7.20.1", - "@changesets/config": "^2.3.0", + "@changesets/config": "^2.3.1", "@changesets/get-version-range-type": "^0.3.2", "@changesets/git": "^2.0.0", "@changesets/types": "^5.2.1", @@ -664,44 +667,30 @@ "outdent": "^0.5.0", "prettier": "^2.7.1", "resolve-from": "^5.0.0", - "semver": "^5.4.1" + "semver": "^7.5.3" } }, "node_modules/@changesets/apply-release-plan/node_modules/resolve-from": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/@changesets/apply-release-plan/node_modules/semver": { - "version": "5.7.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, "node_modules/@changesets/assemble-release-plan": { - "version": "5.2.3", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-5.2.4.tgz", + "integrity": "sha512-xJkWX+1/CUaOUWTguXEbCDTyWJFECEhmdtbkjhn5GVBGxdP/JwaHBIU9sW3FR6gD07UwZ7ovpiPclQZs+j+mvg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/runtime": "^7.20.1", "@changesets/errors": "^0.1.4", - "@changesets/get-dependents-graph": "^1.3.5", + "@changesets/get-dependents-graph": "^1.3.6", "@changesets/types": "^5.2.1", "@manypkg/get-packages": "^1.1.3", - "semver": "^5.4.1" - } - }, - "node_modules/@changesets/assemble-release-plan/node_modules/semver": { - "version": "5.7.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" + "semver": "^7.5.3" } }, "node_modules/@changesets/changelog-git": { @@ -713,18 +702,19 @@ } }, "node_modules/@changesets/cli": { - "version": "2.26.1", + "version": "2.26.2", + "resolved": "https://registry.npmjs.org/@changesets/cli/-/cli-2.26.2.tgz", + "integrity": "sha512-dnWrJTmRR8bCHikJHl9b9HW3gXACCehz4OasrXpMp7sx97ECuBGGNjJhjPhdZNCvMy9mn4BWdplI323IbqsRig==", "dev": true, - "license": "MIT", "dependencies": { "@babel/runtime": "^7.20.1", - "@changesets/apply-release-plan": "^6.1.3", - "@changesets/assemble-release-plan": "^5.2.3", + "@changesets/apply-release-plan": "^6.1.4", + "@changesets/assemble-release-plan": "^5.2.4", "@changesets/changelog-git": "^0.1.14", - "@changesets/config": "^2.3.0", + "@changesets/config": "^2.3.1", "@changesets/errors": "^0.1.4", - "@changesets/get-dependents-graph": "^1.3.5", - "@changesets/get-release-plan": "^3.0.16", + "@changesets/get-dependents-graph": "^1.3.6", + "@changesets/get-release-plan": "^3.0.17", "@changesets/git": "^2.0.0", "@changesets/logger": "^0.0.5", "@changesets/pre": "^1.0.14", @@ -733,7 +723,7 @@ "@changesets/write": "^0.2.3", "@manypkg/get-packages": "^1.1.3", "@types/is-ci": "^3.0.0", - "@types/semver": "^6.0.0", + "@types/semver": "^7.5.0", "ansi-colors": "^4.1.3", "chalk": "^2.1.0", "enquirer": "^2.3.0", @@ -746,7 +736,7 @@ "p-limit": "^2.2.0", "preferred-pm": "^3.0.0", "resolve-from": "^5.0.0", - "semver": "^5.4.1", + "semver": "^7.5.3", "spawndamnit": "^2.0.0", "term-size": "^2.1.0", "tty-table": "^4.1.5" @@ -755,11 +745,6 @@ "changeset": "bin.js" } }, - "node_modules/@changesets/cli/node_modules/@types/semver": { - "version": "6.2.3", - "dev": true, - "license": "MIT" - }, "node_modules/@changesets/cli/node_modules/ansi-styles": { "version": "3.2.1", "dev": true, @@ -835,14 +820,6 @@ "node": ">=8" } }, - "node_modules/@changesets/cli/node_modules/semver": { - "version": "5.7.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, "node_modules/@changesets/cli/node_modules/supports-color": { "version": "5.5.0", "dev": true, @@ -855,12 +832,13 @@ } }, "node_modules/@changesets/config": { - "version": "2.3.0", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@changesets/config/-/config-2.3.1.tgz", + "integrity": "sha512-PQXaJl82CfIXddUOppj4zWu+987GCw2M+eQcOepxN5s+kvnsZOwjEJO3DH9eVy+OP6Pg/KFEWdsECFEYTtbg6w==", "dev": true, - "license": "MIT", "dependencies": { "@changesets/errors": "^0.1.4", - "@changesets/get-dependents-graph": "^1.3.5", + "@changesets/get-dependents-graph": "^1.3.6", "@changesets/logger": "^0.0.5", "@changesets/types": "^5.2.1", "@manypkg/get-packages": "^1.1.3", @@ -870,28 +848,31 @@ }, "node_modules/@changesets/errors": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@changesets/errors/-/errors-0.1.4.tgz", + "integrity": "sha512-HAcqPF7snsUJ/QzkWoKfRfXushHTu+K5KZLJWPb34s4eCZShIf8BFO3fwq6KU8+G7L5KdtN2BzQAXOSXEyiY9Q==", "dev": true, - "license": "MIT", "dependencies": { "extendable-error": "^0.1.5" } }, "node_modules/@changesets/get-dependents-graph": { - "version": "1.3.5", + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@changesets/get-dependents-graph/-/get-dependents-graph-1.3.6.tgz", + "integrity": "sha512-Q/sLgBANmkvUm09GgRsAvEtY3p1/5OCzgBE5vX3vgb5CvW0j7CEljocx5oPXeQSNph6FXulJlXV3Re/v3K3P3Q==", "dev": true, - "license": "MIT", "dependencies": { "@changesets/types": "^5.2.1", "@manypkg/get-packages": "^1.1.3", "chalk": "^2.1.0", "fs-extra": "^7.0.1", - "semver": "^5.4.1" + "semver": "^7.5.3" } }, "node_modules/@changesets/get-dependents-graph/node_modules/ansi-styles": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -901,8 +882,9 @@ }, "node_modules/@changesets/get-dependents-graph/node_modules/chalk": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -914,45 +896,42 @@ }, "node_modules/@changesets/get-dependents-graph/node_modules/color-convert": { "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "node_modules/@changesets/get-dependents-graph/node_modules/color-name": { "version": "1.1.3", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true }, "node_modules/@changesets/get-dependents-graph/node_modules/escape-string-regexp": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/@changesets/get-dependents-graph/node_modules/has-flag": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, - "node_modules/@changesets/get-dependents-graph/node_modules/semver": { - "version": "5.7.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, "node_modules/@changesets/get-dependents-graph/node_modules/supports-color": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -961,13 +940,14 @@ } }, "node_modules/@changesets/get-release-plan": { - "version": "3.0.16", + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-3.0.17.tgz", + "integrity": "sha512-6IwKTubNEgoOZwDontYc2x2cWXfr6IKxP3IhKeK+WjyD6y3M4Gl/jdQvBw+m/5zWILSOCAaGLu2ZF6Q+WiPniw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/runtime": "^7.20.1", - "@changesets/assemble-release-plan": "^5.2.3", - "@changesets/config": "^2.3.0", + "@changesets/assemble-release-plan": "^5.2.4", + "@changesets/config": "^2.3.1", "@changesets/pre": "^1.0.14", "@changesets/read": "^0.5.9", "@changesets/types": "^5.2.1", @@ -976,13 +956,15 @@ }, "node_modules/@changesets/get-version-range-type": { "version": "0.3.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@changesets/get-version-range-type/-/get-version-range-type-0.3.2.tgz", + "integrity": "sha512-SVqwYs5pULYjYT4op21F2pVbcrca4qA/bAA3FmFXKMN7Y+HcO8sbZUTx3TAy2VXulP2FACd1aC7f2nTuqSPbqg==", + "dev": true }, "node_modules/@changesets/git": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@changesets/git/-/git-2.0.0.tgz", + "integrity": "sha512-enUVEWbiqUTxqSnmesyJGWfzd51PY4H7mH9yUw0hPVpZBJ6tQZFMU3F3mT/t9OJ/GjyiM4770i+sehAn6ymx6A==", "dev": true, - "license": "MIT", "dependencies": { "@babel/runtime": "^7.20.1", "@changesets/errors": "^0.1.4", @@ -995,16 +977,18 @@ }, "node_modules/@changesets/logger": { "version": "0.0.5", + "resolved": "https://registry.npmjs.org/@changesets/logger/-/logger-0.0.5.tgz", + "integrity": "sha512-gJyZHomu8nASHpaANzc6bkQMO9gU/ib20lqew1rVx753FOxffnCrJlGIeQVxNWCqM+o6OOleCo/ivL8UAO5iFw==", "dev": true, - "license": "MIT", "dependencies": { "chalk": "^2.1.0" } }, "node_modules/@changesets/logger/node_modules/ansi-styles": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -1014,8 +998,9 @@ }, "node_modules/@changesets/logger/node_modules/chalk": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -1027,37 +1012,42 @@ }, "node_modules/@changesets/logger/node_modules/color-convert": { "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "node_modules/@changesets/logger/node_modules/color-name": { "version": "1.1.3", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true }, "node_modules/@changesets/logger/node_modules/escape-string-regexp": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/@changesets/logger/node_modules/has-flag": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@changesets/logger/node_modules/supports-color": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -1067,8 +1057,9 @@ }, "node_modules/@changesets/parse": { "version": "0.3.16", + "resolved": "https://registry.npmjs.org/@changesets/parse/-/parse-0.3.16.tgz", + "integrity": "sha512-127JKNd167ayAuBjUggZBkmDS5fIKsthnr9jr6bdnuUljroiERW7FBTDNnNVyJ4l69PzR57pk6mXQdtJyBCJKg==", "dev": true, - "license": "MIT", "dependencies": { "@changesets/types": "^5.2.1", "js-yaml": "^3.13.1" @@ -1076,16 +1067,18 @@ }, "node_modules/@changesets/parse/node_modules/argparse": { "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, - "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } }, "node_modules/@changesets/parse/node_modules/js-yaml": { "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, - "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -1096,8 +1089,9 @@ }, "node_modules/@changesets/pre": { "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@changesets/pre/-/pre-1.0.14.tgz", + "integrity": "sha512-dTsHmxQWEQekHYHbg+M1mDVYFvegDh9j/kySNuDKdylwfMEevTeDouR7IfHNyVodxZXu17sXoJuf2D0vi55FHQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/runtime": "^7.20.1", "@changesets/errors": "^0.1.4", @@ -1108,8 +1102,9 @@ }, "node_modules/@changesets/read": { "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@changesets/read/-/read-0.5.9.tgz", + "integrity": "sha512-T8BJ6JS6j1gfO1HFq50kU3qawYxa4NTbI/ASNVVCBTsKquy2HYwM9r7ZnzkiMe8IEObAJtUVGSrePCOxAK2haQ==", "dev": true, - "license": "MIT", "dependencies": { "@babel/runtime": "^7.20.1", "@changesets/git": "^2.0.0", @@ -1123,8 +1118,9 @@ }, "node_modules/@changesets/read/node_modules/ansi-styles": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -1134,8 +1130,9 @@ }, "node_modules/@changesets/read/node_modules/chalk": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -1147,37 +1144,42 @@ }, "node_modules/@changesets/read/node_modules/color-convert": { "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "node_modules/@changesets/read/node_modules/color-name": { "version": "1.1.3", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true }, "node_modules/@changesets/read/node_modules/escape-string-regexp": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/@changesets/read/node_modules/has-flag": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@changesets/read/node_modules/supports-color": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -1267,9 +1269,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz", - "integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==", + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz", + "integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1819,8 +1821,9 @@ }, "node_modules/@manypkg/find-root": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@manypkg/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/runtime": "^7.5.5", "@types/node": "^12.7.1", @@ -1830,13 +1833,15 @@ }, "node_modules/@manypkg/find-root/node_modules/@types/node": { "version": "12.20.55", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "dev": true }, "node_modules/@manypkg/find-root/node_modules/find-up": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -1847,8 +1852,9 @@ }, "node_modules/@manypkg/find-root/node_modules/fs-extra": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -1860,8 +1866,9 @@ }, "node_modules/@manypkg/find-root/node_modules/locate-path": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -1871,8 +1878,9 @@ }, "node_modules/@manypkg/find-root/node_modules/p-limit": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -1885,8 +1893,9 @@ }, "node_modules/@manypkg/find-root/node_modules/p-locate": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -1896,8 +1905,9 @@ }, "node_modules/@manypkg/get-packages": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@manypkg/get-packages/-/get-packages-1.1.3.tgz", + "integrity": "sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==", "dev": true, - "license": "MIT", "dependencies": { "@babel/runtime": "^7.5.5", "@changesets/types": "^4.0.1", @@ -1909,13 +1919,15 @@ }, "node_modules/@manypkg/get-packages/node_modules/@changesets/types": { "version": "4.1.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@changesets/types/-/types-4.1.0.tgz", + "integrity": "sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==", + "dev": true }, "node_modules/@manypkg/get-packages/node_modules/fs-extra": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -2421,9 +2433,9 @@ } }, "node_modules/@oclif/core": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/@oclif/core/-/core-2.8.5.tgz", - "integrity": "sha512-316DLfrHQDYmWDriI4Woxk9y1wVUrPN1sZdbQLHdOdlTA9v/twe7TdHpWOriEypfl6C85NWEJKc1870yuLtjrQ==", + "version": "2.8.10", + "resolved": "https://registry.npmjs.org/@oclif/core/-/core-2.8.10.tgz", + "integrity": "sha512-coRn9vYDEnoE8Vg20aavts9+Bt5QrHhbdh0cDkImopV0MgT8i/VmgL04D33+qoHQH20XzBOMqrjk+bqQzqyaHg==", "dependencies": { "@types/cli-progress": "^3.11.0", "ansi-escapes": "^4.3.2", @@ -2541,11 +2553,11 @@ } }, "node_modules/@oclif/plugin-help": { - "version": "5.2.9", - "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-5.2.9.tgz", - "integrity": "sha512-0J3oowPURZJ4Dn1p1WpQ46E4+CoV20KTn1cvsNiDl6Hmbw+qoljKQnArJJzNFeZQxWo4R7/S42PrzKJTVYh68Q==", + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-5.2.10.tgz", + "integrity": "sha512-l3hnloPkXOLGGrepLLdj8NsBpVhhEpg4jclIeIBaZzIo6+c+/uqcL2LjvOogmSEf5g4zooRtxivwUpcFiBSaBg==", "dependencies": { - "@oclif/core": "^2.8.0" + "@oclif/core": "^2.8.7" }, "engines": { "node": ">=12.0.0" @@ -2761,6 +2773,175 @@ "@octokit/openapi-types": "^12.11.0" } }, + "node_modules/@peculiar/asn1-cms": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.3.6.tgz", + "integrity": "sha512-Kr0XsyjuElTc4NijuPYyd6YkTlbz0KCuoWnNkfPFhXjHTzbUIh/s15ixjxLj8XDrXsI1aPQp3D64uHbrs3Kuyg==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "@peculiar/asn1-x509-attr": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-csr": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.3.6.tgz", + "integrity": "sha512-gCTEB/PvUxapmxo4SzGZT1JtEdevRnphRGZZmc9oJE7+pLuj2Px0Q6x+w8VvObfozA3pyPRTq+Wkocnu64+oLw==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-ecc": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.3.6.tgz", + "integrity": "sha512-Hu1xzMJQWv8/GvzOiinaE6XiD1/kEhq2C/V89UEoWeZ2fLUcGNIvMxOr/pMyL0OmpRWj/mhCTXOZp4PP+a0aTg==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-pfx": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.3.6.tgz", + "integrity": "sha512-bScrrpQ59mppcoZLkDEW/Wruu+daSWQxpR2vqGjg69+v7VoQ1Le/Elm10ObfNShV2eNNridNQcOQvsHMLvUOCg==", + "dependencies": { + "@peculiar/asn1-cms": "^2.3.6", + "@peculiar/asn1-pkcs8": "^2.3.6", + "@peculiar/asn1-rsa": "^2.3.6", + "@peculiar/asn1-schema": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-pkcs8": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.3.6.tgz", + "integrity": "sha512-poqgdjsHNiyR0gnxP8l5VjRInSgpQvOM3zLULF/ZQW67uUsEiuPfplvaNJUlNqNOCd2szGo9jKW9+JmVVpWojA==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-pkcs9": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.3.6.tgz", + "integrity": "sha512-uaxSBF60glccuu5BEZvoPsaJzebVYcQRjXx2wXsGe7Grz/BXtq5RQAJ/3i9fEXawFK/zIbvbXBBpy07cnvrqhA==", + "dependencies": { + "@peculiar/asn1-cms": "^2.3.6", + "@peculiar/asn1-pfx": "^2.3.6", + "@peculiar/asn1-pkcs8": "^2.3.6", + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "@peculiar/asn1-x509-attr": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-rsa": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.3.6.tgz", + "integrity": "sha512-DswjJyAXZnvESuImGNTvbNKvh1XApBVqU+r3UmrFFTAI23gv62byl0f5OFKWTNhCf66WQrd3sklpsCZc/4+jwA==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-schema": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.6.tgz", + "integrity": "sha512-izNRxPoaeJeg/AyH8hER6s+H7p4itk+03QCa4sbxI3lNdseQYCuxzgsuNK8bTXChtLTjpJz6NmXKA73qLa3rCA==", + "dependencies": { + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-x509": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.3.6.tgz", + "integrity": "sha512-dRwX31R1lcbIdzbztiMvLNTDoGptxdV7HocNx87LfKU0fEWh7fTWJjx4oV+glETSy6heF/hJHB2J4RGB3vVSYg==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "asn1js": "^3.0.5", + "ipaddr.js": "^2.0.1", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-x509-attr": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.3.6.tgz", + "integrity": "sha512-x5Kax8xp3fz+JSc+4Sq0/SUXIdbJeOePibYqvjHMGkP6AoeCOVcP+gg7rZRRGkTlDSyQnAoUTgTEsfAfFEd1/g==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-x509/node_modules/ipaddr.js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", + "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@peculiar/webcrypto": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.3.tgz", + "integrity": "sha512-VtaY4spKTdN5LjJ04im/d/joXuvLbQdgy5Z4DXF4MFZhQ+MTrejbNMkfZBp1Bs3O5+bFqnJgyGdPuZQflvIa5A==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.2", + "tslib": "^2.5.0", + "webcrypto-core": "^1.7.7" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/@peculiar/x509": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.9.3.tgz", + "integrity": "sha512-rv1TrPi85jOtBJ7Xmqx08p3QPIE2avd5CWgtiwOIAbhV3hoUCLlGIUtXn9CuShfFBCjGy8EnZRQ6YbNFaDL8vw==", + "dependencies": { + "@peculiar/asn1-cms": "^2.3.4", + "@peculiar/asn1-csr": "^2.3.4", + "@peculiar/asn1-ecc": "^2.3.4", + "@peculiar/asn1-pkcs9": "^2.3.4", + "@peculiar/asn1-rsa": "^2.3.4", + "@peculiar/asn1-schema": "^2.3.3", + "@peculiar/asn1-x509": "^2.3.4", + "pvtsutils": "^1.3.2", + "reflect-metadata": "^0.1.13", + "tslib": "^2.4.1", + "tsyringe": "^4.7.0" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -2774,6 +2955,14 @@ "resolved": "packages/cli", "link": true }, + "node_modules/@sigstore/jest": { + "resolved": "packages/jest", + "link": true + }, + "node_modules/@sigstore/mock": { + "resolved": "packages/mock", + "link": true + }, "node_modules/@sigstore/protobuf-specs": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.1.0.tgz", @@ -2844,9 +3033,9 @@ } }, "node_modules/@total-typescript/shoehorn": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@total-typescript/shoehorn/-/shoehorn-0.1.0.tgz", - "integrity": "sha512-XKig6hXxWnUh0fsW3LR2vxpxwLlPFokfOSR0riHKA9uXvdHDfwOOPdAOi4U/YNKLmgYUu/plUfnF3yiAAz1+Zg==", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@total-typescript/shoehorn/-/shoehorn-0.1.1.tgz", + "integrity": "sha512-XSPcazQsC2Cr7eCiAI+M2bTmMziBvFWYTYMgUDKLbU6i+7m3I2BF5gXF5vKDO8577fONs9CvmTvVa7+nMHMfxg==", "dev": true }, "node_modules/@tsconfig/node10": { @@ -2860,8 +3049,10 @@ "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" }, "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "license": "MIT" + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-14.1.0.tgz", + "integrity": "sha512-VmsCG04YR58ciHBeJKBDNMWWfYbyP8FekWVuTlpstaUPlat1D0x/tXzkWP7yCMU0eSz9V4OZU0LBWTFJ3xZf6w==", + "dev": true }, "node_modules/@tsconfig/node16": { "version": "1.0.4", @@ -2914,7 +3105,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/@tufjs/repo-mock/-/repo-mock-1.3.1.tgz", "integrity": "sha512-7IDezQbPGReWD3xmgR2pAfG61BZpvW51XnB87OfuiJOe5mkGnziCTTGITtUC3A6htQr9shkk5qIKrhpoMXBwpQ==", - "dev": true, "dependencies": { "@tufjs/models": "1.0.4", "nock": "^13.3.1" @@ -3073,7 +3263,6 @@ "version": "10.0.1", "resolved": "https://registry.npmjs.org/@types/make-fetch-happen/-/make-fetch-happen-10.0.1.tgz", "integrity": "sha512-DFKsprsL3krCqtCD+WAnWDrCJBinI0GwcgXqeIFC1ZhWZbmoTAv6Rgl+P8On/rfQIuYp2OmZymjvm9ZukWh8ZA==", - "dev": true, "dependencies": { "@types/node-fetch": "*", "@types/retry": "*", @@ -3092,15 +3281,14 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.2.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz", - "integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==" + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.2.tgz", + "integrity": "sha512-vOBLVQeCQfIcF/2Y7eKFTqrMnizK5lRNQ7ykML/5RuwVXVWxYkgwS7xbt4B6fKCUPgbSL5FSsjHQpaGQP/dQmw==" }, "node_modules/@types/node-fetch": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.3.tgz", "integrity": "sha512-ETTL1mOEdq/sxUtgtOhKjyB2Irra4cjxksvcMUR5Zr4n+PxVhsCD9WS46oPbHL3et9Zde7CNRr+WUNlcHvsX+w==", - "dev": true, "dependencies": { "@types/node": "*", "form-data": "^3.0.0" @@ -3128,8 +3316,7 @@ "node_modules/@types/retry": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", - "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", - "dev": true + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==" }, "node_modules/@types/semver": { "version": "7.5.0", @@ -3145,7 +3332,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/@types/ssri/-/ssri-7.1.1.tgz", "integrity": "sha512-DPP/jkDaqGiyU75MyMURxLWyYLwKSjnAuGe9ZCsLp9QZOpXmDfuevk769F0BS86TmRuD5krnp06qw9nSoNO+0g==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -3179,15 +3365,15 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.9.tgz", - "integrity": "sha512-4uQIBq1ffXd2YvF7MAvehWKW3zVv/w+mSfRAu+8cKbfj3nwzyqJLNcZJpQ/WZ1HLbJDiowwmQ6NO+63nCA+fqA==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.1.tgz", + "integrity": "sha512-KSWsVvsJsLJv3c4e73y/Bzt7OpqMCADUO846bHcuWYSYM19bldbAeDv7dYyV0jwkbMfJ2XdlzwjhXtuD7OY6bw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/type-utils": "5.59.9", - "@typescript-eslint/utils": "5.59.9", + "@typescript-eslint/scope-manager": "5.60.1", + "@typescript-eslint/type-utils": "5.60.1", + "@typescript-eslint/utils": "5.60.1", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -3213,14 +3399,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.9.tgz", - "integrity": "sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.60.1.tgz", + "integrity": "sha512-pHWlc3alg2oSMGwsU/Is8hbm3XFbcrb6P5wIxcQW9NsYBfnrubl/GhVVD/Jm/t8HXhA2WncoIRfBtnCgRGV96Q==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/typescript-estree": "5.59.9", + "@typescript-eslint/scope-manager": "5.60.1", + "@typescript-eslint/types": "5.60.1", + "@typescript-eslint/typescript-estree": "5.60.1", "debug": "^4.3.4" }, "engines": { @@ -3240,13 +3426,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.9.tgz", - "integrity": "sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.60.1.tgz", + "integrity": "sha512-Dn/LnN7fEoRD+KspEOV0xDMynEmR3iSHdgNsarlXNLGGtcUok8L4N71dxUgt3YvlO8si7E+BJ5Fe3wb5yUw7DQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/visitor-keys": "5.59.9" + "@typescript-eslint/types": "5.60.1", + "@typescript-eslint/visitor-keys": "5.60.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3257,13 +3443,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.9.tgz", - "integrity": "sha512-ksEsT0/mEHg9e3qZu98AlSrONAQtrSTljL3ow9CGej8eRo7pe+yaC/mvTjptp23Xo/xIf2mLZKC6KPv4Sji26Q==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.60.1.tgz", + "integrity": "sha512-vN6UztYqIu05nu7JqwQGzQKUJctzs3/Hg7E2Yx8rz9J+4LgtIDFWjjl1gm3pycH0P3mHAcEUBd23LVgfrsTR8A==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.59.9", - "@typescript-eslint/utils": "5.59.9", + "@typescript-eslint/typescript-estree": "5.60.1", + "@typescript-eslint/utils": "5.60.1", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -3284,9 +3470,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.9.tgz", - "integrity": "sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.1.tgz", + "integrity": "sha512-zDcDx5fccU8BA0IDZc71bAtYIcG9PowaOwaD8rjYbqwK7dpe/UMQl3inJ4UtUK42nOCT41jTSCwg76E62JpMcg==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3297,13 +3483,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz", - "integrity": "sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.1.tgz", + "integrity": "sha512-hkX70J9+2M2ZT6fhti5Q2FoU9zb+GeZK2SLP1WZlvUDqdMbEKhexZODD1WodNRyO8eS+4nScvT0dts8IdaBzfw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/visitor-keys": "5.59.9", + "@typescript-eslint/types": "5.60.1", + "@typescript-eslint/visitor-keys": "5.60.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -3324,17 +3510,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.9.tgz", - "integrity": "sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.60.1.tgz", + "integrity": "sha512-tiJ7FFdFQOWssFa3gqb94Ilexyw0JVxj6vBzaSpfN/8IhoKkDuSAenUKvsSHw2A/TMpJb26izIszTXaqygkvpQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/typescript-estree": "5.59.9", + "@typescript-eslint/scope-manager": "5.60.1", + "@typescript-eslint/types": "5.60.1", + "@typescript-eslint/typescript-estree": "5.60.1", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -3350,12 +3536,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.9.tgz", - "integrity": "sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.1.tgz", + "integrity": "sha512-xEYIxKcultP6E/RMKqube11pGjXH1DCo60mQoWhVYyKfLkwbIVVjYxmOenNMxILx0TjCujPTjjnTIVzm09TXIw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.9", + "@typescript-eslint/types": "5.60.1", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -3599,6 +3785,19 @@ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", "dev": true }, + "node_modules/asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "dependencies": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", @@ -3607,8 +3806,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/at-least-node": { "version": "1.0.0", @@ -3768,8 +3966,9 @@ }, "node_modules/better-path-resolve": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/better-path-resolve/-/better-path-resolve-1.0.0.tgz", + "integrity": "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==", "dev": true, - "license": "MIT", "dependencies": { "is-windows": "^1.0.0" }, @@ -3944,6 +4143,14 @@ "integrity": "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==", "dev": true }, + "node_modules/bytestreamjs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bytestreamjs/-/bytestreamjs-2.0.1.tgz", + "integrity": "sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/cacache": { "version": "17.1.0", "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.0.tgz", @@ -4116,6 +4323,11 @@ ], "license": "CC-BY-4.0" }, + "node_modules/canonicalize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-2.0.0.tgz", + "integrity": "sha512-ulDEYPv7asdKvqahuAY35c1selLdzDwHqugK92hfkzvlDCwXRRelDkR+Er33md/PtnpqHemgkuDPanZ4fiYZ8w==" + }, "node_modules/cardinal": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", @@ -4431,7 +4643,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -4778,7 +4989,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -4805,8 +5015,9 @@ }, "node_modules/detect-indent": { "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -5112,15 +5323,15 @@ } }, "node_modules/eslint": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz", - "integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==", + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz", + "integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.42.0", + "@eslint/js": "8.43.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -5413,8 +5624,9 @@ }, "node_modules/extendable-error": { "version": "0.1.7", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/extendable-error/-/extendable-error-0.1.7.tgz", + "integrity": "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==", + "dev": true }, "node_modules/external-editor": { "version": "3.1.0", @@ -5710,7 +5922,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -6790,8 +7001,9 @@ }, "node_modules/is-subdir": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-subdir/-/is-subdir-1.2.0.tgz", + "integrity": "sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==", "dev": true, - "license": "MIT", "dependencies": { "better-path-resolve": "1.0.0" }, @@ -6862,8 +7074,9 @@ }, "node_modules/is-windows": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -7609,9 +7822,9 @@ } }, "node_modules/json-schema-to-typescript": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-13.0.1.tgz", - "integrity": "sha512-VU+Spn84eLJyt8R0Bmg2soTwHQFgvrGrU7V8mXbhqWFdEYCFekSYk4JcpCzx0i/WzjEVJKAU7r0y0PVYT14E6Q==", + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-13.0.2.tgz", + "integrity": "sha512-TCaEVW4aI2FmMQe7f98mvr3/oiVmXEC1xZjkTZ9L/BSoTXFlC7p64mD5AD2d8XWycNBQZUnHwXL5iVXt1HWwNQ==", "dev": true, "dependencies": { "@bcherny/json-schema-ref-parser": "10.0.5-fork", @@ -7657,7 +7870,6 @@ }, "node_modules/json-stringify-safe": { "version": "5.0.1", - "dev": true, "license": "ISC" }, "node_modules/json5": { @@ -7808,7 +8020,6 @@ }, "node_modules/lodash": { "version": "4.17.21", - "dev": true, "license": "MIT" }, "node_modules/lodash.memoize": { @@ -7823,8 +8034,9 @@ }, "node_modules/lodash.startcase": { "version": "4.4.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", + "dev": true }, "node_modules/log-symbols": { "version": "4.1.0", @@ -8114,7 +8326,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -8123,7 +8334,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -8480,7 +8690,6 @@ "version": "13.3.1", "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.1.tgz", "integrity": "sha512-vHnopocZuI93p2ccivFyGuUfzjq2fxNyNurp7816mlT5V5HF4SzXu8lvLrVzBbNqzs+ODooZ6OksuSUNM7Njkw==", - "dev": true, "dependencies": { "debug": "^4.1.0", "json-stringify-safe": "^5.0.1", @@ -9252,9 +9461,9 @@ } }, "node_modules/oclif": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/oclif/-/oclif-3.9.0.tgz", - "integrity": "sha512-fsFyHVQYJdE50EcKrBjwzl2WT5sZUtTiRY1vqMwykgLFUDYrQS0lj7yqy2IgcPSmAWaLQryODdfBujCWOU98Ww==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/oclif/-/oclif-3.9.1.tgz", + "integrity": "sha512-gJ8gJrohFY8qEeVBOw7wgAFdwPt2CTTkEFXDTkfUeXap6URIy6ngP7g/E1A2zFt2I0wH/qQHwcfuTpfBbj1+Uw==", "dev": true, "dependencies": { "@oclif/core": "^2.8.4", @@ -9530,8 +9739,9 @@ }, "node_modules/outdent": { "version": "0.5.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.5.0.tgz", + "integrity": "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==", + "dev": true }, "node_modules/p-cancelable": { "version": "2.1.1", @@ -9544,8 +9754,9 @@ }, "node_modules/p-filter": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz", + "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==", "dev": true, - "license": "MIT", "dependencies": { "p-map": "^2.0.0" }, @@ -9555,8 +9766,9 @@ }, "node_modules/p-filter/node_modules/p-map": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6" } @@ -10073,6 +10285,21 @@ "node": ">=8" } }, + "node_modules/pkijs": { + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/pkijs/-/pkijs-3.0.15.tgz", + "integrity": "sha512-n7nAl9JpqdeQsjy+rPmswkmZ3oO/Fu5uN9me45PPQVdWjd0X7HKfL8+HYwfxihqoDSSPUIajkOcqFxEUxMqhwQ==", + "dependencies": { + "asn1js": "^3.0.5", + "bytestreamjs": "^2.0.0", + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/preferred-pm": { "version": "3.0.3", "dev": true, @@ -10218,7 +10445,6 @@ }, "node_modules/propagate": { "version": "2.0.1", - "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -10226,8 +10452,9 @@ }, "node_modules/pseudomap": { "version": "1.0.2", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", + "dev": true }, "node_modules/pump": { "version": "3.0.0", @@ -10262,12 +10489,28 @@ ], "license": "MIT" }, - "node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", - "dev": true, + "node_modules/pvtsutils": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.2.tgz", + "integrity": "sha512-+Ipe2iNUyrZz+8K/2IOo+kKikdtfhRKzNpQbruF2URmqPtoqAs8g3xS7TJvFF2GcPXjh7DkqMnpVveRFq4PgEQ==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "dev": true, "engines": { "node": ">=0.4.x" } @@ -10421,8 +10664,9 @@ }, "node_modules/read-yaml-file": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-yaml-file/-/read-yaml-file-1.1.0.tgz", + "integrity": "sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.1.5", "js-yaml": "^3.6.1", @@ -10435,16 +10679,18 @@ }, "node_modules/read-yaml-file/node_modules/argparse": { "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, - "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } }, "node_modules/read-yaml-file/node_modules/js-yaml": { "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, - "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -10455,8 +10701,9 @@ }, "node_modules/read-yaml-file/node_modules/strip-bom": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -10520,6 +10767,11 @@ "esprima": "~4.0.0" } }, + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, "node_modules/regenerator-runtime": { "version": "0.13.11", "dev": true, @@ -10774,9 +11026,9 @@ } }, "node_modules/semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -11107,8 +11359,9 @@ }, "node_modules/spawndamnit": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawndamnit/-/spawndamnit-2.0.0.tgz", + "integrity": "sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==", "dev": true, - "license": "MIT", "dependencies": { "cross-spawn": "^5.1.0", "signal-exit": "^3.0.2" @@ -11116,8 +11369,9 @@ }, "node_modules/spawndamnit/node_modules/cross-spawn": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", "dev": true, - "license": "MIT", "dependencies": { "lru-cache": "^4.0.1", "shebang-command": "^1.2.0", @@ -11126,8 +11380,9 @@ }, "node_modules/spawndamnit/node_modules/lru-cache": { "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", "dev": true, - "license": "ISC", "dependencies": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" @@ -11135,8 +11390,9 @@ }, "node_modules/spawndamnit/node_modules/shebang-command": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", "dev": true, - "license": "MIT", "dependencies": { "shebang-regex": "^1.0.0" }, @@ -11146,16 +11402,18 @@ }, "node_modules/spawndamnit/node_modules/shebang-regex": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/spawndamnit/node_modules/which": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, - "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -11165,8 +11423,9 @@ }, "node_modules/spawndamnit/node_modules/yallist": { "version": "2.1.2", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "dev": true }, "node_modules/spdx-correct": { "version": "3.1.1", @@ -11640,9 +11899,10 @@ } }, "node_modules/ts-jest": { - "version": "29.1.0", + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", "dev": true, - "license": "MIT", "dependencies": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", @@ -11650,7 +11910,7 @@ "json5": "^2.2.3", "lodash.memoize": "4.x", "make-error": "1.x", - "semver": "7.x", + "semver": "^7.5.3", "yargs-parser": "^21.0.1" }, "bin": { @@ -11723,10 +11983,15 @@ } } }, + "node_modules/ts-node/node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, "node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==" + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -11748,6 +12013,22 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, + "node_modules/tsyringe": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.7.0.tgz", + "integrity": "sha512-ncFDM1jTLsok4ejMvSW5jN1VGPQD48y2tfAR0pdptWRKYX4bkbqPt92k7KJ5RFJ1KV36JEs/+TMh7I6OUgj74g==", + "dependencies": { + "tslib": "^1.9.3" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/tsyringe/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, "node_modules/tty-table": { "version": "4.1.6", "dev": true, @@ -11777,13 +12058,13 @@ } }, "node_modules/tuf-js": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.6.tgz", - "integrity": "sha512-CXwFVIsXGbVY4vFiWF7TJKWmlKJAT8TWkH4RmiohJRcDJInix++F0dznDmoVbtJNzZ8yLprKUG4YrDIhv3nBMg==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz", + "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==", "dependencies": { "@tufjs/models": "1.0.4", "debug": "^4.3.4", - "make-fetch-happen": "^11.1.0" + "make-fetch-happen": "^11.1.1" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -11851,9 +12132,9 @@ } }, "node_modules/typescript": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", - "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", + "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -12125,6 +12406,18 @@ "defaults": "^1.0.3" } }, + "node_modules/webcrypto-core": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.7.tgz", + "integrity": "sha512-7FjigXNsBfopEj+5DV2nhNpfic2vumtjjgPmeDKk45z+MJwXKKfhPB7118Pfzrmh4jqOMST6Ch37iPAHoImg5g==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/json-schema": "^1.1.12", + "asn1js": "^3.0.1", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -12664,7 +12957,7 @@ }, "packages/cli": { "name": "@sigstore/cli", - "version": "0.0.5", + "version": "0.1.0", "license": "Apache-2.0", "dependencies": { "@oclif/color": "^1.0.6", @@ -12672,7 +12965,7 @@ "@oclif/plugin-help": "^5", "open": "^8.4.2", "openid-client": "^5.4.2", - "sigstore": "^1.5.2" + "sigstore": "^1.6.0" }, "bin": { "sigstore": "bin/run" @@ -12680,9 +12973,7 @@ "devDependencies": { "make-fetch-happen": "^11.1.1", "oclif": "^3", - "shx": "^0.3.3", - "tslib": "^2.5.3", - "typescript": "^5.1.3" + "tslib": "^2.6.0" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -12690,28 +12981,32 @@ }, "packages/client": { "name": "sigstore", - "version": "1.5.2", + "version": "1.6.0", "license": "Apache-2.0", "dependencies": { "@sigstore/protobuf-specs": "^0.1.0", - "@sigstore/tuf": "^0.0.0", - "make-fetch-happen": "^11.0.1", - "tuf-js": "^1.1.3" + "@sigstore/tuf": "^1.0.0", + "make-fetch-happen": "^11.0.1" }, "bin": { "sigstore": "bin/sigstore.js" }, "devDependencies": { - "@sigstore/rekor-types": "^0.0.3", - "@total-typescript/shoehorn": "^0.1.0", + "@sigstore/jest": "^0.0.0", + "@sigstore/rekor-types": "^1.0.0", "@tufjs/repo-mock": "^1.1.0", - "@types/make-fetch-happen": "^10.0.0", - "@types/node": "^20.2.5", - "@types/sigstore-jest-extended": "^0.0.0", - "json-schema-to-typescript": "^13.0.0", - "nock": "^13.2.4", - "shx": "^0.3.3", - "typescript": "^5.1.3" + "@types/make-fetch-happen": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "packages/jest": { + "name": "@sigstore/jest", + "version": "0.0.0", + "license": "Apache-2.0", + "dependencies": { + "@types/sigstore-jest-extended": "^0.0.0" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -12722,6 +13017,40 @@ "version": "0.0.0", "license": "Apache-2.0" }, + "packages/mock": { + "name": "@sigstore/mock", + "version": "0.0.0", + "license": "Apache-2.0", + "dependencies": { + "@peculiar/webcrypto": "^1.4.3", + "@peculiar/x509": "^1.9.3", + "@sigstore/protobuf-specs": "^0.1.0", + "@tufjs/repo-mock": "^1.1.0", + "asn1js": "^3.0.5", + "bytestreamjs": "^2.0.1", + "canonicalize": "^2.0.0", + "jose": "^4.14.4", + "nock": "^13.3.1", + "pkijs": "^3.0.15", + "pvtsutils": "^1.3.2" + }, + "devDependencies": { + "@sigstore/rekor-types": "^0.0.3", + "make-fetch-happen": "^11.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "packages/mock/node_modules/@sigstore/rekor-types": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@sigstore/rekor-types/-/rekor-types-0.0.3.tgz", + "integrity": "sha512-yCPe8wpQOfDNXDxhMGEhcvezJGHyEwZNeBVNa3W7xZ1Jweo/m4oAef6UK8gYowAQEafLZ0LaWUxrsVUp+ljrPg==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "packages/oauth": { "name": "@sigstore/oauth", "version": "0.0.3", @@ -12743,13 +13072,11 @@ }, "packages/rekor-types": { "name": "@sigstore/rekor-types", - "version": "0.0.3", + "version": "1.0.0", "license": "Apache-2.0", "devDependencies": { - "json-schema-to-typescript": "^13.0.0", - "openapi-typescript-codegen": "^0.24.0", - "shx": "^0.3.3", - "typescript": "^5.1.3" + "json-schema-to-typescript": "^13.0.2", + "openapi-typescript-codegen": "^0.24.0" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -12757,20 +13084,16 @@ }, "packages/tuf": { "name": "@sigstore/tuf", - "version": "0.0.0", + "version": "1.0.0", "license": "Apache-2.0", "dependencies": { "@sigstore/protobuf-specs": "^0.1.0", - "make-fetch-happen": "^11.0.1", - "tuf-js": "^1.1.3" + "@types/make-fetch-happen": "^10.0.0", + "tuf-js": "^1.1.7" }, "devDependencies": { - "@total-typescript/shoehorn": "^0.1.0", - "@tufjs/repo-mock": "^1.1.0", - "@types/node": "^20.2.5", - "nock": "^13.2.4", - "shx": "^0.3.3", - "typescript": "^5.1.3" + "@sigstore/jest": "^0.0.0", + "@tufjs/repo-mock": "^1.1.0" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -13186,11 +13509,13 @@ "dev": true }, "@changesets/apply-release-plan": { - "version": "6.1.3", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-6.1.4.tgz", + "integrity": "sha512-FMpKF1fRlJyCZVYHr3CbinpZZ+6MwvOtWUuO8uo+svcATEoc1zRDcj23pAurJ2TZ/uVz1wFHH6K3NlACy0PLew==", "dev": true, "requires": { "@babel/runtime": "^7.20.1", - "@changesets/config": "^2.3.0", + "@changesets/config": "^2.3.1", "@changesets/get-version-range-type": "^0.3.2", "@changesets/git": "^2.0.0", "@changesets/types": "^5.2.1", @@ -13201,35 +13526,29 @@ "outdent": "^0.5.0", "prettier": "^2.7.1", "resolve-from": "^5.0.0", - "semver": "^5.4.1" + "semver": "^7.5.3" }, "dependencies": { "resolve-from": { "version": "5.0.0", - "dev": true - }, - "semver": { - "version": "5.7.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true } } }, "@changesets/assemble-release-plan": { - "version": "5.2.3", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-5.2.4.tgz", + "integrity": "sha512-xJkWX+1/CUaOUWTguXEbCDTyWJFECEhmdtbkjhn5GVBGxdP/JwaHBIU9sW3FR6gD07UwZ7ovpiPclQZs+j+mvg==", "dev": true, "requires": { "@babel/runtime": "^7.20.1", "@changesets/errors": "^0.1.4", - "@changesets/get-dependents-graph": "^1.3.5", + "@changesets/get-dependents-graph": "^1.3.6", "@changesets/types": "^5.2.1", "@manypkg/get-packages": "^1.1.3", - "semver": "^5.4.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "dev": true - } + "semver": "^7.5.3" } }, "@changesets/changelog-git": { @@ -13240,17 +13559,19 @@ } }, "@changesets/cli": { - "version": "2.26.1", + "version": "2.26.2", + "resolved": "https://registry.npmjs.org/@changesets/cli/-/cli-2.26.2.tgz", + "integrity": "sha512-dnWrJTmRR8bCHikJHl9b9HW3gXACCehz4OasrXpMp7sx97ECuBGGNjJhjPhdZNCvMy9mn4BWdplI323IbqsRig==", "dev": true, "requires": { "@babel/runtime": "^7.20.1", - "@changesets/apply-release-plan": "^6.1.3", - "@changesets/assemble-release-plan": "^5.2.3", + "@changesets/apply-release-plan": "^6.1.4", + "@changesets/assemble-release-plan": "^5.2.4", "@changesets/changelog-git": "^0.1.14", - "@changesets/config": "^2.3.0", + "@changesets/config": "^2.3.1", "@changesets/errors": "^0.1.4", - "@changesets/get-dependents-graph": "^1.3.5", - "@changesets/get-release-plan": "^3.0.16", + "@changesets/get-dependents-graph": "^1.3.6", + "@changesets/get-release-plan": "^3.0.17", "@changesets/git": "^2.0.0", "@changesets/logger": "^0.0.5", "@changesets/pre": "^1.0.14", @@ -13259,7 +13580,7 @@ "@changesets/write": "^0.2.3", "@manypkg/get-packages": "^1.1.3", "@types/is-ci": "^3.0.0", - "@types/semver": "^6.0.0", + "@types/semver": "^7.5.0", "ansi-colors": "^4.1.3", "chalk": "^2.1.0", "enquirer": "^2.3.0", @@ -13272,16 +13593,12 @@ "p-limit": "^2.2.0", "preferred-pm": "^3.0.0", "resolve-from": "^5.0.0", - "semver": "^5.4.1", + "semver": "^7.5.3", "spawndamnit": "^2.0.0", "term-size": "^2.1.0", "tty-table": "^4.1.5" }, "dependencies": { - "@types/semver": { - "version": "6.2.3", - "dev": true - }, "ansi-styles": { "version": "3.2.1", "dev": true, @@ -13328,10 +13645,6 @@ "version": "5.0.0", "dev": true }, - "semver": { - "version": "5.7.1", - "dev": true - }, "supports-color": { "version": "5.5.0", "dev": true, @@ -13342,11 +13655,13 @@ } }, "@changesets/config": { - "version": "2.3.0", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@changesets/config/-/config-2.3.1.tgz", + "integrity": "sha512-PQXaJl82CfIXddUOppj4zWu+987GCw2M+eQcOepxN5s+kvnsZOwjEJO3DH9eVy+OP6Pg/KFEWdsECFEYTtbg6w==", "dev": true, "requires": { "@changesets/errors": "^0.1.4", - "@changesets/get-dependents-graph": "^1.3.5", + "@changesets/get-dependents-graph": "^1.3.6", "@changesets/logger": "^0.0.5", "@changesets/types": "^5.2.1", "@manypkg/get-packages": "^1.1.3", @@ -13356,24 +13671,30 @@ }, "@changesets/errors": { "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@changesets/errors/-/errors-0.1.4.tgz", + "integrity": "sha512-HAcqPF7snsUJ/QzkWoKfRfXushHTu+K5KZLJWPb34s4eCZShIf8BFO3fwq6KU8+G7L5KdtN2BzQAXOSXEyiY9Q==", "dev": true, "requires": { "extendable-error": "^0.1.5" } }, "@changesets/get-dependents-graph": { - "version": "1.3.5", + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@changesets/get-dependents-graph/-/get-dependents-graph-1.3.6.tgz", + "integrity": "sha512-Q/sLgBANmkvUm09GgRsAvEtY3p1/5OCzgBE5vX3vgb5CvW0j7CEljocx5oPXeQSNph6FXulJlXV3Re/v3K3P3Q==", "dev": true, "requires": { "@changesets/types": "^5.2.1", "@manypkg/get-packages": "^1.1.3", "chalk": "^2.1.0", "fs-extra": "^7.0.1", - "semver": "^5.4.1" + "semver": "^7.5.3" }, "dependencies": { "ansi-styles": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { "color-convert": "^1.9.0" @@ -13381,6 +13702,8 @@ }, "chalk": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -13390,6 +13713,8 @@ }, "color-convert": { "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { "color-name": "1.1.3" @@ -13397,22 +13722,26 @@ }, "color-name": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "escape-string-regexp": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true }, "has-flag": { "version": "3.0.0", - "dev": true - }, - "semver": { - "version": "5.7.1", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true }, "supports-color": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -13421,12 +13750,14 @@ } }, "@changesets/get-release-plan": { - "version": "3.0.16", + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-3.0.17.tgz", + "integrity": "sha512-6IwKTubNEgoOZwDontYc2x2cWXfr6IKxP3IhKeK+WjyD6y3M4Gl/jdQvBw+m/5zWILSOCAaGLu2ZF6Q+WiPniw==", "dev": true, "requires": { "@babel/runtime": "^7.20.1", - "@changesets/assemble-release-plan": "^5.2.3", - "@changesets/config": "^2.3.0", + "@changesets/assemble-release-plan": "^5.2.4", + "@changesets/config": "^2.3.1", "@changesets/pre": "^1.0.14", "@changesets/read": "^0.5.9", "@changesets/types": "^5.2.1", @@ -13435,10 +13766,14 @@ }, "@changesets/get-version-range-type": { "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@changesets/get-version-range-type/-/get-version-range-type-0.3.2.tgz", + "integrity": "sha512-SVqwYs5pULYjYT4op21F2pVbcrca4qA/bAA3FmFXKMN7Y+HcO8sbZUTx3TAy2VXulP2FACd1aC7f2nTuqSPbqg==", "dev": true }, "@changesets/git": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@changesets/git/-/git-2.0.0.tgz", + "integrity": "sha512-enUVEWbiqUTxqSnmesyJGWfzd51PY4H7mH9yUw0hPVpZBJ6tQZFMU3F3mT/t9OJ/GjyiM4770i+sehAn6ymx6A==", "dev": true, "requires": { "@babel/runtime": "^7.20.1", @@ -13452,6 +13787,8 @@ }, "@changesets/logger": { "version": "0.0.5", + "resolved": "https://registry.npmjs.org/@changesets/logger/-/logger-0.0.5.tgz", + "integrity": "sha512-gJyZHomu8nASHpaANzc6bkQMO9gU/ib20lqew1rVx753FOxffnCrJlGIeQVxNWCqM+o6OOleCo/ivL8UAO5iFw==", "dev": true, "requires": { "chalk": "^2.1.0" @@ -13459,6 +13796,8 @@ "dependencies": { "ansi-styles": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { "color-convert": "^1.9.0" @@ -13466,6 +13805,8 @@ }, "chalk": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -13475,6 +13816,8 @@ }, "color-convert": { "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { "color-name": "1.1.3" @@ -13482,18 +13825,26 @@ }, "color-name": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "escape-string-regexp": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true }, "has-flag": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true }, "supports-color": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -13503,6 +13854,8 @@ }, "@changesets/parse": { "version": "0.3.16", + "resolved": "https://registry.npmjs.org/@changesets/parse/-/parse-0.3.16.tgz", + "integrity": "sha512-127JKNd167ayAuBjUggZBkmDS5fIKsthnr9jr6bdnuUljroiERW7FBTDNnNVyJ4l69PzR57pk6mXQdtJyBCJKg==", "dev": true, "requires": { "@changesets/types": "^5.2.1", @@ -13511,6 +13864,8 @@ "dependencies": { "argparse": { "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { "sprintf-js": "~1.0.2" @@ -13518,6 +13873,8 @@ }, "js-yaml": { "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -13528,6 +13885,8 @@ }, "@changesets/pre": { "version": "1.0.14", + "resolved": "https://registry.npmjs.org/@changesets/pre/-/pre-1.0.14.tgz", + "integrity": "sha512-dTsHmxQWEQekHYHbg+M1mDVYFvegDh9j/kySNuDKdylwfMEevTeDouR7IfHNyVodxZXu17sXoJuf2D0vi55FHQ==", "dev": true, "requires": { "@babel/runtime": "^7.20.1", @@ -13539,6 +13898,8 @@ }, "@changesets/read": { "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@changesets/read/-/read-0.5.9.tgz", + "integrity": "sha512-T8BJ6JS6j1gfO1HFq50kU3qawYxa4NTbI/ASNVVCBTsKquy2HYwM9r7ZnzkiMe8IEObAJtUVGSrePCOxAK2haQ==", "dev": true, "requires": { "@babel/runtime": "^7.20.1", @@ -13553,6 +13914,8 @@ "dependencies": { "ansi-styles": { "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { "color-convert": "^1.9.0" @@ -13560,6 +13923,8 @@ }, "chalk": { "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -13569,6 +13934,8 @@ }, "color-convert": { "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { "color-name": "1.1.3" @@ -13576,18 +13943,26 @@ }, "color-name": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "escape-string-regexp": { "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true }, "has-flag": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true }, "supports-color": { "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -13656,9 +14031,9 @@ } }, "@eslint/js": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.42.0.tgz", - "integrity": "sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==", + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.43.0.tgz", + "integrity": "sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==", "dev": true }, "@gar/promisify": { @@ -14043,6 +14418,8 @@ }, "@manypkg/find-root": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@manypkg/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==", "dev": true, "requires": { "@babel/runtime": "^7.5.5", @@ -14053,10 +14430,14 @@ "dependencies": { "@types/node": { "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", "dev": true }, "find-up": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { "locate-path": "^5.0.0", @@ -14065,6 +14446,8 @@ }, "fs-extra": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "requires": { "graceful-fs": "^4.2.0", @@ -14074,6 +14457,8 @@ }, "locate-path": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { "p-locate": "^4.1.0" @@ -14081,6 +14466,8 @@ }, "p-limit": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -14088,6 +14475,8 @@ }, "p-locate": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "requires": { "p-limit": "^2.2.0" @@ -14097,6 +14486,8 @@ }, "@manypkg/get-packages": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@manypkg/get-packages/-/get-packages-1.1.3.tgz", + "integrity": "sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==", "dev": true, "requires": { "@babel/runtime": "^7.5.5", @@ -14109,10 +14500,14 @@ "dependencies": { "@changesets/types": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@changesets/types/-/types-4.1.0.tgz", + "integrity": "sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==", "dev": true }, "fs-extra": { "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "requires": { "graceful-fs": "^4.2.0", @@ -14540,9 +14935,9 @@ } }, "@oclif/core": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/@oclif/core/-/core-2.8.5.tgz", - "integrity": "sha512-316DLfrHQDYmWDriI4Woxk9y1wVUrPN1sZdbQLHdOdlTA9v/twe7TdHpWOriEypfl6C85NWEJKc1870yuLtjrQ==", + "version": "2.8.10", + "resolved": "https://registry.npmjs.org/@oclif/core/-/core-2.8.10.tgz", + "integrity": "sha512-coRn9vYDEnoE8Vg20aavts9+Bt5QrHhbdh0cDkImopV0MgT8i/VmgL04D33+qoHQH20XzBOMqrjk+bqQzqyaHg==", "requires": { "@types/cli-progress": "^3.11.0", "ansi-escapes": "^4.3.2", @@ -14636,11 +15031,11 @@ } }, "@oclif/plugin-help": { - "version": "5.2.9", - "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-5.2.9.tgz", - "integrity": "sha512-0J3oowPURZJ4Dn1p1WpQ46E4+CoV20KTn1cvsNiDl6Hmbw+qoljKQnArJJzNFeZQxWo4R7/S42PrzKJTVYh68Q==", + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-5.2.10.tgz", + "integrity": "sha512-l3hnloPkXOLGGrepLLdj8NsBpVhhEpg4jclIeIBaZzIo6+c+/uqcL2LjvOogmSEf5g4zooRtxivwUpcFiBSaBg==", "requires": { - "@oclif/core": "^2.8.0" + "@oclif/core": "^2.8.7" } }, "@oclif/plugin-not-found": { @@ -14835,6 +15230,168 @@ "@octokit/openapi-types": "^12.11.0" } }, + "@peculiar/asn1-cms": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.3.6.tgz", + "integrity": "sha512-Kr0XsyjuElTc4NijuPYyd6YkTlbz0KCuoWnNkfPFhXjHTzbUIh/s15ixjxLj8XDrXsI1aPQp3D64uHbrs3Kuyg==", + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "@peculiar/asn1-x509-attr": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-csr": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.3.6.tgz", + "integrity": "sha512-gCTEB/PvUxapmxo4SzGZT1JtEdevRnphRGZZmc9oJE7+pLuj2Px0Q6x+w8VvObfozA3pyPRTq+Wkocnu64+oLw==", + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-ecc": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.3.6.tgz", + "integrity": "sha512-Hu1xzMJQWv8/GvzOiinaE6XiD1/kEhq2C/V89UEoWeZ2fLUcGNIvMxOr/pMyL0OmpRWj/mhCTXOZp4PP+a0aTg==", + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-pfx": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.3.6.tgz", + "integrity": "sha512-bScrrpQ59mppcoZLkDEW/Wruu+daSWQxpR2vqGjg69+v7VoQ1Le/Elm10ObfNShV2eNNridNQcOQvsHMLvUOCg==", + "requires": { + "@peculiar/asn1-cms": "^2.3.6", + "@peculiar/asn1-pkcs8": "^2.3.6", + "@peculiar/asn1-rsa": "^2.3.6", + "@peculiar/asn1-schema": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-pkcs8": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.3.6.tgz", + "integrity": "sha512-poqgdjsHNiyR0gnxP8l5VjRInSgpQvOM3zLULF/ZQW67uUsEiuPfplvaNJUlNqNOCd2szGo9jKW9+JmVVpWojA==", + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-pkcs9": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.3.6.tgz", + "integrity": "sha512-uaxSBF60glccuu5BEZvoPsaJzebVYcQRjXx2wXsGe7Grz/BXtq5RQAJ/3i9fEXawFK/zIbvbXBBpy07cnvrqhA==", + "requires": { + "@peculiar/asn1-cms": "^2.3.6", + "@peculiar/asn1-pfx": "^2.3.6", + "@peculiar/asn1-pkcs8": "^2.3.6", + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "@peculiar/asn1-x509-attr": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-rsa": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.3.6.tgz", + "integrity": "sha512-DswjJyAXZnvESuImGNTvbNKvh1XApBVqU+r3UmrFFTAI23gv62byl0f5OFKWTNhCf66WQrd3sklpsCZc/4+jwA==", + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-schema": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.6.tgz", + "integrity": "sha512-izNRxPoaeJeg/AyH8hER6s+H7p4itk+03QCa4sbxI3lNdseQYCuxzgsuNK8bTXChtLTjpJz6NmXKA73qLa3rCA==", + "requires": { + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-x509": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.3.6.tgz", + "integrity": "sha512-dRwX31R1lcbIdzbztiMvLNTDoGptxdV7HocNx87LfKU0fEWh7fTWJjx4oV+glETSy6heF/hJHB2J4RGB3vVSYg==", + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "asn1js": "^3.0.5", + "ipaddr.js": "^2.0.1", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + }, + "dependencies": { + "ipaddr.js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", + "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==" + } + } + }, + "@peculiar/asn1-x509-attr": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.3.6.tgz", + "integrity": "sha512-x5Kax8xp3fz+JSc+4Sq0/SUXIdbJeOePibYqvjHMGkP6AoeCOVcP+gg7rZRRGkTlDSyQnAoUTgTEsfAfFEd1/g==", + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@peculiar/webcrypto": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.3.tgz", + "integrity": "sha512-VtaY4spKTdN5LjJ04im/d/joXuvLbQdgy5Z4DXF4MFZhQ+MTrejbNMkfZBp1Bs3O5+bFqnJgyGdPuZQflvIa5A==", + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.2", + "tslib": "^2.5.0", + "webcrypto-core": "^1.7.7" + } + }, + "@peculiar/x509": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.9.3.tgz", + "integrity": "sha512-rv1TrPi85jOtBJ7Xmqx08p3QPIE2avd5CWgtiwOIAbhV3hoUCLlGIUtXn9CuShfFBCjGy8EnZRQ6YbNFaDL8vw==", + "requires": { + "@peculiar/asn1-cms": "^2.3.4", + "@peculiar/asn1-csr": "^2.3.4", + "@peculiar/asn1-ecc": "^2.3.4", + "@peculiar/asn1-pkcs9": "^2.3.4", + "@peculiar/asn1-rsa": "^2.3.4", + "@peculiar/asn1-schema": "^2.3.3", + "@peculiar/asn1-x509": "^2.3.4", + "pvtsutils": "^1.3.2", + "reflect-metadata": "^0.1.13", + "tslib": "^2.4.1", + "tsyringe": "^4.7.0" + } + }, "@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -14851,10 +15408,40 @@ "oclif": "^3", "open": "^8.4.2", "openid-client": "^5.4.2", - "shx": "^0.3.3", - "sigstore": "^1.5.2", - "tslib": "^2.5.3", - "typescript": "^5.1.3" + "sigstore": "^1.6.0", + "tslib": "^2.6.0" + } + }, + "@sigstore/jest": { + "version": "file:packages/jest", + "requires": { + "@types/sigstore-jest-extended": "^0.0.0" + } + }, + "@sigstore/mock": { + "version": "file:packages/mock", + "requires": { + "@peculiar/webcrypto": "^1.4.3", + "@peculiar/x509": "^1.9.3", + "@sigstore/protobuf-specs": "^0.1.0", + "@sigstore/rekor-types": "^0.0.3", + "@tufjs/repo-mock": "^1.1.0", + "asn1js": "^3.0.5", + "bytestreamjs": "^2.0.1", + "canonicalize": "^2.0.0", + "jose": "^4.14.4", + "make-fetch-happen": "^11.0.1", + "nock": "^13.3.1", + "pkijs": "^3.0.15", + "pvtsutils": "^1.3.2" + }, + "dependencies": { + "@sigstore/rekor-types": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@sigstore/rekor-types/-/rekor-types-0.0.3.tgz", + "integrity": "sha512-yCPe8wpQOfDNXDxhMGEhcvezJGHyEwZNeBVNa3W7xZ1Jweo/m4oAef6UK8gYowAQEafLZ0LaWUxrsVUp+ljrPg==", + "dev": true + } } }, "@sigstore/protobuf-specs": { @@ -14865,24 +15452,18 @@ "@sigstore/rekor-types": { "version": "file:packages/rekor-types", "requires": { - "json-schema-to-typescript": "^13.0.0", - "openapi-typescript-codegen": "^0.24.0", - "shx": "^0.3.3", - "typescript": "^5.1.3" + "json-schema-to-typescript": "^13.0.2", + "openapi-typescript-codegen": "^0.24.0" } }, "@sigstore/tuf": { "version": "file:packages/tuf", "requires": { + "@sigstore/jest": "^0.0.0", "@sigstore/protobuf-specs": "^0.1.0", - "@total-typescript/shoehorn": "^0.1.0", "@tufjs/repo-mock": "^1.1.0", - "@types/node": "^20.2.5", - "make-fetch-happen": "^11.0.1", - "nock": "^13.2.4", - "shx": "^0.3.3", - "tuf-js": "^1.1.3", - "typescript": "^5.1.3" + "@types/make-fetch-happen": "^10.0.0", + "tuf-js": "^1.1.7" } }, "@sinclair/typebox": { @@ -14924,9 +15505,9 @@ "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" }, "@total-typescript/shoehorn": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@total-typescript/shoehorn/-/shoehorn-0.1.0.tgz", - "integrity": "sha512-XKig6hXxWnUh0fsW3LR2vxpxwLlPFokfOSR0riHKA9uXvdHDfwOOPdAOi4U/YNKLmgYUu/plUfnF3yiAAz1+Zg==", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@total-typescript/shoehorn/-/shoehorn-0.1.1.tgz", + "integrity": "sha512-XSPcazQsC2Cr7eCiAI+M2bTmMziBvFWYTYMgUDKLbU6i+7m3I2BF5gXF5vKDO8577fONs9CvmTvVa7+nMHMfxg==", "dev": true }, "@tsconfig/node10": { @@ -14940,7 +15521,10 @@ "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" }, "@tsconfig/node14": { - "version": "1.0.3" + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-14.1.0.tgz", + "integrity": "sha512-VmsCG04YR58ciHBeJKBDNMWWfYbyP8FekWVuTlpstaUPlat1D0x/tXzkWP7yCMU0eSz9V4OZU0LBWTFJ3xZf6w==", + "dev": true }, "@tsconfig/node16": { "version": "1.0.4", @@ -14983,7 +15567,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/@tufjs/repo-mock/-/repo-mock-1.3.1.tgz", "integrity": "sha512-7IDezQbPGReWD3xmgR2pAfG61BZpvW51XnB87OfuiJOe5mkGnziCTTGITtUC3A6htQr9shkk5qIKrhpoMXBwpQ==", - "dev": true, "requires": { "@tufjs/models": "1.0.4", "nock": "^13.3.1" @@ -15129,7 +15712,6 @@ "version": "10.0.1", "resolved": "https://registry.npmjs.org/@types/make-fetch-happen/-/make-fetch-happen-10.0.1.tgz", "integrity": "sha512-DFKsprsL3krCqtCD+WAnWDrCJBinI0GwcgXqeIFC1ZhWZbmoTAv6Rgl+P8On/rfQIuYp2OmZymjvm9ZukWh8ZA==", - "dev": true, "requires": { "@types/node-fetch": "*", "@types/retry": "*", @@ -15147,15 +15729,14 @@ "dev": true }, "@types/node": { - "version": "20.2.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.2.5.tgz", - "integrity": "sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==" + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.2.tgz", + "integrity": "sha512-vOBLVQeCQfIcF/2Y7eKFTqrMnizK5lRNQ7ykML/5RuwVXVWxYkgwS7xbt4B6fKCUPgbSL5FSsjHQpaGQP/dQmw==" }, "@types/node-fetch": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.3.tgz", "integrity": "sha512-ETTL1mOEdq/sxUtgtOhKjyB2Irra4cjxksvcMUR5Zr4n+PxVhsCD9WS46oPbHL3et9Zde7CNRr+WUNlcHvsX+w==", - "dev": true, "requires": { "@types/node": "*", "form-data": "^3.0.0" @@ -15181,8 +15762,7 @@ "@types/retry": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", - "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", - "dev": true + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==" }, "@types/semver": { "version": "7.5.0", @@ -15197,7 +15777,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/@types/ssri/-/ssri-7.1.1.tgz", "integrity": "sha512-DPP/jkDaqGiyU75MyMURxLWyYLwKSjnAuGe9ZCsLp9QZOpXmDfuevk769F0BS86TmRuD5krnp06qw9nSoNO+0g==", - "dev": true, "requires": { "@types/node": "*" } @@ -15228,15 +15807,15 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.9.tgz", - "integrity": "sha512-4uQIBq1ffXd2YvF7MAvehWKW3zVv/w+mSfRAu+8cKbfj3nwzyqJLNcZJpQ/WZ1HLbJDiowwmQ6NO+63nCA+fqA==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.1.tgz", + "integrity": "sha512-KSWsVvsJsLJv3c4e73y/Bzt7OpqMCADUO846bHcuWYSYM19bldbAeDv7dYyV0jwkbMfJ2XdlzwjhXtuD7OY6bw==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/type-utils": "5.59.9", - "@typescript-eslint/utils": "5.59.9", + "@typescript-eslint/scope-manager": "5.60.1", + "@typescript-eslint/type-utils": "5.60.1", + "@typescript-eslint/utils": "5.60.1", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -15246,53 +15825,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.9.tgz", - "integrity": "sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.60.1.tgz", + "integrity": "sha512-pHWlc3alg2oSMGwsU/Is8hbm3XFbcrb6P5wIxcQW9NsYBfnrubl/GhVVD/Jm/t8HXhA2WncoIRfBtnCgRGV96Q==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/typescript-estree": "5.59.9", + "@typescript-eslint/scope-manager": "5.60.1", + "@typescript-eslint/types": "5.60.1", + "@typescript-eslint/typescript-estree": "5.60.1", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.9.tgz", - "integrity": "sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.60.1.tgz", + "integrity": "sha512-Dn/LnN7fEoRD+KspEOV0xDMynEmR3iSHdgNsarlXNLGGtcUok8L4N71dxUgt3YvlO8si7E+BJ5Fe3wb5yUw7DQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/visitor-keys": "5.59.9" + "@typescript-eslint/types": "5.60.1", + "@typescript-eslint/visitor-keys": "5.60.1" } }, "@typescript-eslint/type-utils": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.9.tgz", - "integrity": "sha512-ksEsT0/mEHg9e3qZu98AlSrONAQtrSTljL3ow9CGej8eRo7pe+yaC/mvTjptp23Xo/xIf2mLZKC6KPv4Sji26Q==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.60.1.tgz", + "integrity": "sha512-vN6UztYqIu05nu7JqwQGzQKUJctzs3/Hg7E2Yx8rz9J+4LgtIDFWjjl1gm3pycH0P3mHAcEUBd23LVgfrsTR8A==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.59.9", - "@typescript-eslint/utils": "5.59.9", + "@typescript-eslint/typescript-estree": "5.60.1", + "@typescript-eslint/utils": "5.60.1", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.9.tgz", - "integrity": "sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.60.1.tgz", + "integrity": "sha512-zDcDx5fccU8BA0IDZc71bAtYIcG9PowaOwaD8rjYbqwK7dpe/UMQl3inJ4UtUK42nOCT41jTSCwg76E62JpMcg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz", - "integrity": "sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.1.tgz", + "integrity": "sha512-hkX70J9+2M2ZT6fhti5Q2FoU9zb+GeZK2SLP1WZlvUDqdMbEKhexZODD1WodNRyO8eS+4nScvT0dts8IdaBzfw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/visitor-keys": "5.59.9", + "@typescript-eslint/types": "5.60.1", + "@typescript-eslint/visitor-keys": "5.60.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -15301,28 +15880,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.9.tgz", - "integrity": "sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.60.1.tgz", + "integrity": "sha512-tiJ7FFdFQOWssFa3gqb94Ilexyw0JVxj6vBzaSpfN/8IhoKkDuSAenUKvsSHw2A/TMpJb26izIszTXaqygkvpQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.9", - "@typescript-eslint/types": "5.59.9", - "@typescript-eslint/typescript-estree": "5.59.9", + "@typescript-eslint/scope-manager": "5.60.1", + "@typescript-eslint/types": "5.60.1", + "@typescript-eslint/typescript-estree": "5.60.1", "eslint-scope": "^5.1.1", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.59.9", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.9.tgz", - "integrity": "sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q==", + "version": "5.60.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.1.tgz", + "integrity": "sha512-xEYIxKcultP6E/RMKqube11pGjXH1DCo60mQoWhVYyKfLkwbIVVjYxmOenNMxILx0TjCujPTjjnTIVzm09TXIw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.9", + "@typescript-eslint/types": "5.60.1", "eslint-visitor-keys": "^3.3.0" } }, @@ -15479,6 +16058,16 @@ "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", "dev": true }, + "asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "requires": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + } + }, "async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", @@ -15487,8 +16076,7 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "at-least-node": { "version": "1.0.0", @@ -15594,6 +16182,8 @@ }, "better-path-resolve": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/better-path-resolve/-/better-path-resolve-1.0.0.tgz", + "integrity": "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==", "dev": true, "requires": { "is-windows": "^1.0.0" @@ -15715,6 +16305,11 @@ "integrity": "sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==", "dev": true }, + "bytestreamjs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bytestreamjs/-/bytestreamjs-2.0.1.tgz", + "integrity": "sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ==" + }, "cacache": { "version": "17.1.0", "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.0.tgz", @@ -15831,6 +16426,11 @@ "version": "1.0.30001450", "dev": true }, + "canonicalize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-2.0.0.tgz", + "integrity": "sha512-ulDEYPv7asdKvqahuAY35c1selLdzDwHqugK92hfkzvlDCwXRRelDkR+Er33md/PtnpqHemgkuDPanZ4fiYZ8w==" + }, "cardinal": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", @@ -16055,7 +16655,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "requires": { "delayed-stream": "~1.0.0" } @@ -16291,8 +16890,7 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, "delegates": { "version": "1.0.0", @@ -16313,6 +16911,8 @@ }, "detect-indent": { "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", "dev": true }, "detect-newline": { @@ -16540,15 +17140,15 @@ "version": "4.0.0" }, "eslint": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.42.0.tgz", - "integrity": "sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==", + "version": "8.43.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.43.0.tgz", + "integrity": "sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.42.0", + "@eslint/js": "8.43.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -16745,6 +17345,8 @@ }, "extendable-error": { "version": "0.1.7", + "resolved": "https://registry.npmjs.org/extendable-error/-/extendable-error-0.1.7.tgz", + "integrity": "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==", "dev": true }, "external-editor": { @@ -16979,7 +17581,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -17662,6 +18263,8 @@ }, "is-subdir": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-subdir/-/is-subdir-1.2.0.tgz", + "integrity": "sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==", "dev": true, "requires": { "better-path-resolve": "1.0.0" @@ -17706,6 +18309,8 @@ }, "is-windows": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, "is-wsl": { @@ -18223,9 +18828,9 @@ } }, "json-schema-to-typescript": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-13.0.1.tgz", - "integrity": "sha512-VU+Spn84eLJyt8R0Bmg2soTwHQFgvrGrU7V8mXbhqWFdEYCFekSYk4JcpCzx0i/WzjEVJKAU7r0y0PVYT14E6Q==", + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-13.0.2.tgz", + "integrity": "sha512-TCaEVW4aI2FmMQe7f98mvr3/oiVmXEC1xZjkTZ9L/BSoTXFlC7p64mD5AD2d8XWycNBQZUnHwXL5iVXt1HWwNQ==", "dev": true, "requires": { "@bcherny/json-schema-ref-parser": "10.0.5-fork", @@ -18259,8 +18864,7 @@ "dev": true }, "json-stringify-safe": { - "version": "5.0.1", - "dev": true + "version": "5.0.1" }, "json5": { "version": "2.2.3", @@ -18363,8 +18967,7 @@ } }, "lodash": { - "version": "4.17.21", - "dev": true + "version": "4.17.21" }, "lodash.memoize": { "version": "4.1.2", @@ -18376,6 +18979,8 @@ }, "lodash.startcase": { "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", "dev": true }, "log-symbols": { @@ -18585,14 +19190,12 @@ "mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "requires": { "mime-db": "1.52.0" } @@ -18866,7 +19469,6 @@ "version": "13.3.1", "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.1.tgz", "integrity": "sha512-vHnopocZuI93p2ccivFyGuUfzjq2fxNyNurp7816mlT5V5HF4SzXu8lvLrVzBbNqzs+ODooZ6OksuSUNM7Njkw==", - "dev": true, "requires": { "debug": "^4.1.0", "json-stringify-safe": "^5.0.1", @@ -19465,9 +20067,9 @@ } }, "oclif": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/oclif/-/oclif-3.9.0.tgz", - "integrity": "sha512-fsFyHVQYJdE50EcKrBjwzl2WT5sZUtTiRY1vqMwykgLFUDYrQS0lj7yqy2IgcPSmAWaLQryODdfBujCWOU98Ww==", + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/oclif/-/oclif-3.9.1.tgz", + "integrity": "sha512-gJ8gJrohFY8qEeVBOw7wgAFdwPt2CTTkEFXDTkfUeXap6URIy6ngP7g/E1A2zFt2I0wH/qQHwcfuTpfBbj1+Uw==", "dev": true, "requires": { "@oclif/core": "^2.8.4", @@ -19673,6 +20275,8 @@ }, "outdent": { "version": "0.5.0", + "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.5.0.tgz", + "integrity": "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==", "dev": true }, "p-cancelable": { @@ -19683,6 +20287,8 @@ }, "p-filter": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz", + "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==", "dev": true, "requires": { "p-map": "^2.0.0" @@ -19690,6 +20296,8 @@ "dependencies": { "p-map": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", "dev": true } } @@ -20054,6 +20662,18 @@ } } }, + "pkijs": { + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/pkijs/-/pkijs-3.0.15.tgz", + "integrity": "sha512-n7nAl9JpqdeQsjy+rPmswkmZ3oO/Fu5uN9me45PPQVdWjd0X7HKfL8+HYwfxihqoDSSPUIajkOcqFxEUxMqhwQ==", + "requires": { + "asn1js": "^3.0.5", + "bytestreamjs": "^2.0.0", + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + } + }, "preferred-pm": { "version": "3.0.3", "dev": true, @@ -20148,11 +20768,12 @@ } }, "propagate": { - "version": "2.0.1", - "dev": true + "version": "2.0.1" }, "pseudomap": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", "dev": true }, "pump": { @@ -20173,6 +20794,19 @@ "version": "6.0.0", "dev": true }, + "pvtsutils": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.2.tgz", + "integrity": "sha512-+Ipe2iNUyrZz+8K/2IOo+kKikdtfhRKzNpQbruF2URmqPtoqAs8g3xS7TJvFF2GcPXjh7DkqMnpVveRFq4PgEQ==", + "requires": { + "tslib": "^2.4.0" + } + }, + "pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==" + }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", @@ -20268,6 +20902,8 @@ }, "read-yaml-file": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-yaml-file/-/read-yaml-file-1.1.0.tgz", + "integrity": "sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==", "dev": true, "requires": { "graceful-fs": "^4.1.5", @@ -20278,6 +20914,8 @@ "dependencies": { "argparse": { "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { "sprintf-js": "~1.0.2" @@ -20285,6 +20923,8 @@ }, "js-yaml": { "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -20293,6 +20933,8 @@ }, "strip-bom": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true } } @@ -20345,6 +20987,11 @@ "esprima": "~4.0.0" } }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, "regenerator-runtime": { "version": "0.13.11", "dev": true @@ -20501,9 +21148,9 @@ "dev": true }, "semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", "requires": { "lru-cache": "^6.0.0" }, @@ -20572,20 +21219,13 @@ "sigstore": { "version": "file:packages/client", "requires": { + "@sigstore/jest": "^0.0.0", "@sigstore/protobuf-specs": "^0.1.0", - "@sigstore/rekor-types": "^0.0.3", - "@sigstore/tuf": "^0.0.0", - "@total-typescript/shoehorn": "^0.1.0", + "@sigstore/rekor-types": "^1.0.0", + "@sigstore/tuf": "^1.0.0", "@tufjs/repo-mock": "^1.1.0", "@types/make-fetch-happen": "^10.0.0", - "@types/node": "^20.2.5", - "@types/sigstore-jest-extended": "^0.0.0", - "json-schema-to-typescript": "^13.0.0", - "make-fetch-happen": "^11.0.1", - "nock": "^13.2.4", - "shx": "^0.3.3", - "tuf-js": "^1.1.3", - "typescript": "^5.1.3" + "make-fetch-happen": "^11.0.1" } }, "sisteransi": { @@ -20746,6 +21386,8 @@ }, "spawndamnit": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawndamnit/-/spawndamnit-2.0.0.tgz", + "integrity": "sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==", "dev": true, "requires": { "cross-spawn": "^5.1.0", @@ -20754,6 +21396,8 @@ "dependencies": { "cross-spawn": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", "dev": true, "requires": { "lru-cache": "^4.0.1", @@ -20763,6 +21407,8 @@ }, "lru-cache": { "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", "dev": true, "requires": { "pseudomap": "^1.0.2", @@ -20771,6 +21417,8 @@ }, "shebang-command": { "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", "dev": true, "requires": { "shebang-regex": "^1.0.0" @@ -20778,10 +21426,14 @@ }, "shebang-regex": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", "dev": true }, "which": { "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { "isexe": "^2.0.0" @@ -20789,6 +21441,8 @@ }, "yallist": { "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", "dev": true } } @@ -21135,7 +21789,9 @@ "dev": true }, "ts-jest": { - "version": "29.1.0", + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", "dev": true, "requires": { "bs-logger": "0.x", @@ -21144,7 +21800,7 @@ "json5": "^2.2.3", "lodash.memoize": "4.x", "make-error": "1.x", - "semver": "7.x", + "semver": "^7.5.3", "yargs-parser": "^21.0.1" } }, @@ -21166,12 +21822,19 @@ "make-error": "^1.1.1", "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" + }, + "dependencies": { + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + } } }, "tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==" + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" }, "tsutils": { "version": "3.21.0", @@ -21188,6 +21851,21 @@ } } }, + "tsyringe": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.7.0.tgz", + "integrity": "sha512-ncFDM1jTLsok4ejMvSW5jN1VGPQD48y2tfAR0pdptWRKYX4bkbqPt92k7KJ5RFJ1KV36JEs/+TMh7I6OUgj74g==", + "requires": { + "tslib": "^1.9.3" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, "tty-table": { "version": "4.1.6", "dev": true, @@ -21208,13 +21886,13 @@ } }, "tuf-js": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.6.tgz", - "integrity": "sha512-CXwFVIsXGbVY4vFiWF7TJKWmlKJAT8TWkH4RmiohJRcDJInix++F0dznDmoVbtJNzZ8yLprKUG4YrDIhv3nBMg==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz", + "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==", "requires": { "@tufjs/models": "1.0.4", "debug": "^4.3.4", - "make-fetch-happen": "^11.1.0" + "make-fetch-happen": "^11.1.1" } }, "tunnel-agent": { @@ -21257,9 +21935,9 @@ } }, "typescript": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", - "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==" + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", + "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==" }, "uglify-js": { "version": "3.17.4", @@ -21468,6 +22146,18 @@ "defaults": "^1.0.3" } }, + "webcrypto-core": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.7.tgz", + "integrity": "sha512-7FjigXNsBfopEj+5DV2nhNpfic2vumtjjgPmeDKk45z+MJwXKKfhPB7118Pfzrmh4jqOMST6Ch37iPAHoImg5g==", + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/json-schema": "^1.1.12", + "asn1js": "^3.0.1", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", diff --git a/package.json b/package.json index 8bde3ea9..73b69415 100644 --- a/package.json +++ b/package.json @@ -15,20 +15,22 @@ }, "license": "Apache-2.0", "devDependencies": { - "@changesets/cli": "^2.26.0", - "@tsconfig/node14": "^1.0.3", + "@changesets/cli": "^2.26.2", + "@total-typescript/shoehorn": "^0.1.1", + "@tsconfig/node14": "^14.1.0", "@types/jest": "^29.5.2", - "@types/node": "^20.2.5", - "@typescript-eslint/eslint-plugin": "^5.59.9", - "@typescript-eslint/parser": "^5.59.9", - "eslint": "^8.42.0", + "@types/node": "^20.3.2", + "@typescript-eslint/eslint-plugin": "^5.60.1", + "@typescript-eslint/parser": "^5.60.1", + "eslint": "^8.43.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-prettier": "^4.0.0", "jest": "^29.4.1", "nock": "^13.2.4", "prettier": "^2.6.2", - "ts-jest": "^29.0.5", - "typescript": "^5.1.3" + "shx": "^0.3.3", + "ts-jest": "^29.1.1", + "typescript": "^5.1.6" }, "workspaces": [ "./packages/*" diff --git a/packages/cli/package.json b/packages/cli/package.json index ae633129..33c21840 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -42,9 +42,7 @@ "devDependencies": { "make-fetch-happen": "^11.1.1", "oclif": "^3", - "shx": "^0.3.3", - "tslib": "^2.5.3", - "typescript": "^5.1.3" + "tslib": "^2.6.0" }, "repository": { "type": "git", diff --git a/packages/client/CHANGELOG.md b/packages/client/CHANGELOG.md index 35907326..365550bc 100644 --- a/packages/client/CHANGELOG.md +++ b/packages/client/CHANGELOG.md @@ -1,10 +1,24 @@ # sigstore +## 1.7.0 + +### Minor Changes + +- f374dd3: Include transparency log inclusion proof in Sigstore bundle +- fbfb315: Exports new `createVerifier` function + +### Patch Changes + +- bd1e1e1: Internal refactoring of Typescript types +- Updated dependencies [b97be71] + - @sigstore/tuf@1.0.1 + ## 1.6.0 ### Minor Changes - 5ea8b63: Adds a new `identityProvider` config option for the `sign`/`attest` functions +- 16de8c7: Support for verifying Rekor entries w/ the new `dsse` entry type ### Patch Changes diff --git a/packages/client/jest.config.js b/packages/client/jest.config.js index d4dfe40c..e2ecd478 100644 --- a/packages/client/jest.config.js +++ b/packages/client/jest.config.js @@ -18,7 +18,7 @@ const base = require('../../jest.config.base'); module.exports = { ...base, displayName: 'client', - setupFilesAfterEnv: ['./jest.setup.ts'], + setupFilesAfterEnv: ['./jest.setup.ts', '@sigstore/jest/all'], testPathIgnorePatterns: [ '/dist/', '/src/__tests__/__fixtures__', diff --git a/packages/client/jest.setup.ts b/packages/client/jest.setup.ts index d422bb09..3b8733ae 100644 --- a/packages/client/jest.setup.ts +++ b/packages/client/jest.setup.ts @@ -15,75 +15,5 @@ limitations under the License. */ console.error = jest.fn(); -const result = (pass: boolean, msg: string) => ({ pass, message: () => msg }); -const pass = (msg: string) => result(true, msg); -const fail = (msg: string) => result(false, msg); - -const customMatchersObj = { - // The promise attribute is necessary for the type checking to work correctly - // in the matchers below. It is not used in the matchers themselves as the - // functions are invoked with `this` bound to the Jest matchers object. - promise: undefined, - - // Matcher for checking that a function throws an error of a specific type - // with a specific `code` property - // eslint-disable-next-line @typescript-eslint/no-explicit-any - toThrowWithCode(received: any, type: any, code: string) { - const isFromReject = this && this.promise === 'rejects'; - - // Must be called with either a rejected promise, or a function to be - // invoked - if ((!received || typeof received !== 'function') && !isFromReject) { - return fail(`Excpected ${received} to be a function`); - } - - // Type must be some kind of class (e.g. Error) - if (!type || typeof type !== 'function') { - return fail(`Type argument must be a function, received ${type}`); - } - - if (typeof code !== 'string') { - return fail(`Code argument must be a string, received ${code}`); - } - - // Gather the error, either from the rejected promise or by invoking the - // supplied function - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let error: (object & { code?: string; name?: string }) | null = null; - if (isFromReject) { - error = received; - } else { - try { - received(); - } catch (e) { - error = e as object; - } - } - - if (!error) { - return fail(`Received function did not throw`); - } - - if (!(error instanceof type)) { - return fail( - `Expected function to throw ${type.name}, but got ${error.name}` - ); - } - - if (error.code !== code) { - return fail( - `Expected error to have code "${code}", but got "${error.code}"` - ); - } - return pass(`Expected function to throw ${type.name} with code ${code}`); - }, -}; - -// Strip out the dummy `promise` attribute from the custom matchers object -// before passing it to Jest's `expect.extend` function -// eslint-disable-next-line @typescript-eslint/no-unused-vars -const { promise: _, ...customMatchers } = customMatchersObj; -expect.extend(customMatchers); - // Export something so we look like a an importable module export {}; diff --git a/packages/client/package.json b/packages/client/package.json index b7dc6e30..02655a6c 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "sigstore", - "version": "1.6.0", + "version": "1.7.0", "description": "code-signing for npm packages", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -31,21 +31,14 @@ }, "devDependencies": { "@sigstore/rekor-types": "^1.0.0", - "@total-typescript/shoehorn": "^0.1.0", + "@sigstore/jest": "^0.0.0", "@tufjs/repo-mock": "^1.1.0", - "@types/make-fetch-happen": "^10.0.0", - "@types/sigstore-jest-extended": "^0.0.0", - "@types/node": "^20.2.5", - "json-schema-to-typescript": "^13.0.0", - "nock": "^13.2.4", - "shx": "^0.3.3", - "typescript": "^5.1.3" + "@types/make-fetch-happen": "^10.0.0" }, "dependencies": { "@sigstore/protobuf-specs": "^0.1.0", - "@sigstore/tuf": "^1.0.0", - "make-fetch-happen": "^11.0.1", - "tuf-js": "^1.1.3" + "@sigstore/tuf": "^1.0.1", + "make-fetch-happen": "^11.0.1" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" diff --git a/packages/client/src/__tests__/__fixtures__/trust.ts b/packages/client/src/__tests__/__fixtures__/trust.ts index 37eb9da9..1596a1dd 100644 --- a/packages/client/src/__tests__/__fixtures__/trust.ts +++ b/packages/client/src/__tests__/__fixtures__/trust.ts @@ -13,7 +13,8 @@ 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. */ -import * as sigstore from '../../types/sigstore'; +import { TrustedRoot } from '@sigstore/protobuf-specs'; + const trustedRootJSON = { mediaType: 'application/vnd.dev.sigstore.trustedroot+json;version=0.1', tlogs: [ @@ -103,4 +104,4 @@ const trustedRootJSON = { timestampAuthorities: [], }; -export const trustedRoot = sigstore.TrustedRoot.fromJSON(trustedRootJSON); +export const trustedRoot = TrustedRoot.fromJSON(trustedRootJSON); diff --git a/packages/client/src/__tests__/ca/verify/index.test.ts b/packages/client/src/__tests__/ca/verify/index.test.ts index 1a9cd08a..3b8fda5c 100644 --- a/packages/client/src/__tests__/ca/verify/index.test.ts +++ b/packages/client/src/__tests__/ca/verify/index.test.ts @@ -21,7 +21,7 @@ import { trustedRoot } from '../../__fixtures__/trust'; describe('verifySigningCertificate', () => { // Temporary until we reconsole bundle formats const bundleJSON = bundles.dsse.valid.withSigningCert; - const bundle = sigstore.Bundle.fromJSON( + const bundle = sigstore.bundleFromJSON( bundleJSON ) as sigstore.BundleWithCertificateChain; diff --git a/packages/client/src/__tests__/index.test.ts b/packages/client/src/__tests__/index.test.ts index 5c9794dd..b214f588 100644 --- a/packages/client/src/__tests__/index.test.ts +++ b/packages/client/src/__tests__/index.test.ts @@ -22,12 +22,17 @@ describe('sigstore', () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const identityProvider: IdentityProvider = {} as any; expect(identityProvider).toBeDefined(); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const bundleVerifier: sigstore.BundleVerifier = {} as any; + expect(bundleVerifier).toBeDefined(); }); it('exports sigstore core functions', async () => { expect(sigstore.attest).toBeInstanceOf(Function); expect(sigstore.sign).toBeInstanceOf(Function); expect(sigstore.verify).toBeInstanceOf(Function); + expect(sigstore.createVerifier).toBeInstanceOf(Function); }); it('exports sigstore utils', () => { diff --git a/packages/client/src/__tests__/merkle/digest.test.ts b/packages/client/src/__tests__/merkle/digest.test.ts deleted file mode 100644 index 386ccf77..00000000 --- a/packages/client/src/__tests__/merkle/digest.test.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* -Copyright 2022 GitHub, Inc - -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. -*/ - -import { Hasher } from '../../merkle/digest'; - -describe('Hasher', () => { - it('should create an instance', () => { - const hasher = new Hasher(); - expect(hasher).toBeTruthy(); - }); - - describe('when the hash algorithm is sha256', () => { - const subject = new Hasher('sha256'); - - describe('size', () => { - it('is 32', () => { - expect(subject.size()).toBe(32); - }); - }); - - describe('hashLeaf', () => { - it('hashes a leaf', () => { - const hash = subject.hashLeaf(Buffer.from('hello')); - - expect(hash).toEqual( - Buffer.from('iipcm3aIJ95alVLDigRMZpWcaPbS8htSYK9U0vh9uCc=', 'base64') - ); - }); - }); - - describe('hashChildren', () => { - it('hashes the children', () => { - const l = Buffer.from('left'); - const r = Buffer.from('right'); - const hash = subject.hashChildren(l, r); - - expect(hash).toEqual( - Buffer.from('I8JKzKnpqpZvObkOQVTZEzNPoWDjX8vNA05nO/szOa0=', 'base64') - ); - }); - }); - }); -}); diff --git a/packages/client/src/__tests__/merkle/verify.test.ts b/packages/client/src/__tests__/merkle/verify.test.ts deleted file mode 100644 index 773a6dff..00000000 --- a/packages/client/src/__tests__/merkle/verify.test.ts +++ /dev/null @@ -1,94 +0,0 @@ -/* -Copyright 2022 GitHub, Inc - -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. -*/ - -import { Hasher } from '../../merkle/digest'; -import { verifyInclusion } from '../../merkle/verify'; - -describe('verifyInclusion', () => { - const defaultHasher = new Hasher(); - - // Test data comes from https://rekor.sigstore.dev/api/v1/log/entries?logIndex=3056587 - const entry = - 'eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoicmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI0OGQ5OTkyNjBkZmY4ZDgzNGY4MWM4NWE3NGY1MDk1YWY4ZWRlNTM5ZWEzYWVhMTk5NTc4N2M0NTU1YzZiZTQ3In19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUURDRnBjaHVyQTNTWVNFMTJHTG9qUjRZRmR5RFpkaU9IbkppYVdLRENiVW53SWdHSnJRUm5qcm9xUmtuRiszRUdqaHhqaURUZDhURXB2MTVmZkRBR2Z6enVVPSIsImZvcm1hdCI6Ing1MDkiLCJwdWJsaWNLZXkiOnsiY29udGVudCI6IkxTMHRMUzFDUlVkSlRpQlFWVUpNU1VNZ1MwVlpMUzB0TFMwS1RVWnJkMFYzV1VoTGIxcEplbW93UTBGUldVbExiMXBKZW1vd1JFRlJZMFJSWjBGRlRXVmpZWFVyV1daTlJsZFpjazV0ZDFreldVaE5kM0E0VlUwMU1RcHhaV1o1ZG1oWmNqSnhaV0pLV0ZCdFdFY3hWM0JpYkdwWFkyYzVaekZHVDJoUWFXVjVPVWh6VEVsdGFERnJWMlJqYkhjdlkzcERWMUYzUFQwS0xTMHRMUzFGVGtRZ1VGVkNURWxESUV0RldTMHRMUzB0Q2c9PSJ9fX19'; - const entryBytes = Buffer.from(entry, 'base64'); - - const hashes = [ - '6f6ad87e72762b653c96db394eadcb58a8bbce16ba72fd3d1ad56421baefd0af', - '2fa68c2f97cdf8257b0e8103d10ab6320c5007099c8f9e2c2196db634dc364f5', - '9f8f947be87b4f343a0ad1a4835cabd0c744eff2a51b852057e8459e2bb55a56', - '336e1fc366c19dd34250e10baea5ef74caa0a5b7db0ae92047fcda8067c0385f', - '5da501f1e7f45fe63af0b09373b4f5578b3899d3fc6e0ec7262387d2975eb22c', - '490b00a963228e7a8f70762d4856eeeb8280413e1d1cb7fb4e9683e223b5f6ba', - '075e588755235f14fddd7190ac9347b6ec045ce4c88a0794ce193cbfe3d60142', - '167fe9d15fd6a3de12ae2747785e23c9425bf677c7fd957976cae3e27b6d9bd1', - 'eee183886501e85197c62c6c0d371e479115f71a50618d8552b73b228717a5ae', - 'ef118b4a9e69d9000c48515d7e2f30ce606197d21e6bacc82fd7a61c48a67507', - 'bd0cbc5a454654ff88d2e08e3c443204308e423834e0fed2481b847da5d2dfcf', - 'cec90b763ab869bc411f51ed8f4206b4d051c9502533f2638b15277fd2ae5e9e', - '4e2d269ec9ef9d4e9270c482b70a64e75d84f850902b5e5e65acd14844cf659b', - 'd63d28e2b4a9476ea2df69f03be3e9dd453c2232ed172e5f79487a9e60711f51', - '599040ed55824445153996171c1045d696176b6a252159aaa3630c033b45e70c', - '860efc785c66773fe35db221860cfb482dfe0a6bfe602aaade78149084c9ab86', - '39da4af7f0fbe095e6bc78c146ad59c70881d3fcb22e90c7675dee5e6736bc76', - '806e7153f439cdb4558d7ac89defb0e17aa9742e888cb660774b94b5399c3322', - 'efb36cfc54705d8cd921a621a9389ffa03956b15d68bfabadac2b4853852079b', - ]; - const proof = hashes.map((hash) => Buffer.from(hash, 'hex')); - - const rootHash = - '8326106075b643a01711dddf32e9b361b475ca21e9d81afec867a3c6a3dbb55c'; - const root = Buffer.from(rootHash, 'hex'); - - const index = BigInt(3056587); - const size = BigInt(3063448); - - describe('when everything matches perfectly', () => { - it('returns true', () => { - const leafHash = defaultHasher.hashLeaf(entryBytes); - - expect( - verifyInclusion(defaultHasher, index, size, leafHash, proof, root) - ).toBe(true); - }); - }); - - describe('when the leaf hash is incorrect', () => { - it('returns false', () => { - const leafHash = defaultHasher.hashLeaf(Buffer.from('wrong')); - - expect( - verifyInclusion(defaultHasher, index, size, leafHash, proof, root) - ).toBe(false); - }); - }); - - describe('when the proof is missing hashes', () => { - it('returns false', () => { - const leafHash = defaultHasher.hashLeaf(entryBytes); - - expect(() => { - verifyInclusion( - defaultHasher, - index, - size, - leafHash, - proof.slice(2), - root - ); - }).toThrow('invalid proof length'); - }); - }); -}); diff --git a/packages/client/src/__tests__/sign.test.ts b/packages/client/src/__tests__/sign.test.ts index 82a4b8b4..3341cdb9 100644 --- a/packages/client/src/__tests__/sign.test.ts +++ b/packages/client/src/__tests__/sign.test.ts @@ -23,6 +23,8 @@ import { SignatureMaterial, SignerFunc } from '../types/signature'; import { HashAlgorithm } from '../types/sigstore'; import { pem } from '../util'; +import type { LogEntry } from '@sigstore/rekor-types'; + describe('Signer', () => { const fulcioBaseURL = 'http://localhost:8001'; const rekorBaseURL = 'http://localhost:8002'; @@ -140,9 +142,16 @@ describe('Signer', () => { verification: { signedEntryTimestamp: 'MEUCIQD6CD7ZNLUipFoxzmSL/L8Ewic4SRkXN77UjfJZ7d/wAAIgatokSuX9Rg0iWxAgSfHMtcsagtDCQalU5IvXdQ+yLEA=', + inclusionProof: { + hashes: ['deadbeef', 'feedface'], + logIndex: 12345, + rootHash: 'fee1dead', + treeSize: 12346, + checkpoint: 'checkpoint', + }, }, }, - }; + } satisfies LogEntry; beforeEach(() => { // Mock Rekor request @@ -211,7 +220,34 @@ describe('Signer', () => { expect(tlog?.logIndex).toEqual( rekorEntry[uuid].logIndex.toString() ); - expect(tlog?.inclusionProof).toBeFalsy(); + expect(tlog?.inclusionProof?.checkpoint?.envelope).toEqual( + rekorEntry[uuid].verification.inclusionProof.checkpoint + ); + expect(tlog?.inclusionProof?.hashes).toHaveLength(2); + expect(tlog?.inclusionProof?.hashes[0]).toEqual( + Buffer.from( + rekorEntry[uuid].verification.inclusionProof.hashes[0], + 'hex' + ) + ); + expect(tlog?.inclusionProof?.hashes[1]).toEqual( + Buffer.from( + rekorEntry[uuid].verification.inclusionProof.hashes[1], + 'hex' + ) + ); + expect(tlog?.inclusionProof?.logIndex).toEqual( + rekorEntry[uuid].verification.inclusionProof.logIndex.toString() + ); + expect(tlog?.inclusionProof?.rootHash).toEqual( + Buffer.from( + rekorEntry[uuid].verification.inclusionProof.rootHash, + 'hex' + ) + ); + expect(tlog?.inclusionProof?.treeSize).toEqual( + rekorEntry[uuid].verification.inclusionProof.treeSize.toString() + ); expect(tlog?.kindVersion?.kind).toEqual('hashedrekord'); expect(tlog?.kindVersion?.version).toEqual('0.0.1'); }); diff --git a/packages/client/src/__tests__/sigstore.test.ts b/packages/client/src/__tests__/sigstore.test.ts index 4e1b2678..2b498e94 100644 --- a/packages/client/src/__tests__/sigstore.test.ts +++ b/packages/client/src/__tests__/sigstore.test.ts @@ -13,11 +13,7 @@ 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. */ -import { TUFError } from '@sigstore/tuf'; -import mocktuf, { Target } from '@tufjs/repo-mock'; -import { PolicyError, VerificationError } from '../error'; -import { Signer } from '../sign'; -import { attest, sign, tuf, verify } from '../sigstore'; +/* eslint-disable @typescript-eslint/no-non-null-assertion */ import { Bundle, HashAlgorithm, @@ -25,11 +21,18 @@ import { TransparencyLogEntry, TrustedRoot, X509CertificateChain, -} from '../types/sigstore'; +} from '@sigstore/protobuf-specs'; +import { TUFError } from '@sigstore/tuf'; +import { fromPartial } from '@total-typescript/shoehorn'; +import mocktuf, { Target } from '@tufjs/repo-mock'; +import { PolicyError, VerificationError } from '../error'; +import { Signer } from '../sign'; +import { attest, createVerifier, sign, tuf, verify } from '../sigstore'; +import { SerializedBundle } from '../types/sigstore'; import bundles from './__fixtures__/bundles'; import { trustedRoot } from './__fixtures__/trust'; -import type { VerifyOptions } from '../config'; +import type { TUFOptions, VerifyOptions } from '../config'; jest.mock('../sign'); @@ -317,13 +320,19 @@ describe('#verify', () => { }); }); -describe('tuf', () => { +describe('#createVerifier', () => { let tufRepo: ReturnType | undefined; - let options: VerifyOptions | undefined; + let tufOptions: VerifyOptions | undefined; + + const trustedRootJSON = JSON.stringify(TrustedRoot.toJSON(trustedRoot)); + const target: Target = { + name: 'trusted_root.json', + content: Buffer.from(trustedRootJSON), + }; beforeEach(() => { tufRepo = mocktuf(target, { metadataPathPrefix: '' }); - options = { + tufOptions = { tufMirrorURL: tufRepo.baseURL, tufCachePath: tufRepo.cachePath, }; @@ -331,11 +340,55 @@ describe('tuf', () => { afterEach(() => tufRepo?.teardown()); + it('returns a object', async () => { + const verifier = await createVerifier(tufOptions!); + expect(verifier).toBeInstanceOf(Object); + }); + + describe('when the bundle is valid', () => { + const bundle: SerializedBundle = fromPartial( + bundles.dsse.valid.withSigningCert + ); + + it('does not throw an error when invoked', async () => { + const verifier = await createVerifier(tufOptions!); + expect(verifier.verify(bundle)).toBeUndefined(); + }); + }); + + describe('when the bundle is invalid', () => { + const bundle: SerializedBundle = fromPartial( + bundles.dsse.invalid.badSignature + ); + + it('throws an error when invoked', async () => { + const verifier = await createVerifier(tufOptions!); + expect(() => { + verifier.verify(bundle); + }).toThrowError(VerificationError); + }); + }); +}); + +describe('tuf', () => { + let tufRepo: ReturnType | undefined; + let options: TUFOptions | undefined; + const target: Target = { name: 'foo', content: 'bar', }; + beforeEach(() => { + tufRepo = mocktuf(target, { metadataPathPrefix: '' }); + options = { + tufMirrorURL: tufRepo.baseURL, + tufCachePath: tufRepo.cachePath, + }; + }); + + afterEach(() => tufRepo?.teardown()); + describe('getTarget', () => { describe('when the target exists', () => { it('returns the target', async () => { diff --git a/packages/client/src/__tests__/tlog/verify/index.test.ts b/packages/client/src/__tests__/tlog/verify/index.test.ts index b0948f12..99382dd0 100644 --- a/packages/client/src/__tests__/tlog/verify/index.test.ts +++ b/packages/client/src/__tests__/tlog/verify/index.test.ts @@ -22,7 +22,7 @@ import { trustedRoot } from '../../__fixtures__/trust'; describe('verifyTLogEntries', () => { const bundle = sigstore.bundleFromJSON( bundles.signature.valid.withSigningCert - ) as sigstore.BundleWithVerificationMaterial; + ) as sigstore.Bundle; const options: sigstore.ArtifactVerificationOptions_TlogOptions = { disable: false, @@ -42,7 +42,7 @@ describe('verifyTLogEntries', () => { describe('when the bundle does NOT have a signing certificate', () => { const bundle = sigstore.bundleFromJSON( bundles.signature.valid.withPublicKey - ) as sigstore.BundleWithVerificationMaterial; + ) as sigstore.Bundle; it('does NOT throw an error', () => { expect(() => @@ -83,7 +83,7 @@ describe('verifyTLogEntries', () => { describe('when tlog entries are missing data necessary for verification', () => { const bundle = sigstore.bundleFromJSON( bundles.dsse.invalid.tlogKindVersionMissing - ) as sigstore.BundleWithVerificationMaterial; + ) as sigstore.Bundle; it('throws an error', () => { expect(() => verifyTLogEntries(bundle, trustedRoot, options)).toThrow( diff --git a/packages/client/src/__tests__/tlog/verify/merkle.test.ts b/packages/client/src/__tests__/tlog/verify/merkle.test.ts new file mode 100644 index 00000000..609910ec --- /dev/null +++ b/packages/client/src/__tests__/tlog/verify/merkle.test.ts @@ -0,0 +1,197 @@ +/* +Copyright 2023 The Sigstore 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. +*/ +import { VerificationError } from '../../../error'; +import { verifyMerkleInclusion } from '../../../tlog/verify/merkle'; +import * as sigstore from '../../../types/sigstore'; + +describe('verifyMerkleInclusion', () => { + // Test data comes from https://rekor.sigstore.dev/api/v1/log/entries?logIndex=25591465 + const canonicalizedBody = Buffer.from( + 'eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaW50b3RvIiwic3BlYyI6eyJjb250ZW50Ijp7ImVudmVsb3BlIjp7InBheWxvYWRUeXBlIjoiYXBwbGljYXRpb24vdm5kLmluLXRvdG8ranNvbiIsInNpZ25hdHVyZXMiOlt7InB1YmxpY0tleSI6IkxTMHRMUzFDUlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVU13VkVORFFXeGhaMEYzU1VKQlowbFZRMGxaYmpsclZWQkRTV2hqTVdKcFJFTTBhMlJQV1ROVGNXRm5kME5uV1VsTGIxcEplbW93UlVGM1RYY0tUbnBGVmsxQ1RVZEJNVlZGUTJoTlRXTXliRzVqTTFKMlkyMVZkVnBIVmpKTlVqUjNTRUZaUkZaUlVVUkZlRlo2WVZka2VtUkhPWGxhVXpGd1ltNVNiQXBqYlRGc1drZHNhR1JIVlhkSWFHTk9UV3BOZDA1cVNUVk5WR040VFVSVk1WZG9ZMDVOYWsxM1RtcEpOVTFVWTNsTlJGVXhWMnBCUVUxR2EzZEZkMWxJQ2t0dldrbDZhakJEUVZGWlNVdHZXa2w2YWpCRVFWRmpSRkZuUVVVelZVOVVZWGhKVW5sUFdHbHJOM1JCVFRKT01rcFNkV04zVG1aRmNYUXdRbkE1Tm1FS2VHd3hORUpOV0ZRMWR5OW1lVzAwWmtNd1JFUnZUazVyY0ZaWVVtZHFhMjkxTTBjeFpsa3dZV3RzY2xJclJpOWFWWEZQUTBGWVZYZG5aMFo0VFVFMFJ3cEJNVlZrUkhkRlFpOTNVVVZCZDBsSVowUkJWRUpuVGxaSVUxVkZSRVJCUzBKblozSkNaMFZHUWxGalJFRjZRV1JDWjA1V1NGRTBSVVpuVVZWWlRXbGxDa2xRVVhKWUwwdE5NM2xqTWtZeFNHRnhXSEZwTTJNMGQwaDNXVVJXVWpCcVFrSm5kMFp2UVZVek9WQndlakZaYTBWYVlqVnhUbXB3UzBaWGFYaHBORmtLV2tRNGQwaDNXVVJXVWpCU1FWRklMMEpDVlhkRk5FVlNXVzVLY0ZsWE5VRmFSMVp2V1ZjeGJHTnBOV3BpTWpCM1RFRlpTMHQzV1VKQ1FVZEVkbnBCUWdwQlVWRmxZVWhTTUdOSVRUWk1lVGx1WVZoU2IyUlhTWFZaTWpsMFRESjRkbG95YkhWTU1qbG9aRmhTYjAxRE5FZERhWE5IUVZGUlFtYzNPSGRCVVdkRkNrbEJkMlZoU0ZJd1kwaE5Oa3g1T1c1aFdGSnZaRmRKZFZreU9YUk1NbmgyV2pKc2RVd3lPV2hrV0ZKdlRVbEhTMEpuYjNKQ1owVkZRV1JhTlVGblVVTUtRa2gzUldWblFqUkJTRmxCTTFRd2QyRnpZa2hGVkVwcVIxSTBZMjFYWXpOQmNVcExXSEpxWlZCTE15OW9OSEI1WjBNNGNEZHZORUZCUVVkS1EwTk1lUXAxVVVGQlFrRk5RVko2UWtaQmFVRnphbTh6YTBvd1lYWlFkelUwY2tGVVNHNVNRelF6TkZKUVpFMHZlbTlCVldsdFRuZERSQ3MyZVZsUlNXaEJURXQ0Q2pGdWVsUk9NSGxEYTBKdVRUbFlTMVkyUVdSRGVVdFdkMmh2TjFKeU1GbEdORW95WldGclMweE5RVzlIUTBOeFIxTk5ORGxDUVUxRVFUSnJRVTFIV1VNS1RWRkVORzgwWVRoa2VraDNZbFIwTmpJMU5FazFXWHBETVVoWVJVSnRlazQwVkVoYVpGQnBMMlpZZFc1T2NXTTVMMjF2V0d0cWQxcExTSE5DWWtSV09RcElOVmxEVFZGRVRVRTNaemhQWldwSU5rMTNVa2xpVXk5WFVUTjFOM1ZWV21WYVNsRnFTMFJHWWpkTmJHTmxRbFI0SzBRdlQzTnFkVkpOTldwWWRtNWFDa1l5UmxaeVYxVTlDaTB0TFMwdFJVNUVJRU5GVWxSSlJrbERRVlJGTFMwdExTMD0iLCJzaWciOiJUVVZWUTBsUlJFNXBWWGxPZWxwc05pOU1iblJ4ZUdoNVRsZExUbkZJYm1aRFFrWnNWRWxCYjNKdFNtSnFXRWRqZVZGSlowOVFSM0ZNYm5wWFlWWlJWbk5KUlZwQ1MyNXJURzlWVGtJMlJIWkRVVGRxT0RaTVJIZ3dObE13ZEZrOSJ9XX0sImhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI3OWJiMDRhN2VhMDA3M2FiN2VmY2NkYjlkOWM5NTQ0MWJiOWJkNjQ5ZGE5ZTc0YzNlNzkzMTVlZTk5NjFkYWE4In0sInBheWxvYWRIYXNoIjp7ImFsZ29yaXRobSI6InNoYTI1NiIsInZhbHVlIjoiOGE3NWY2YzhkYzRkOWY0MDcyODViYjQ5ZDNlMDE5YTVlNjY2ZjQzNDk5YzI3MDdkOTI4OWFhMjdjM2MyYTY3ZSJ9fX19', + 'base64' + ); + const inclusionProof = { + logIndex: '21428034', + treeSize: '21476367', + hashes: [ + Buffer.from( + '19d3dbf73de6aefabc91f0b0e143b98aa85a09da0fe425ec5f1cd6d156f71618', + 'hex' + ), + Buffer.from( + 'd1142137fddf94069fea54345b912823d6b58b6c11988056581e14328cc1030f', + 'hex' + ), + Buffer.from( + '93dc3b1aa26f0abe487597beae4e195e906e749e8e4ddeee27e79dbde5b91402', + 'hex' + ), + Buffer.from( + '39f0b7d480d19cf281a3fd1bb9e22d2e00c4439872b4bbf93356761ff7924d01', + 'hex' + ), + Buffer.from( + 'c4dbc3de6933e3adec550dd14c7fee8959ae510524e8028c3e755c3c6b865be4', + 'hex' + ), + Buffer.from( + 'fb0c3969556c47a5da58cb9cd58de783f1d133f145b2a24ff6c7767ad0557b20', + 'hex' + ), + Buffer.from( + '8a8f4d600381615d5a9ebc191241cffa65299e80a5f48562f63d72630aedf0c6', + 'hex' + ), + Buffer.from( + '6e3cfb0b5ac7d32e7e58f51324748e12600d03fe293049fe36247fed3fb2fa65', + 'hex' + ), + Buffer.from( + 'ea20898f9069a9d85faf515f20b062b56b1ff4c1750ce4d741acead08b254b4a', + 'hex' + ), + Buffer.from( + '3c0c2711b5709e116362413734eebf10b2dcd81cadd2325502254585f5408a93', + 'hex' + ), + Buffer.from( + '293213bbbac895205eb11b6a4f905eeb2632182aa8022fc96c109d5fa9d9ea31', + 'hex' + ), + Buffer.from( + 'f6f08053bc2277b800e3bfbc74db76a24015f1f38a17e438fac9f3e3a49aa1d4', + 'hex' + ), + Buffer.from( + '0be5c7bbcf481d1efcfc63a27fce447cf6345f7bb3155cf5de39de592c16d52d', + 'hex' + ), + Buffer.from( + 'f597f4bae8df3d6fc6eebfe3eabd7d393e08781f6f16b42398eca8512398fff1', + 'hex' + ), + Buffer.from( + '4e35fcb3c0a59e7f329994002b38db35f5d511f499ba009e10b31f5d27563607', + 'hex' + ), + Buffer.from( + '47044b7ac3aab820e44f0010538d7de71e17a11f4140cbbe9eeb37f78b77cc7d', + 'hex' + ), + Buffer.from( + 'a096e8b56b363e063fb47944b05535e10247eae804325cc5c5df3d024b61e9bf', + 'hex' + ), + Buffer.from( + 'ff41aa21106dbe03996b4335dd158c7ffafd144e45022193de19b2b9136c3e42', + 'hex' + ), + Buffer.from( + 'e6ebdeef2e23335d8d7049ba5a0049a90593efdfe9c1b4548946b44a19d7214f', + 'hex' + ), + Buffer.from( + 'dd51e840e892d70093ad7e1db1e2dea3d50334c7345d360e444d22fc49ed9f5e', + 'hex' + ), + Buffer.from( + 'ad712c98424de0f1284d4f144b8a95b5d22c181d4c0a246518e7a9a220bdf643', + 'hex' + ), + ], + rootHash: Buffer.from( + 'd5c395a44b9537f8fa2524a6e93071969dd475ac40e87e2b1231b2aebd9a138b', + 'hex' + ), + }; + + describe('when the inclusion proof is valid', () => { + const entry = { + canonicalizedBody, + inclusionProof, + } as sigstore.TransparencyLogEntry; + + it('returns true', () => { + expect(verifyMerkleInclusion(entry)).toBe(true); + }); + }); + + describe('when the entry does NOT match the inclusion proof', () => { + const invalidEntry = { + canonicalizedBody: Buffer.from('invalid'), + inclusionProof, + } as sigstore.TransparencyLogEntry; + + it('returns false', () => { + expect(verifyMerkleInclusion(invalidEntry)).toBe(false); + }); + }); + + describe('when the log index is invalid', () => { + const invalidEntry = { + canonicalizedBody, + inclusionProof: { ...inclusionProof, logIndex: '-1' }, + } as sigstore.TransparencyLogEntry; + + it('throws an error', () => { + expect(() => verifyMerkleInclusion(invalidEntry)).toThrow( + VerificationError + ); + }); + }); + + describe('when the entry does NOT contain an inclusion proof', () => { + const invalidEntry = { + canonicalizedBody, + inclusionProof: undefined, + } as sigstore.TransparencyLogEntry; + + it('throws an error', () => { + expect(() => verifyMerkleInclusion(invalidEntry)).toThrow( + VerificationError + ); + }); + }); + + describe('when the inclusion proof log index is greather than the tree size', () => { + const invalidEntry = { + canonicalizedBody, + inclusionProof: { ...inclusionProof, treeSize: '99', logIndex: '100' }, + } as sigstore.TransparencyLogEntry; + + it('throws an error true', () => { + expect(() => verifyMerkleInclusion(invalidEntry)).toThrow( + VerificationError + ); + }); + }); + + describe('when the inclusion proof is missing hashes', () => { + const invalidEntry = { + canonicalizedBody: Buffer.from('foo'), + inclusionProof: { + ...inclusionProof, + hashes: inclusionProof.hashes.slice(0, 1), + }, + } as sigstore.TransparencyLogEntry; + + it('throws an error true', () => { + expect(() => verifyMerkleInclusion(invalidEntry)).toThrow( + VerificationError + ); + }); + }); +}); diff --git a/packages/client/src/__tests__/types/sigstore/index.test.ts b/packages/client/src/__tests__/types/sigstore/index.test.ts index cb98a6c7..c05474fe 100644 --- a/packages/client/src/__tests__/types/sigstore/index.test.ts +++ b/packages/client/src/__tests__/types/sigstore/index.test.ts @@ -13,49 +13,16 @@ 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. */ +import type { Entry } from '../../../external/rekor'; import { SignatureMaterial } from '../../../types/signature'; import * as sigstore from '../../../types/sigstore'; import { encoding as enc, pem } from '../../../util'; import bundles from '../../__fixtures__/bundles/'; -import type { Entry } from '../../../external/rekor'; - -describe('isBundleWithVerificationMaterial', () => { - describe('when the bundle contains verification material', () => { - const json = bundles.dsse.valid.withSigningCert; - const bundle = sigstore.Bundle.fromJSON(json); - - it('returns true', () => { - expect(sigstore.isBundleWithVerificationMaterial(bundle)).toBe(true); - }); - }); - - describe('when the bundle does NOT contain verification material', () => { - const bundle: sigstore.Bundle = { - mediaType: 'application/vnd.dev.cosign.simplesigning.v1+json', - verificationMaterial: undefined, - content: { - $case: 'messageSignature', - messageSignature: { - messageDigest: { - algorithm: sigstore.HashAlgorithm.SHA2_256, - digest: Buffer.from(''), - }, - signature: Buffer.from(''), - }, - }, - }; - - it('returns false', () => { - expect(sigstore.isBundleWithVerificationMaterial(bundle)).toBe(false); - }); - }); -}); - describe('isBundleWithCertificateChain', () => { describe('when the bundle contains a certificate chain', () => { const json = bundles.dsse.valid.withSigningCert; - const bundle = sigstore.Bundle.fromJSON(json); + const bundle = sigstore.bundleFromJSON(json); it('returns true', () => { expect(sigstore.isBundleWithCertificateChain(bundle)).toBe(true); @@ -64,7 +31,7 @@ describe('isBundleWithCertificateChain', () => { describe('when the bundle does NOT contain a certificate chain', () => { const json = bundles.dsse.valid.withPublicKey; - const bundle = sigstore.Bundle.fromJSON(json); + const bundle = sigstore.bundleFromJSON(json); it('returns false', () => { expect(sigstore.isBundleWithCertificateChain(bundle)).toBe(false); @@ -178,11 +145,11 @@ describe('bundle', () => { verification: { signedEntryTimestamp: Buffer.from('set').toString('base64'), inclusionProof: { - hashes: [], - logIndex: 0, - rootHash: '', - treeSize: 0, - checkpoint: '', + hashes: ['deadbeef', 'feedface'], + logIndex: 12345, + rootHash: 'fee1dead', + treeSize: 12346, + checkpoint: 'checkpoint', }, }, } satisfies Entry; @@ -232,9 +199,27 @@ describe('bundle', () => { expect(tlog?.logId?.keyId).toBeTruthy(); expect(tlog?.logId?.keyId.toString('hex')).toEqual(rekorEntry.logID); expect(tlog?.logIndex).toEqual(rekorEntry.logIndex.toString()); - expect(tlog?.inclusionProof).toBeFalsy(); expect(tlog?.kindVersion?.kind).toEqual(entryKind.kind); expect(tlog?.kindVersion?.version).toEqual(entryKind.apiVersion); + expect(tlog?.inclusionProof?.checkpoint?.envelope).toEqual( + rekorEntry.verification.inclusionProof.checkpoint + ); + expect(tlog?.inclusionProof?.hashes).toHaveLength(2); + expect(tlog?.inclusionProof?.hashes[0]).toEqual( + Buffer.from(rekorEntry.verification.inclusionProof.hashes[0], 'hex') + ); + expect(tlog?.inclusionProof?.hashes[1]).toEqual( + Buffer.from(rekorEntry.verification.inclusionProof.hashes[1], 'hex') + ); + expect(tlog?.inclusionProof?.logIndex).toEqual( + rekorEntry.verification.inclusionProof.logIndex.toString() + ); + expect(tlog?.inclusionProof?.rootHash).toEqual( + Buffer.from(rekorEntry.verification.inclusionProof.rootHash, 'hex') + ); + expect(tlog?.inclusionProof?.treeSize).toEqual( + rekorEntry.verification.inclusionProof.treeSize.toString() + ); // Timestamp verification data expect( diff --git a/packages/client/src/__tests__/types/sigstore/serialized.test.ts b/packages/client/src/__tests__/types/sigstore/serialized.test.ts index 64a9fcec..1195623d 100644 --- a/packages/client/src/__tests__/types/sigstore/serialized.test.ts +++ b/packages/client/src/__tests__/types/sigstore/serialized.test.ts @@ -13,11 +13,10 @@ 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. */ -import { - Bundle, +import { Bundle, hashAlgorithmToJSON } from '@sigstore/protobuf-specs'; +import type { Envelope, HashAlgorithm, - hashAlgorithmToJSON, MessageSignature, PublicKeyIdentifier, SerializedBundle, diff --git a/packages/client/src/__tests__/types/sigstore/validate.test.ts b/packages/client/src/__tests__/types/sigstore/validate.test.ts index d4fc5de3..0d14c235 100644 --- a/packages/client/src/__tests__/types/sigstore/validate.test.ts +++ b/packages/client/src/__tests__/types/sigstore/validate.test.ts @@ -14,12 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ import { ValidationError } from '../../../error'; -import { - assertValidBundle, +import { assertValidBundle } from '../../../types/sigstore/validate'; + +import type { Bundle, Signature, X509Certificate, -} from '../../../types/sigstore'; +} from '@sigstore/protobuf-specs'; describe('assertValidBundle', () => { describe('when the bundle is completely empty', () => { diff --git a/packages/client/src/__tests__/x509/cert.test.ts b/packages/client/src/__tests__/x509/cert.test.ts index 29bf23f0..90f51e85 100644 --- a/packages/client/src/__tests__/x509/cert.test.ts +++ b/packages/client/src/__tests__/x509/cert.test.ts @@ -13,7 +13,7 @@ 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. */ -import * as sigstore from '../../types/sigstore'; +import { TransparencyLogInstance } from '@sigstore/protobuf-specs'; import { pem } from '../../util'; import { x509Certificate } from '../../x509/cert'; import { certificates } from '../__fixtures__/certs'; @@ -290,8 +290,8 @@ describe('x509Certificate', () => { logId: { keyId: 'CGCS8ChS/2hF0dFrJ4ScRWcYrBY9wzjSbea8IgY2b3I=' }, }; - const logs: sigstore.TransparencyLogInstance[] = [ - sigstore.TransparencyLogInstance.fromJSON(ctl), + const logs: TransparencyLogInstance[] = [ + TransparencyLogInstance.fromJSON(ctl), ]; describe('when the certificate does NOT have an SCT extension', () => { diff --git a/packages/client/src/__tests__/x509/sct.test.ts b/packages/client/src/__tests__/x509/sct.test.ts index fb52d1e3..f764eeda 100644 --- a/packages/client/src/__tests__/x509/sct.test.ts +++ b/packages/client/src/__tests__/x509/sct.test.ts @@ -13,7 +13,7 @@ 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. */ -import * as sigstore from '../../types/sigstore'; +import { TransparencyLogInstance } from '@sigstore/protobuf-specs'; import { SignedCertificateTimestamp } from '../../x509/sct'; describe('SignedCertificateTimestamp', () => { @@ -130,8 +130,8 @@ describe('SignedCertificateTimestamp', () => { logId: { keyId: Buffer.from(logID, 'hex') }, }; - const logs: sigstore.TransparencyLogInstance[] = [ - sigstore.TransparencyLogInstance.fromJSON(ctl), + const logs: TransparencyLogInstance[] = [ + TransparencyLogInstance.fromJSON(ctl), ]; describe('when the signature is valid', () => { diff --git a/packages/client/src/config.ts b/packages/client/src/config.ts index c76a64ef..b44ed92d 100644 --- a/packages/client/src/config.ts +++ b/packages/client/src/config.ts @@ -68,6 +68,10 @@ export type VerifyOptions = { } & TLogOptions & TUFOptions; +export type CreateVerifierOptions = { + keySelector?: KeySelector; +} & TUFOptions; + export const DEFAULT_FULCIO_URL = 'https://fulcio.sigstore.dev'; export const DEFAULT_REKOR_URL = 'https://rekor.sigstore.dev'; diff --git a/packages/client/src/external/rekor.ts b/packages/client/src/external/rekor.ts index 4e6b2771..06336c7c 100644 --- a/packages/client/src/external/rekor.ts +++ b/packages/client/src/external/rekor.ts @@ -19,22 +19,24 @@ import { checkStatus } from './error'; import type { LogEntry, - ProposedEntry, ProposedDSSEEntry, + ProposedEntry, ProposedHashedRekordEntry, ProposedIntotoEntry, + InclusionProof as RekorInclusionProof, SearchIndex, SearchLogQuery, } from '@sigstore/rekor-types'; import type { FetchOptions } from '../types/fetch'; export type { - ProposedEntry, - SearchIndex, - SearchLogQuery, ProposedDSSEEntry, + ProposedEntry, ProposedHashedRekordEntry, ProposedIntotoEntry, + RekorInclusionProof, + SearchIndex, + SearchLogQuery, }; // The LogEntry type from @sigstore/rekor-types is a Record type diff --git a/packages/client/src/merkle/digest.ts b/packages/client/src/merkle/digest.ts deleted file mode 100644 index 5efc1409..00000000 --- a/packages/client/src/merkle/digest.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* -Copyright 2022 GitHub, Inc - -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. -*/ - -import crypto from 'crypto'; - -const RFC6962LeafHashPrefix = Buffer.from([0x00]); -const RFC6962NodeHashPrefix = Buffer.from([0x01]); - -// Implements Merkle Tree Hash logic according to RFC6962. -// https://datatracker.ietf.org/doc/html/rfc6962#section-2 -export class Hasher { - private algorithm: string; - - constructor(algorithm = 'sha256') { - this.algorithm = algorithm; - } - - public size(): number { - return crypto.createHash(this.algorithm).digest().length; - } - - public hashLeaf(leaf: Buffer): Buffer { - const hasher = crypto.createHash(this.algorithm); - hasher.update(RFC6962LeafHashPrefix); - hasher.update(leaf); - return hasher.digest(); - } - - public hashChildren(l: Buffer, r: Buffer): Buffer { - const hasher = crypto.createHash(this.algorithm); - hasher.update(RFC6962NodeHashPrefix); - hasher.update(l); - hasher.update(r); - return hasher.digest(); - } -} diff --git a/packages/client/src/merkle/verify.ts b/packages/client/src/merkle/verify.ts deleted file mode 100644 index 51f2ed5a..00000000 --- a/packages/client/src/merkle/verify.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { Hasher } from './digest'; -/* -Copyright 2022 GitHub, Inc - -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. -*/ - -// Implementation largely copied from -// https://github.com/transparency-dev/merkle/blob/main/proof/verify.go#L46 - -// Verifies the correctness of the inclusion proof for the given leaf hash -// and index relative to the tree of the given size and root hash. -export function verifyInclusion( - hasher: Hasher, - index: bigint, - size: bigint, - leafHash: Buffer, - proof: Buffer[], - root: Buffer -): boolean { - const calcroot = rootFromInclusionProof(hasher, index, size, leafHash, proof); - return calcroot.equals(root); -} - -// Calculates the expected root hash for a tree of the given size, provided a -// leaf index and hash with corresponding inclusion proof. -function rootFromInclusionProof( - hasher: Hasher, - index: bigint, - size: bigint, - leafHash: Buffer, - proof: Buffer[] -): Buffer { - if (index >= size) { - throw new Error('index exceeds size of tree'); - } - - if (leafHash.length !== hasher.size()) { - throw new Error('leafHash has unexpected size'); - } - - const { inner, border } = decompInclProof(index, size); - if (proof.length != inner + border) { - throw new Error('invalid proof length'); - } - - let hash = chainInner(hasher, leafHash, proof.slice(0, inner), index); - hash = chainBorderRight(hasher, hash, proof.slice(inner)); - return hash; -} - -// Breaks down inclusion proof for a leaf at the specified index in a tree of -// the specified size. The split point is where paths to the index leaf and -// the (size - 1) leaf diverge. Returns lengths of the bottom and upper proof -// parts. -function decompInclProof( - index: bigint, - size: bigint -): { inner: number; border: number } { - const inner = innerProofSize(index, size); - const border = onesCount(index >> BigInt(inner)); - return { inner, border }; -} - -// Computes a subtree hash for an node on or below the tree's right border. -// Assumes the provided proof hashes are ordered from lower to higher levels -// and seed is the initial hash of the node specified by the index. -function chainInner( - hasher: Hasher, - seed: Buffer, - proof: Buffer[], - index: bigint -): Buffer { - return proof.reduce((acc, h, i) => { - if ((index >> BigInt(i)) & BigInt(1)) { - return hasher.hashChildren(h, acc); - } else { - return hasher.hashChildren(acc, h); - } - }, seed); -} - -// Computes a subtree hash for nodes along the tree's right border. -function chainBorderRight( - hasher: Hasher, - seed: Buffer, - proof: Buffer[] -): Buffer { - return proof.reduce((acc, h) => hasher.hashChildren(h, acc), seed); -} - -function innerProofSize(index: bigint, size: bigint): number { - return (index ^ (size - BigInt(1))).toString(2).length; -} - -// Counts the number of ones in the binary representation of the given number. -// https://en.wikipedia.org/wiki/Hamming_weight -function onesCount(x: bigint): number { - return x.toString(2).split('1').length - 1; -} diff --git a/packages/client/src/sigstore-utils.ts b/packages/client/src/sigstore-utils.ts index 045933fe..089bab47 100644 --- a/packages/client/src/sigstore-utils.ts +++ b/packages/client/src/sigstore-utils.ts @@ -65,5 +65,5 @@ export async function createRekorEntry( signature: sigMaterial, tlogEntry: entry, }); - return sigstore.Bundle.toJSON(bundle) as sigstore.SerializedBundle; + return sigstore.bundleToJSON(bundle) as sigstore.SerializedBundle; } diff --git a/packages/client/src/sigstore.ts b/packages/client/src/sigstore.ts index a5b46c56..b3995f3e 100644 --- a/packages/client/src/sigstore.ts +++ b/packages/client/src/sigstore.ts @@ -36,7 +36,7 @@ export async function sign( }); const bundle = await signer.signBlob(payload); - return sigstore.Bundle.toJSON(bundle) as sigstore.SerializedBundle; + return sigstore.bundleToJSON(bundle) as sigstore.SerializedBundle; } export async function attest( @@ -59,7 +59,7 @@ export async function attest( }); const bundle = await signer.signAttestation(payload, payloadType); - return sigstore.Bundle.toJSON(bundle) as sigstore.SerializedBundle; + return sigstore.bundleToJSON(bundle) as sigstore.SerializedBundle; } export async function verify( @@ -81,6 +81,31 @@ export async function verify( return verifier.verify(deserializedBundle, opts, payload); } +export interface BundleVerifier { + verify(bundle: sigstore.SerializedBundle): void; +} + +export async function createVerifier( + options: config.CreateVerifierOptions +): Promise { + const trustedRoot = await tuf.getTrustedRoot({ + mirrorURL: options.tufMirrorURL, + rootPath: options.tufRootPath, + cachePath: options.tufCachePath, + retry: options.retry ?? config.DEFAULT_RETRY, + timeout: options.timeout ?? config.DEFAULT_TIMEOUT, + }); + const verifier = new Verifier(trustedRoot, options.keySelector); + const verifyOpts = config.artifactVerificationOptions(options); + + return { + verify: (bundle: sigstore.SerializedBundle): void => { + const deserializedBundle = sigstore.bundleFromJSON(bundle); + return verifier.verify(deserializedBundle, verifyOpts); + }, + }; +} + const tufUtils = { client: (options: config.TUFOptions = {}): Promise => { return tuf.initTUF({ diff --git a/packages/client/src/tlog/verify/index.ts b/packages/client/src/tlog/verify/index.ts index 2e99ac12..516f265d 100644 --- a/packages/client/src/tlog/verify/index.ts +++ b/packages/client/src/tlog/verify/index.ts @@ -22,7 +22,7 @@ import { verifyTLogSET } from './set'; // Verifies that the number of tlog entries that pass offline verification // is greater than or equal to the threshold specified in the options. export function verifyTLogEntries( - bundle: sigstore.BundleWithVerificationMaterial, + bundle: sigstore.Bundle, trustedRoot: sigstore.TrustedRoot, options: sigstore.ArtifactVerificationOptions_TlogOptions ): void { @@ -31,7 +31,7 @@ export function verifyTLogEntries( } // Extract the signing cert, if available - const signingCert = sigstore.signingCertificate(bundle); + const signingCert = signingCertificate(bundle); // Iterate over the tlog entries and verify each one const verifiedEntries = bundle.verificationMaterial.tlogEntries.filter( @@ -74,3 +74,15 @@ function verifyTLogEntryOffline( verifyTLogIntegrationTime() ); } + +function signingCertificate( + bundle: sigstore.Bundle +): x509Certificate | undefined { + if (!sigstore.isBundleWithCertificateChain(bundle)) { + return undefined; + } + + const signingCert = + bundle.verificationMaterial.content.x509CertificateChain.certificates[0]; + return x509Certificate.parse(signingCert.rawBytes); +} diff --git a/packages/client/src/tlog/verify/merkle.ts b/packages/client/src/tlog/verify/merkle.ts new file mode 100644 index 00000000..d0907488 --- /dev/null +++ b/packages/client/src/tlog/verify/merkle.ts @@ -0,0 +1,128 @@ +/* +Copyright 2023 The Sigstore 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. +*/ +import crypto from 'crypto'; +import { VerificationError } from '../../error'; +import * as sigstore from '../../types/sigstore'; + +const RFC6962_LEAF_HASH_PREFIX = Buffer.from([0x00]); +const RFC6962_NODE_HASH_PREFIX = Buffer.from([0x01]); + +export function verifyMerkleInclusion( + entry: sigstore.TransparencyLogEntry +): boolean { + const inclusionProof = entry.inclusionProof; + + if (!inclusionProof) { + throw new VerificationError('tlog entry has no inclusion proof'); + } + + const logIndex = BigInt(inclusionProof.logIndex); + const treeSize = BigInt(inclusionProof.treeSize); + + if (logIndex < 0n || logIndex >= treeSize) { + throw new VerificationError('invalid inclusion proof index'); + } + + // Figure out which subset of hashes corresponds to the inner and border + // nodes + const { inner, border } = decompInclProof(logIndex, treeSize); + + if (inclusionProof.hashes.length !== inner + border) { + throw new VerificationError('invalid inclusion proof length'); + } + + const innerHashes = inclusionProof.hashes.slice(0, inner); + const borderHashes = inclusionProof.hashes.slice(inner); + + // The entry's hash is the leaf hash + const leafHash = hashLeaf(entry.canonicalizedBody); + + // Chain the hashes belonging to the inner and border portions + const calculatedHash = chainBorderRight( + chainInner(leafHash, innerHashes, logIndex), + borderHashes + ); + + // Calculated hash should match the root hash in the inclusion proof + return bufferEqual(calculatedHash, inclusionProof.rootHash); +} + +// Breaks down inclusion proof for a leaf at the specified index in a tree of +// the specified size. The split point is where paths to the index leaf and +// the (size - 1) leaf diverge. Returns lengths of the bottom and upper proof +// parts. +function decompInclProof( + index: bigint, + size: bigint +): { inner: number; border: number } { + const inner = innerProofSize(index, size); + const border = onesCount(index >> BigInt(inner)); + return { inner, border }; +} + +// Computes a subtree hash for a node on or below the tree's right border. +// Assumes the provided proof hashes are ordered from lower to higher levels +// and seed is the initial hash of the node specified by the index. +function chainInner(seed: Buffer, hashes: Buffer[], index: bigint): Buffer { + return hashes.reduce((acc, h, i) => { + if ((index >> BigInt(i)) & BigInt(1)) { + return hashChildren(h, acc); + } else { + return hashChildren(acc, h); + } + }, seed); +} + +// Computes a subtree hash for nodes along the tree's right border. +function chainBorderRight(seed: Buffer, hashes: Buffer[]): Buffer { + return hashes.reduce((acc, h) => hashChildren(h, acc), seed); +} + +function innerProofSize(index: bigint, size: bigint): number { + return (index ^ (size - BigInt(1))).toString(2).length; +} + +// Counts the number of ones in the binary representation of the given number. +// https://en.wikipedia.org/wiki/Hamming_weight +function onesCount(x: bigint): number { + return x.toString(2).split('1').length - 1; +} + +// Hashing logic according to RFC6962. +// https://datatracker.ietf.org/doc/html/rfc6962#section-2 +function hashChildren(left: Buffer, right: Buffer): Buffer { + const hasher = crypto.createHash('sha256'); + hasher.update(RFC6962_NODE_HASH_PREFIX); + hasher.update(left); + hasher.update(right); + return hasher.digest(); +} + +function hashLeaf(leaf: Buffer): Buffer { + const hasher = crypto.createHash('sha256'); + hasher.update(RFC6962_LEAF_HASH_PREFIX); + hasher.update(leaf); + return hasher.digest(); +} + +function bufferEqual(a: Buffer, b: Buffer): boolean { + try { + return crypto.timingSafeEqual(a, b); + } catch { + /* istanbul ignore next */ + return false; + } +} diff --git a/packages/client/src/types/sigstore/index.ts b/packages/client/src/types/sigstore/index.ts index 111aca78..a148e579 100644 --- a/packages/client/src/types/sigstore/index.ts +++ b/packages/client/src/types/sigstore/index.ts @@ -13,26 +13,59 @@ 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. */ -import { +import { Bundle, HashAlgorithm } from '@sigstore/protobuf-specs'; +import { encoding as enc, pem } from '../../util'; +import { SignatureMaterial } from '../signature'; +import { ValidBundle, assertValidBundle } from './validate'; + +import type { ArtifactVerificationOptions, - Bundle, Envelope, - HashAlgorithm, + InclusionProof, TimestampVerificationData, TransparencyLogEntry, VerificationMaterial, } from '@sigstore/protobuf-specs'; -import { encoding as enc, pem } from '../../util'; -import { x509Certificate } from '../../x509/cert'; -import { WithRequired } from '../utility'; -import { ValidBundle, assertValidBundle } from './validate'; +import type { + Entry, + ProposedEntry, + RekorInclusionProof, +} from '../../external/rekor'; +import type { WithRequired } from '../utility'; +import type { SerializedBundle } from './serialized'; -import type { Entry, ProposedEntry } from '../../external/rekor'; -import type { SignatureMaterial } from '../signature'; - -export * from '@sigstore/protobuf-specs'; -export * from './serialized'; -export * from './validate'; +// Enums from protobuf-specs +// TODO: Move Envelope to "type" export once @sigstore/sign is a thing +export { + Envelope, + HashAlgorithm, + PublicKeyDetails, + SubjectAlternativeNameType, +} from '@sigstore/protobuf-specs'; +// Types from protobuf-specs +export type { + ArtifactVerificationOptions, + ArtifactVerificationOptions_CtlogOptions, + ArtifactVerificationOptions_TlogOptions, + CertificateAuthority, + CertificateIdentities, + CertificateIdentity, + MessageSignature, + ObjectIdentifierValuePair, + PublicKey, + PublicKeyIdentifier, + RFC3161SignedTimestamp, + Signature, + SubjectAlternativeName, + TimestampVerificationData, + TransparencyLogEntry, + TransparencyLogInstance, + TrustedRoot, + X509Certificate, + X509CertificateChain, +} from '@sigstore/protobuf-specs'; +export type { SerializedBundle, SerializedEnvelope } from './serialized'; +export type { ValidBundle as Bundle }; // eslint-disable-next-line @typescript-eslint/no-explicit-any export const bundleFromJSON = (obj: any): ValidBundle => { @@ -41,26 +74,17 @@ export const bundleFromJSON = (obj: any): ValidBundle => { return bundle; }; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const bundleToJSON = (bundle: ValidBundle): SerializedBundle => { + return Bundle.toJSON(bundle) as SerializedBundle; +}; + const BUNDLE_MEDIA_TYPE = 'application/vnd.dev.sigstore.bundle+json;version=0.1'; -// Subset of sigstore.Bundle that has verification material as part -// of the bundle -export type BundleWithVerificationMaterial = WithRequired< - Bundle, - 'verificationMaterial' ->; - -// Type guard for narrowing a Bundle to a BundleWithVerificationMaterial -export function isBundleWithVerificationMaterial( - bundle: Bundle -): bundle is BundleWithVerificationMaterial { - return bundle.verificationMaterial !== undefined; -} - // Subset of sigstore.Bundle that has a certificate chain as part // of the verification material (as opposed to a public key) -export type BundleWithCertificateChain = Bundle & { +export type BundleWithCertificateChain = ValidBundle & { verificationMaterial: VerificationMaterial & { content: Extract< VerificationMaterial['content'], @@ -71,10 +95,9 @@ export type BundleWithCertificateChain = Bundle & { // Type guard for narrowing a Bundle to a BundleWithCertificateChain export function isBundleWithCertificateChain( - bundle: Bundle + bundle: ValidBundle ): bundle is BundleWithCertificateChain { return ( - isBundleWithVerificationMaterial(bundle) && bundle.verificationMaterial.content !== undefined && bundle.verificationMaterial.content.$case === 'x509CertificateChain' ); @@ -122,6 +145,9 @@ export function isVerifiableTransparencyLogEntry( ); } +// All of the following functions are used to construct a ValidBundle +// from various types of input. When this code moves into the +// @sigstore/sign package, these functions will be exported from there. export function toDSSEBundle({ envelope, signature, @@ -132,7 +158,7 @@ export function toDSSEBundle({ signature: SignatureMaterial; tlogEntry?: Entry; timestamp?: Buffer; -}): Bundle { +}): ValidBundle { return { mediaType: BUNDLE_MEDIA_TYPE, content: { $case: 'dsseEnvelope', dsseEnvelope: envelope }, @@ -154,7 +180,7 @@ export function toMessageSignatureBundle({ signature: SignatureMaterial; tlogEntry?: Entry; timestamp?: Buffer; -}): Bundle { +}): ValidBundle { return { mediaType: BUNDLE_MEDIA_TYPE, content: { @@ -179,6 +205,9 @@ function toTransparencyLogEntry(entry: Entry): TransparencyLogEntry { const b64SET = entry.verification?.signedEntryTimestamp || ''; const set = Buffer.from(b64SET, 'base64'); const logID = Buffer.from(entry.logID, 'hex'); + const proof = entry.verification?.inclusionProof + ? toInclusionProof(entry.verification.inclusionProof) + : undefined; // Parse entry body so we can extract the kind and version. const bodyJSON = enc.base64Decode(entry.body); @@ -197,11 +226,23 @@ function toTransparencyLogEntry(entry: Entry): TransparencyLogEntry { kind: entryBody.kind, version: entryBody.apiVersion, }, - inclusionProof: undefined, + inclusionProof: proof, canonicalizedBody: Buffer.from(entry.body, 'base64'), }; } +function toInclusionProof(proof: RekorInclusionProof): InclusionProof { + return { + logIndex: proof.logIndex.toString(), + rootHash: Buffer.from(proof.rootHash, 'hex'), + treeSize: proof.treeSize.toString(), + checkpoint: { + envelope: proof.checkpoint, + }, + hashes: proof.hashes.map((h) => Buffer.from(h, 'hex')), + }; +} + function toVerificationMaterial({ signature, tlogEntry, @@ -210,7 +251,7 @@ function toVerificationMaterial({ signature: SignatureMaterial; tlogEntry?: Entry; timestamp?: Buffer; -}): VerificationMaterial { +}): ValidBundle['verificationMaterial'] { return { content: signature.certificates ? toVerificationMaterialx509CertificateChain(signature.certificates) @@ -224,7 +265,7 @@ function toVerificationMaterial({ function toVerificationMaterialx509CertificateChain( certificates: string[] -): VerificationMaterial['content'] { +): ValidBundle['verificationMaterial']['content'] { return { $case: 'x509CertificateChain', x509CertificateChain: { @@ -237,7 +278,7 @@ function toVerificationMaterialx509CertificateChain( function toVerificationMaterialPublicKey( hint: string -): VerificationMaterial['content'] { +): ValidBundle['verificationMaterial']['content'] { return { $case: 'publicKey', publicKey: { hint } }; } @@ -248,15 +289,3 @@ function toTimestampVerificationData( rfc3161Timestamps: [{ signedTimestamp: timestamp }], }; } - -export function signingCertificate( - bundle: Bundle -): x509Certificate | undefined { - if (!isBundleWithCertificateChain(bundle)) { - return undefined; - } - - const signingCert = - bundle.verificationMaterial.content.x509CertificateChain.certificates[0]; - return x509Certificate.parse(signingCert.rawBytes); -} diff --git a/packages/client/src/types/sigstore/serialized.ts b/packages/client/src/types/sigstore/serialized.ts index 8e976f94..167e13cc 100644 --- a/packages/client/src/types/sigstore/serialized.ts +++ b/packages/client/src/types/sigstore/serialized.ts @@ -67,6 +67,9 @@ type SerializedDSSEEnvelope = { }[]; }; +// Serialized form of the DSSE Envelope +export type { SerializedDSSEEnvelope as SerializedEnvelope }; + // Serialized form of the Sigstore Bundle union type with all possible options // represented export type SerializedBundle = { @@ -85,15 +88,3 @@ export type SerializedBundle = { dsseEnvelope: SerializedDSSEEnvelope; messageSignature: SerializedMessageSignature; }>; - -interface SerializedSignature { - sig: string; - keyid: string; -} - -// Serialized form of the DSSE Envelope -export type SerializedEnvelope = { - payload: string; - payloadType: string; - signatures: SerializedSignature[]; -}; diff --git a/packages/client/src/types/sigstore/validate.ts b/packages/client/src/types/sigstore/validate.ts index 31d4fd59..b83962c7 100644 --- a/packages/client/src/types/sigstore/validate.ts +++ b/packages/client/src/types/sigstore/validate.ts @@ -13,15 +13,19 @@ 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. */ -import { +import { ValidationError } from '../../error'; +import { WithRequired } from '../utility'; + +import type { Bundle, MessageSignature, VerificationMaterial, } from '@sigstore/protobuf-specs'; -import { ValidationError } from '../../error'; -import { WithRequired } from '../utility'; -// Sigstore bundle with all required fields populated +// Sigstore bundle with all required fields populated. +// This is the version of Bundle which should be used for all internal +// functions. Any Bundle which is passed to an internal function should be +// validated with assertValidBundle and cast to ValidBundle. export type ValidBundle = Bundle & { verificationMaterial: VerificationMaterial & { content: NonNullable; diff --git a/packages/client/src/verify.ts b/packages/client/src/verify.ts index 70643f63..6e65a76f 100644 --- a/packages/client/src/verify.ts +++ b/packages/client/src/verify.ts @@ -35,7 +35,7 @@ export class Verifier { // Verifies the bundle signature, the bundle's certificate chain (if present) // and the bundle's transparency log entries. public verify( - bundle: sigstore.ValidBundle, + bundle: sigstore.Bundle, options: sigstore.RequiredArtifactVerificationOptions, data?: Buffer ): void { @@ -53,7 +53,7 @@ export class Verifier { // Performs bundle signature verification. Determines the type of the bundle // content and delegates to the appropriate signature verification function. private verifyArtifactSignature( - bundle: sigstore.ValidBundle, + bundle: sigstore.Bundle, data?: Buffer ): void { const publicKey = this.getPublicKey(bundle); @@ -99,7 +99,7 @@ export class Verifier { // Performs verification of the bundle's transparency log entries. The bundle // must contain a list of transparency log entries. private verifyTLogEntries( - bundle: sigstore.ValidBundle, + bundle: sigstore.Bundle, options: sigstore.RequiredArtifactVerificationOptions ): void { tlog.verifyTLogEntries(bundle, this.trustedRoot, options.tlogOptions); @@ -108,7 +108,7 @@ export class Verifier { // Returns the public key which will be used to verify the bundle signature. // The public key is selected based on the verification material in the bundle // and the options provided. - private getPublicKey(bundle: sigstore.ValidBundle): KeyLike { + private getPublicKey(bundle: sigstore.Bundle): KeyLike { // Select the key which will be used to verify the signature switch (bundle.verificationMaterial?.content?.$case) { // If the bundle contains a certificate chain, the public key is the diff --git a/packages/client/store/public-good-instance-root.json b/packages/client/store/public-good-instance-root.json deleted file mode 100644 index e95c7e88..00000000 --- a/packages/client/store/public-good-instance-root.json +++ /dev/null @@ -1 +0,0 @@ -{"signed":{"_type":"root","spec_version":"1.0","version":7,"expires":"2023-10-04T13:08:11Z","keys":{"25a0eb450fd3ee2bd79218c963dce3f1cc6118badf251bf149f0bd07d5cabe99":{"keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEXsz3SZXFb8jMV42j6pJlyjbjR8K\nN3Bwocexq6LMIb5qsWKOQvLN16NUefLc4HswOoumRsVVaajSpQS6fobkRw==\n-----END PUBLIC KEY-----\n"}},"2e61cd0cbf4a8f45809bda9f7f78c0d33ad11842ff94ae340873e2664dc843de":{"keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0ghrh92Lw1Yr3idGV5WqCtMDB8Cx\n+D8hdC4w2ZLNIplVRoVGLskYa3gheMyOjiJ8kPi15aQ2//7P+oj7UvJPGw==\n-----END PUBLIC KEY-----\n"}},"45b283825eb184cabd582eb17b74fc8ed404f68cf452acabdad2ed6f90ce216b":{"keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELrWvNt94v4R085ELeeCMxHp7PldF\n0/T1GxukUh2ODuggLGJE0pc1e8CSBf6CS91Fwo9FUOuRsjBUld+VqSyCdQ==\n-----END PUBLIC KEY-----\n"}},"7f7513b25429a64473e10ce3ad2f3da372bbdd14b65d07bbaf547e7c8bbbe62b":{"keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEinikSsAQmYkNeH5eYq/CnIzLaacO\nxlSaawQDOwqKy/tCqxq5xxPSJc21K4WIhs9GyOkKfzueY3GILzcMJZ4cWw==\n-----END PUBLIC KEY-----\n"}},"e1863ba02070322ebc626dcecf9d881a3a38c35c3b41a83765b6ad6c37eaec2a":{"keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWRiGr5+j+3J5SsH+Ztr5nE2H2wO7\nBV+nO3s93gLca18qTOzHY1oWyAGDykMSsGTUBSt9D+An0KfKsD2mfSM42Q==\n-----END PUBLIC KEY-----\n"}},"f5312f542c21273d9485a49394386c4575804770667f2ddb59b3bf0669fddd2f":{"keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEzBzVOmHCPojMVLSI364WiiV8NPrD\n6IgRxVliskz/v+y3JER5mcVGcONliDcWMC5J2lfHmjPNPhb4H7xm8LzfSA==\n-----END PUBLIC KEY-----\n"}},"ff51e17fcf253119b7033f6f57512631da4a0969442afcf9fc8b141c7f2be99c":{"keytype":"ecdsa-sha2-nistp256","scheme":"ecdsa-sha2-nistp256","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEy8XKsmhBYDI8Jc0GwzBxeKax0cm5\nSTKEU65HPFunUn41sT8pi0FjM4IkHz/YUmwmLUO0Wt7lxhj6BkLIK4qYAw==\n-----END PUBLIC KEY-----\n"}}},"roles":{"root":{"keyids":["ff51e17fcf253119b7033f6f57512631da4a0969442afcf9fc8b141c7f2be99c","25a0eb450fd3ee2bd79218c963dce3f1cc6118badf251bf149f0bd07d5cabe99","f5312f542c21273d9485a49394386c4575804770667f2ddb59b3bf0669fddd2f","7f7513b25429a64473e10ce3ad2f3da372bbdd14b65d07bbaf547e7c8bbbe62b","2e61cd0cbf4a8f45809bda9f7f78c0d33ad11842ff94ae340873e2664dc843de"],"threshold":3},"snapshot":{"keyids":["45b283825eb184cabd582eb17b74fc8ed404f68cf452acabdad2ed6f90ce216b"],"threshold":1},"targets":{"keyids":["ff51e17fcf253119b7033f6f57512631da4a0969442afcf9fc8b141c7f2be99c","25a0eb450fd3ee2bd79218c963dce3f1cc6118badf251bf149f0bd07d5cabe99","f5312f542c21273d9485a49394386c4575804770667f2ddb59b3bf0669fddd2f","7f7513b25429a64473e10ce3ad2f3da372bbdd14b65d07bbaf547e7c8bbbe62b","2e61cd0cbf4a8f45809bda9f7f78c0d33ad11842ff94ae340873e2664dc843de"],"threshold":3},"timestamp":{"keyids":["e1863ba02070322ebc626dcecf9d881a3a38c35c3b41a83765b6ad6c37eaec2a"],"threshold":1}},"consistent_snapshot":true},"signatures":[{"keyid":"25a0eb450fd3ee2bd79218c963dce3f1cc6118badf251bf149f0bd07d5cabe99","sig":"3046022100c0610c0055ce5c4a52d054d7322e7b514d55baf44423d63aa4daa077cc60fd1f022100a097f2803f090fb66c42ead915a2c46ebe7db53a32bf18f2188275cc936f8bdd"},{"keyid":"f5312f542c21273d9485a49394386c4575804770667f2ddb59b3bf0669fddd2f","sig":"304502203134f0468810299d5493a867c40630b341296b92e59c29821311d353343bb3a4022100e667ae3d304e7e3da0894c7425f6b9ecd917106841280e5cf6f3496ad5f8f68e"},{"keyid":"7f7513b25429a64473e10ce3ad2f3da372bbdd14b65d07bbaf547e7c8bbbe62b","sig":"3045022037fe5f45426f21eaaf4730d2136f2b1611d6379688f79b9d1e3f61719997135c022100b63b022d7b79d4694b96f416d88aa4d7b1a3bff8a01f4fb51e0f42137c7d2d06"},{"keyid":"2e61cd0cbf4a8f45809bda9f7f78c0d33ad11842ff94ae340873e2664dc843de","sig":"3044022007cc8fcc4940809f2751ad5b535f4c5f53f5b4952f5b5696b09668e743306ac1022006dfcdf94e94c92163eeb1b47796db62cedaa730aa13aa61b573fe23714730f2"}]} diff --git a/packages/client/tsconfig.json b/packages/client/tsconfig.json index 9f3f2bb5..e0c96ba7 100644 --- a/packages/client/tsconfig.json +++ b/packages/client/tsconfig.json @@ -13,6 +13,6 @@ "references": [ { "path": "../tuf" }, { "path": "../rekor-types" }, - { "path": "../jest-types" } + { "path": "../jest" } ] } diff --git a/packages/jest/LICENSE b/packages/jest/LICENSE new file mode 100644 index 00000000..e9e7c167 --- /dev/null +++ b/packages/jest/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 The Sigstore 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. diff --git a/packages/jest/README.md b/packages/jest/README.md new file mode 100644 index 00000000..2541f5e9 --- /dev/null +++ b/packages/jest/README.md @@ -0,0 +1,40 @@ +# @sigstore/jest + +Custom Jest matchers used across the different Sigstore JavaScript projects. +This is a private package and is not published to the registry. + +## Installation + +``` +npm install --save-dev @sigstore/jest +``` + +Installing this package will also install the `@types/sigstore-jest-extended` +package which gives you access to the TypeScript types for the custom matchers. + +## Setup + +To install specific matchers, create a Jest setup file (`jest.setup.ts`) with +the following: + +```typescript +import { toThrowWithCode } from '@sigstore/jest'; +expect.extend({ toThrowWithCode }); +``` + +To automatically extend `expect` will all matchers you can add the following to +the `setupFilesAfterEnv` property in the `jest.config.js` file: + +```javascript +module.exports = { + setupFilesAfterEnv: ['@sigstore/jest/all'], +}; +``` + +or in the `package.json`: + +```json +"jest": { + "setupFilesAfterEnv": ["@sigtore/jest/all"] +} +``` diff --git a/packages/jest/all.js b/packages/jest/all.js new file mode 100644 index 00000000..5e886ae6 --- /dev/null +++ b/packages/jest/all.js @@ -0,0 +1,16 @@ +/* +Copyright 2023 The Sigstore 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. +*/ +require('./dist/all'); diff --git a/packages/jest/package.json b/packages/jest/package.json new file mode 100644 index 00000000..720598ec --- /dev/null +++ b/packages/jest/package.json @@ -0,0 +1,27 @@ +{ + "name": "@sigstore/jest", + "version": "0.0.0", + "private": "true", + "description": "Custom Jest matchers for Sigstore libraries", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "clean": "shx rm -rf dist *.tsbuildinfo", + "build": "tsc --build" + }, + "files": [ + "dist" + ], + "author": "bdehamer@github.com", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "git+https://github.com/sigstore/sigstore-js.git" + }, + "dependencies": { + "@types/sigstore-jest-extended": "^0.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } +} diff --git a/packages/jest/src/all/index.ts b/packages/jest/src/all/index.ts new file mode 100644 index 00000000..ef407aac --- /dev/null +++ b/packages/jest/src/all/index.ts @@ -0,0 +1,28 @@ +/* +Copyright 2023 The Sigstore 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. +*/ +import * as matchers from '../matchers'; + +/* eslint-disable @typescript-eslint/no-explicit-any */ +const jestExpect = (global as any).expect; + +if (jestExpect !== undefined) { + jestExpect.extend(matchers); +} else { + throw new Error( + "Unable to find Jest's global expect. " + + 'Please check you have added @sigstore/jest correctly to your jest configuration.' + ); +} diff --git a/packages/client/src/merkle/index.ts b/packages/jest/src/index.ts similarity index 83% rename from packages/client/src/merkle/index.ts rename to packages/jest/src/index.ts index f97e41f8..f5961176 100644 --- a/packages/client/src/merkle/index.ts +++ b/packages/jest/src/index.ts @@ -1,5 +1,5 @@ /* -Copyright 2022 GitHub, Inc +Copyright 2023 The Sigstore Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -13,6 +13,4 @@ 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. */ - -export { Hasher } from './digest'; -export { verifyInclusion } from './verify'; +export * from './matchers'; diff --git a/packages/jest/src/matchers/index.ts b/packages/jest/src/matchers/index.ts new file mode 100644 index 00000000..9f422013 --- /dev/null +++ b/packages/jest/src/matchers/index.ts @@ -0,0 +1,16 @@ +/* +Copyright 2023 The Sigstore 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. +*/ +export { toThrowWithCode } from './toThrowWithCode'; diff --git a/packages/jest/src/matchers/toThrowWithCode.ts b/packages/jest/src/matchers/toThrowWithCode.ts new file mode 100644 index 00000000..250a4286 --- /dev/null +++ b/packages/jest/src/matchers/toThrowWithCode.ts @@ -0,0 +1,76 @@ +/* +Copyright 2023 The Sigstore 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. +*/ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +const result = (pass: boolean, msg: string) => ({ pass, message: () => msg }); +const pass = (msg: string) => result(true, msg); +const fail = (msg: string) => result(false, msg); + +// Matcher for checking that a function throws an error of a specific type +// with a specific `code` property +export function toThrowWithCode( + this: any, + received: any, + type: any, + code: string +) { + const isFromReject = this && this.promise === 'rejects'; + + // Must be called with either a rejected promise, or a function to be + // invoked + if ((!received || typeof received !== 'function') && !isFromReject) { + return fail(`Excpected ${received} to be a function`); + } + + // Type must be some kind of class (e.g. Error) + if (!type || typeof type !== 'function') { + return fail(`Type argument must be a function, received ${type}`); + } + + if (typeof code !== 'string') { + return fail(`Code argument must be a string, received ${code}`); + } + + // Gather the error, either from the rejected promise or by invoking the + // supplied function + let error: (object & { code?: string; name?: string }) | null = null; + if (isFromReject) { + error = received; + } else { + try { + received(); + } catch (e) { + error = e as object; + } + } + + if (!error) { + return fail(`Received function did not throw`); + } + + if (!(error instanceof type)) { + return fail( + `Expected function to throw ${type.name}, but got ${error.name}` + ); + } + + if (error.code !== code) { + return fail( + `Expected error to have code "${code}", but got "${error.code}"` + ); + } + return pass(`Expected function to throw ${type.name} with code ${code}`); +} diff --git a/packages/jest/tsconfig.json b/packages/jest/tsconfig.json new file mode 100644 index 00000000..8f6a6eae --- /dev/null +++ b/packages/jest/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "dist", + "composite": true + }, + "exclude": [ + "./dist" + ], + "references": [ + { "path": "../jest-types" } + ] +} diff --git a/packages/mock/CHANGELOG.md b/packages/mock/CHANGELOG.md new file mode 100644 index 00000000..7361b72b --- /dev/null +++ b/packages/mock/CHANGELOG.md @@ -0,0 +1,11 @@ +# @sigstore/mock + +## 0.1.0 + +### Minor Changes + +- 3681515: Initial release + +### Patch Changes + +- 470e1da: Bump pkijs from 3.0.14 to 3.0.15 diff --git a/packages/mock/LICENSE b/packages/mock/LICENSE new file mode 100644 index 00000000..e9e7c167 --- /dev/null +++ b/packages/mock/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 The Sigstore 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. diff --git a/packages/mock/README.md b/packages/mock/README.md new file mode 100644 index 00000000..ec159fa8 --- /dev/null +++ b/packages/mock/README.md @@ -0,0 +1,79 @@ +# @sigstore/mock · [![npm version](https://img.shields.io/npm/v/@sigstore/mock.svg?style=flat)](https://www.npmjs.com/package/@sigstore/mock) [![CI Status](https://github.com/sigstore/sigstore-js/workflows/CI/badge.svg)](https://github.com/sigstore/sigstore-js/actions/workflows/ci.yml) [![Smoke Test Status](https://github.com/sigstore/sigstore-js/workflows/smoke-test/badge.svg)](https://github.com/sigstore/sigstore-js/actions/workflows/smoke-test.yml) + +Builds on top of the [`nock`][1] library to set-up mock endpoints for Sigstore +services. + +## Features + +* Mocked version of the Sigstore Fulcio `POST /api/v2/signingCert` API which + returns a verifiable certificate signed by an ephemeral certificate authority. +* Mocked version of the Sigstore Rekor `POST /api/v1/log/entries` API which + returns a log entry with a verifiable signed-entry timestamp (SET). +* Mocked version of the Sigstore Timestamp Authority `POST /api/v1/timestamp` + API which returns a verifiable signed timestamp. + +## To Do + +* Mocked TUF repository which returns the key material necessary to + verify artifacts returned from the other services. + +## Prerequisites + +- Node.js version >= 14.17.0 + +## Installation + +``` +npm install @sigstore/mock +``` + +## Usage + +```javascript +const { mockFulcio, mockRekor, mockTSA } = require('@sigstore/mock') +``` + +```javascript +import { mockFulcio, mockRekor, mockTSA } from '@sigstore/mock' +``` + +### mockFulcio([options]) +Sets-up a `nock`-based mock endpoint for the Fulcio `POST /api/v2/signingCert` API. + +* `options` `` + * `baseURL` ``: Base URL for mocked Fulcio API server. Defaults to + `'https://fulcio.sigstore.dev'` + * `strict` ``: Flag indicating whether or not the request payload + will be parsed. When set to `true` the request must contain a well-formed + OIDC token and a well-formed public key. The OIDC token does NOT need to be + signed or contain a verifiable signature. The supplied public key will be + part of the returned certificate. When set to `false` the request body will + not be interpreted and a dummy OIDC token and key will be used to provision + the certificate. Defaults to `true`. + +### mockRekor([options]) +Sets-up a `nock`-based mock endpoint for the Rekor `POST /api/v1/log/entries` API. + +* `options` `` + * `baseURL` ``: Base URL for mocked Rekor API server. Defaults to + `'https://rekor.sigstore.dev'` + * `strict` ``: Flag indicating whether or not the request payload + will be parsed. When set to `true` the request must contain a well-formed + JSON string. The supplied JSON object will be embedded in the returned + log entry. When set to `false` the request body will not be interpreted + and a dummy proposed entry be used. Defaults to `true`. + +### mockTSA([options]) +Sets-up a `nock`-based mock endpoint for the Timestamp Authority `POST /api/v1/timestamp` API. + +* `options` `` + * `baseURL` ``: Base URL for mocked TSA API server. Defaults to + `'https://timestamp.sigstore.dev'` + * `strict` ``: Flag indicating whether or not the request payload + will be parsed. When set to `true` the request must contain a well-formed + JSON string. The supplied JSON object will be used to set the artifact hash + and hash algorithm in the returned timestamp. When set to `false` the + request body will not be interpreted and a dummy artifact hash will be + used. Defaults to `true`. + +[1]: https://github.com/nock/nock diff --git a/packages/mock/jest.config.js b/packages/mock/jest.config.js new file mode 100644 index 00000000..ee41554c --- /dev/null +++ b/packages/mock/jest.config.js @@ -0,0 +1,22 @@ +/* +Copyright 2022 The Sigstore 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. +*/ +const base = require('../../jest.config.base') + +module.exports = { + ...base, + displayName: 'mock', + testPathIgnorePatterns: ['/dist/'], +}; diff --git a/packages/mock/package.json b/packages/mock/package.json new file mode 100644 index 00000000..cbeca087 --- /dev/null +++ b/packages/mock/package.json @@ -0,0 +1,48 @@ +{ + "name": "@sigstore/mock", + "version": "0.1.0", + "description": "Mocked version of the Sigstore services", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "clean": "shx rm -rf dist *.tsbuildinfo", + "build": "tsc --build", + "test": "jest" + }, + "files": [ + "dist" + ], + "author": "bdehamer@github.com", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "git+https://github.com/sigstore/sigstore-js.git" + }, + "bugs": { + "url": "https://github.com/sigstore/sigstore-js/issues" + }, + "homepage": "https://github.com/sigstore/sigstore-js/tree/main/packages/mock#readme", + "publishConfig": { + "provenance": true + }, + "devDependencies": { + "@sigstore/rekor-types": "^0.0.3", + "make-fetch-happen": "^11.0.1" + }, + "dependencies": { + "@peculiar/webcrypto": "^1.4.3", + "@peculiar/x509": "^1.9.3", + "@sigstore/protobuf-specs": "^0.1.0", + "@tufjs/repo-mock": "^1.1.0", + "asn1js": "^3.0.5", + "bytestreamjs": "^2.0.1", + "canonicalize": "^2.0.0", + "jose": "^4.14.4", + "nock": "^13.3.1", + "pkijs": "^3.0.15", + "pvtsutils": "^1.3.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } +} diff --git a/packages/mock/src/constants.ts b/packages/mock/src/constants.ts new file mode 100644 index 00000000..1b4431c7 --- /dev/null +++ b/packages/mock/src/constants.ts @@ -0,0 +1,27 @@ +/* +Copyright 2023 The Sigstore 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. +*/ +export const DIGEST_SHA256 = 'SHA-256'; + +export const KEY_ALGORITHM_ECDSA_P256 = { name: 'ECDSA', namedCurve: 'P-256' }; +export const KEY_ALGORITHM_ECDSA_P384 = { name: 'ECDSA', namedCurve: 'P-384' }; +export const SIGNING_ALGORITHM_ECDSA_SHA256 = { + name: 'ECDSA', + hash: 'SHA-256', +}; +export const SIGNING_ALGORITHM_ECDSA_SHA384 = { + name: 'ECDSA', + hash: 'SHA-384', +}; diff --git a/packages/mock/src/fulcio/ca.test.ts b/packages/mock/src/fulcio/ca.test.ts new file mode 100644 index 00000000..244bdbfe --- /dev/null +++ b/packages/mock/src/fulcio/ca.test.ts @@ -0,0 +1,198 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import { Crypto } from '@peculiar/webcrypto'; +import { generateKeyPairSync } from 'crypto'; +import * as pkijs from 'pkijs'; +import { initializeCA } from './ca'; +import { initializeCTLog } from './ctlog'; + +describe('CA', () => { + const crypto = new pkijs.CryptoEngine({ crypto: new Crypto() }); + + beforeEach(() => { + pkijs.setEngine('test', crypto); + }); + + const extension = { + oid: '1.3.6.1.4.1.57264.1.20', + value: 'workflow_dispatch', + }; + + const subjectAltName = 'testsan'; + + describe('#rootCertificate', () => { + it('returns the root certificate', async () => { + const ca = await initializeCA(); + const root = ca.rootCertificate; + + const cert = pkijs.Certificate.fromBER(root); + expect(cert.issuer.typesAndValues[0].value.valueBlock.value).toBe( + 'sigstore' + ); + expect(cert.issuer.typesAndValues[1].value.valueBlock.value).toBe( + 'sigstore.mock' + ); + }); + }); + + describe('#issueCertificate', () => { + const { publicKey } = generateKeyPairSync('ec', { + namedCurve: 'P-256', + }); + + const keyBytes = publicKey.export({ format: 'der', type: 'spki' }); + + describe('when no CT log is provided', () => { + it('issues a cert', async () => { + const ca = await initializeCA(); + + // Issue a certificate with the key above + const signingCert = await ca.issueCertificate({ + publicKey: keyBytes, + subjectAltName, + }); + expect(signingCert).toBeDefined(); + + const cert = pkijs.Certificate.fromBER(signingCert); + expect(cert.issuer.typesAndValues[0].value.valueBlock.value).toBe( + 'sigstore' + ); + expect(cert.issuer.typesAndValues[1].value.valueBlock.value).toBe( + 'sigstore.mock' + ); + }); + + it('issue a cert with the correct key', async () => { + const ca = await initializeCA(); + + // Issue a certificate with the key above + const signingCert = await ca.issueCertificate({ + publicKey: keyBytes, + subjectAltName, + }); + + // Check that the key is correct + const cert = pkijs.Certificate.fromBER(signingCert); + const certKey = await cert.getPublicKey(); + const cerKeyBuf = await crypto.exportKey('spki', certKey); + expect(Buffer.from(cerKeyBuf).toString('base64')).toBe( + keyBytes.toString('base64') + ); + }); + + it('issue a cert with the correct SAN', async () => { + const ca = await initializeCA(); + + // Issue a certificate with the key above + const signingCert = await ca.issueCertificate({ + publicKey: keyBytes, + subjectAltName, + }); + + // Check that the key is correct + const cert = pkijs.Certificate.fromBER(signingCert); + + expect.assertions(1); + cert.extensions!.forEach((ext) => { + if (ext.extnID === pkijs.id_SubjectAltName) { + expect(ext.parsedValue.altNames[0].value).toBe(subjectAltName); + } + }); + }); + + it('issue a cert chained back to the root cert', async () => { + const ca = await initializeCA(); + + // Issue a certificate with the key above + const signingCert = await ca.issueCertificate({ + publicKey: keyBytes, + subjectAltName: 'test', + }); + + const leaf = pkijs.Certificate.fromBER(signingCert); + const root = pkijs.Certificate.fromBER(ca.rootCertificate); + + const ccve = new pkijs.CertificateChainValidationEngine({ + trustedCerts: [root], + certs: [leaf], + checkDate: new Date(), + }); + + const result = await ccve.verify({}, crypto); + expect(result.result).toBe(true); + expect(result.certificatePath).toHaveLength(2); + }); + }); + + describe('when a custom extension is provided', () => { + it('issues a cert with the extension', async () => { + const ca = await initializeCA(); + + // Issue a certificate with the key above + const signingCert = await ca.issueCertificate({ + publicKey: keyBytes, + subjectAltName: 'test', + extensions: [extension], + }); + + const cert = pkijs.Certificate.fromBER(signingCert); + + expect.assertions(1); + cert.extensions!.forEach((ext) => { + if (ext.extnID === extension.oid) { + expect(ext.parsedValue.valueBlock.value).toBe(extension.value); + } + }); + }); + }); + + describe('when a CT log is provided', () => { + it('issues a cert with a verifiable SCT', async () => { + const ctLog = await initializeCTLog(); + const ca = await initializeCA(ctLog); + + // Issue a certificate with the key above + const signingCert = await ca.issueCertificate({ + publicKey: keyBytes, + subjectAltName: 'test', + }); + + // Verification material + const root = ca.rootCertificate; + const ctLogList = [ + { + log_id: ctLog.logID.toString('base64'), + key: ctLog.publicKey.toString('base64'), + }, + ]; + + const cert = pkijs.Certificate.fromBER(signingCert); + // Verify the SCT on the issued certificate + const result = await pkijs.verifySCTsForCertificate( + cert, + pkijs.Certificate.fromBER(root), + ctLogList, + 0, + crypto + ); + expect(result).toHaveLength(1); + expect(result[0]).toBe(true); + }); + }); + }); +}); diff --git a/packages/mock/src/fulcio/ca.ts b/packages/mock/src/fulcio/ca.ts new file mode 100644 index 00000000..1850bad3 --- /dev/null +++ b/packages/mock/src/fulcio/ca.ts @@ -0,0 +1,182 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +import { Crypto } from '@peculiar/webcrypto'; +import x509 from '@peculiar/x509'; +import * as asn1js from 'asn1js'; +import { + DIGEST_SHA256, + KEY_ALGORITHM_ECDSA_P256, + KEY_ALGORITHM_ECDSA_P384, + SIGNING_ALGORITHM_ECDSA_SHA384, +} from '../constants'; +import { createRootCertificate } from '../util/root-cert'; +import type { CTLog } from './ctlog'; + +const ISSUER = 'CN=sigstore,O=sigstore.mock'; + +const OID_SIGNED_CERTIFICATE_TIMESTAMP_LIST = '1.3.6.1.4.1.11129.2.4.2'; + +const MS_PER_MINUTE = 1000 * 60; + +export interface CA { + rootCertificate: Buffer; + issueCertificate: (options: CertificateRequestOptions) => Promise; +} + +export interface CertificateRequestOptions { + publicKey: Buffer; + subjectAltName: string; + extensions?: ExtensionValue[]; +} + +interface ExtensionValue { + oid: string; + value: string; +} + +// Initialize the mock CA. Starts by generating a root key pair and self-signed +// certificate. The root certificate is used to sign any certificates issued by +// the #issueCertificate method. Doing this work in a function allows us to +// work around the fact that some of these operations are async and can't be +// done in the constructor. +export async function initializeCA(ctLog?: CTLog): Promise { + const root = await createRootCertificate( + ISSUER, + KEY_ALGORITHM_ECDSA_P384, + SIGNING_ALGORITHM_ECDSA_SHA384 + ); + + return new CAImpl({ + keyPair: root.keyPair, + rootCertificate: root.cert, + ctLog, + }); +} + +class CAImpl implements CA { + private root: x509.X509Certificate; + private keyPair: CryptoKeyPair; + private ctLog?: CTLog; + private crypto: Crypto; + + constructor(options: { + rootCertificate: x509.X509Certificate; + keyPair: CryptoKeyPair; + ctLog?: CTLog; + }) { + this.root = options.rootCertificate; + this.ctLog = options.ctLog; + this.keyPair = options.keyPair; + this.crypto = new Crypto(); + } + + public get rootCertificate(): Buffer { + return Buffer.from(this.root.rawData); + } + + public async issueCertificate( + opts: CertificateRequestOptions + ): Promise { + // convert key to CryptoKey + const key = await this.crypto.subtle.importKey( + 'spki', + opts.publicKey, + KEY_ALGORITHM_ECDSA_P256, + true, + ['sign', 'verify'] + ); + + // https://github.com/sigstore/fulcio/blob/549813ca04ae02b4a19181817a90a66c2a00960c/pkg/ca/common.go#L29 + const tbs = { + serialNumber: '11182004', + notBefore: new Date(), + notAfter: new Date(Date.now() + 10 * MS_PER_MINUTE), + issuer: ISSUER, + publicKey: key, + signingAlgorithm: SIGNING_ALGORITHM_ECDSA_SHA384, + signingKey: this.keyPair.privateKey, + extensions: [ + new x509.KeyUsagesExtension(x509.KeyUsageFlags.digitalSignature, true), + new x509.ExtendedKeyUsageExtension([x509.ExtendedKeyUsage.codeSigning]), + new x509.SubjectAlternativeNameExtension( + [{ type: 'url', value: opts.subjectAltName }], + true + ), + await x509.SubjectKeyIdentifierExtension.create( + key, + false, + this.crypto + ), + await x509.AuthorityKeyIdentifierExtension.create( + this.keyPair.publicKey, + false, + this.crypto + ), + ...generateExtensions(opts.extensions || []), + ], + } satisfies x509.X509CertificateCreateParams; + + if (this.ctLog) { + // Pre-sign certificate for submission to CT Log + const preCert = await x509.X509CertificateGenerator.create( + tbs, + this.crypto + ); + + // Submit to CT Log in exchange for SCT + const issuerID = await this.issuerID; + const sct = await this.ctLog.log(preCert.rawData, issuerID); + + // Add the SCT extension to the certificate + tbs.extensions.push(extSCTList(sct)); + } + + const cert = await x509.X509CertificateGenerator.create(tbs, this.crypto); + return Buffer.from(cert.rawData); + } + + private get issuerID(): Promise { + return this.crypto.subtle + .exportKey('spki', this.keyPair.publicKey) + .then((key) => this.crypto.subtle.digest({ name: DIGEST_SHA256 }, key)); + } +} + +const extSCTList = (sct: ArrayBuffer): x509.Extension => { + // Manually construct the SCTList + const sctBuffer = sct; + const sctList = Buffer.concat([ + Buffer.from([0x00]), + Buffer.from([sctBuffer.byteLength]), + Buffer.from(sctBuffer), + ]); + + // Wrap the SCTList in an OctetString + const sctListWrapper = new asn1js.OctetString({ valueHex: sctList }); + + return new x509.Extension( + OID_SIGNED_CERTIFICATE_TIMESTAMP_LIST, + false, + sctListWrapper.toBER(false) + ); +}; + +const generateExtensions = (extensions: ExtensionValue[]): x509.Extension[] => + extensions.map((extension) => { + const value = new asn1js.Utf8String({ value: extension.value }); + return new x509.Extension(extension.oid, false, value.toBER(false)); + }); diff --git a/packages/mock/src/fulcio/ctlog.test.ts b/packages/mock/src/fulcio/ctlog.test.ts new file mode 100644 index 00000000..f5dda127 --- /dev/null +++ b/packages/mock/src/fulcio/ctlog.test.ts @@ -0,0 +1,52 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +import crypto from 'crypto'; +import { CTLog, initializeCTLog } from './ctlog'; + +describe('CTLog', () => { + describe('initializeCTLog', () => { + it('returns a CTLog', async () => { + const ctLog: CTLog = await initializeCTLog(); + expect(ctLog).toBeDefined(); + }); + }); + + describe('#publicKey', () => { + it('returns a key', async () => { + const ctLog: CTLog = await initializeCTLog(); + expect(ctLog.publicKey).toBeDefined(); + }); + }); + + describe('#logID', () => { + it('returns the log ID', async () => { + const ctLog: CTLog = await initializeCTLog(); + expect(ctLog.logID.toString('hex')).toMatch(/^[0-9a-f]{64}$/); + }); + + it('returns the log ID matching the public key', async () => { + const ctLog: CTLog = await initializeCTLog(); + + const logID = ctLog.logID.toString('hex'); + const keyDigest = crypto + .createHash('sha256') + .update(ctLog.publicKey) + .digest('hex'); + expect(logID).toMatch(keyDigest); + }); + }); +}); diff --git a/packages/mock/src/fulcio/ctlog.ts b/packages/mock/src/fulcio/ctlog.ts new file mode 100644 index 00000000..5ff3bfe7 --- /dev/null +++ b/packages/mock/src/fulcio/ctlog.ts @@ -0,0 +1,131 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +import { Crypto, CryptoKey } from '@peculiar/webcrypto'; +import * as asn1js from 'asn1js'; +import * as bs from 'bytestreamjs'; +import * as pkijs from 'pkijs'; +import * as pvutils from 'pvutils'; +import { + DIGEST_SHA256, + KEY_ALGORITHM_ECDSA_P256, + SIGNING_ALGORITHM_ECDSA_SHA256, +} from '../constants'; + +export interface CTLog { + publicKey: Buffer; + logID: Buffer; + log: ( + certificate: ArrayBuffer, + issuerID: ArrayBuffer + ) => Promise; +} + +export async function initializeCTLog(): Promise { + const crypto = new Crypto(); + + const { publicKey, privateKey } = await crypto.subtle.generateKey( + KEY_ALGORITHM_ECDSA_P256, + true, + ['sign', 'verify'] + ); + + const publicKeyBytes = await crypto.subtle + .exportKey('spki', publicKey) + .then((bytes) => Buffer.from(bytes)); + + const logID = await crypto.subtle + .digest({ name: DIGEST_SHA256 }, publicKeyBytes) + .then((bytes) => Buffer.from(bytes)); + + return new CTLogImpl({ + publicKey: publicKeyBytes, + privateKey, + logID, + crypto, + }); +} + +interface CTLogOptions { + publicKey: Buffer; + logID: Buffer; + privateKey: CryptoKey; + crypto: Crypto; +} + +class CTLogImpl implements CTLog { + public readonly publicKey: Buffer; + public readonly logID: Buffer; + private privateKey: CryptoKey; + private crypto: Crypto; + + constructor(options: CTLogOptions) { + this.publicKey = options.publicKey; + this.privateKey = options.privateKey; + this.logID = options.logID; + this.crypto = options.crypto; + } + + public async log( + certificate: ArrayBuffer, + issuerID: ArrayBuffer + ): Promise { + const version = 0; + const timestamp = new Date(); + const logID = this.logID; + + // A bit of a hack to get the TBS bytes + const tbs = pkijs.Certificate.fromBER(certificate).encodeTBS().toBER(); + + // Calculate the SCT signature + // https://www.rfc-editor.org/rfc/rfc6962#section-3.2 + const stream = new bs.SeqStream(); + stream.appendChar(version); + stream.appendChar(0x00); // SignatureType - certificate_timestamp(0) + stream.appendView(encodeTimeStamp(timestamp)); + stream.appendUint16(0x01); // LogEntryType = precert_entry(1) + stream.appendView(new Uint8Array(issuerID)); + stream.appendUint24(tbs.byteLength); + stream.appendView(new Uint8Array(tbs)); + stream.appendUint16(0x00); // extensions length + + const sig = await this.sign(stream.buffer); + + return new pkijs.SignedCertificateTimestamp({ + version, + logID, + timestamp, + signature: asn1js.fromBER(sig).result, + hashAlgorithm: 'sha256', + signatureAlgorithm: 'ecdsa', + }).toStream().buffer; + } + + private async sign(data: BufferSource): Promise { + return this.crypto.subtle + .sign(SIGNING_ALGORITHM_ECDSA_SHA256, this.privateKey, data) + .then((bytes) => pkijs.createCMSECDSASignature(bytes)); + } +} + +const encodeTimeStamp = (timestamp: Date): Uint8Array => { + const timeBuffer = new ArrayBuffer(8); + const timeView = new Uint8Array(timeBuffer); + const baseArray = pvutils.utilToBase(timestamp.valueOf(), 8); + timeView.set(new Uint8Array(baseArray), 8 - baseArray.byteLength); + + return timeView; +}; diff --git a/packages/mock/src/fulcio/handler.test.ts b/packages/mock/src/fulcio/handler.test.ts new file mode 100644 index 00000000..740f608a --- /dev/null +++ b/packages/mock/src/fulcio/handler.test.ts @@ -0,0 +1,102 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +import { generateKeyPairSync } from 'crypto'; +import { CA, initializeCA } from './ca'; +import { fulcioHandler } from './handler'; + +describe('fulcioHandler', () => { + describe('#path', () => { + it('returns the correct path', async () => { + const ca = await initializeCA(); + const handler = fulcioHandler(ca); + expect(handler.path).toBe('/api/v2/signingCert'); + }); + }); + + describe('#fn', () => { + it('returns a function', async () => { + const ca = await initializeCA(); + const handler = fulcioHandler(ca); + expect(handler.fn).toBeInstanceOf(Function); + }); + + describe('when invoked', () => { + const { publicKey } = generateKeyPairSync('ec', { namedCurve: 'P-256' }); + + const claims = { + sub: 'http://github.com/foo/workflow.yml@refs/heads/main', + }; + const jwt = jwtify(claims); + + const certRequest = { + credentials: { + oidcIdentityToken: jwt, + }, + publicKeyRequest: { + publicKey: { + algorithm: 'ECDSA', + content: publicKey + .export({ format: 'pem', type: 'spki' }) + .toString('ascii'), + }, + proofOfPossession: 'foobar', + }, + }; + + it('returns a certificate chain', async () => { + const ca = await initializeCA(); + const { fn } = fulcioHandler(ca); + + // Make a request + const resp = await fn(JSON.stringify(certRequest)); + expect(resp.statusCode).toBe(201); + + // Check the response + const certs = JSON.parse(resp.response.toString()); + expect(certs).toBeDefined(); + expect(certs.signedCertificateEmbeddedSct).toBeDefined(); + expect(certs.signedCertificateEmbeddedSct.chain).toBeDefined(); + expect( + certs.signedCertificateEmbeddedSct.chain.certificates + ).toBeDefined(); + expect( + certs.signedCertificateEmbeddedSct.chain.certificates + ).toHaveLength(2); + }); + + describe('when the CA raises an error', () => { + const ca: CA = { + rootCertificate: Buffer.from(''), + issueCertificate: async () => { + throw new Error('oops'); + }, + }; + + it('returns 400 error', async () => { + const { fn } = fulcioHandler(ca, { strict: false }); + const resp = await fn(JSON.stringify(certRequest)); + expect(resp.statusCode).toBe(400); + }); + }); + }); + }); +}); + +/* eslint-disable-next-line @typescript-eslint/no-explicit-any */ +function jwtify(obj: any): string { + return `.${Buffer.from(JSON.stringify(obj)).toString('base64')}.`; +} diff --git a/packages/mock/src/fulcio/handler.ts b/packages/mock/src/fulcio/handler.ts new file mode 100644 index 00000000..bf02f64f --- /dev/null +++ b/packages/mock/src/fulcio/handler.ts @@ -0,0 +1,125 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +import assert from 'assert'; +import { generateKeyPairSync } from 'crypto'; +import * as jose from 'jose'; +import type { Handler, HandlerFn, HandlerFnResult } from '../shared.types'; +import type { CA } from './ca'; + +const CREATE_SIGNING_CERT_PATH = '/api/v2/signingCert'; +const DEFAULT_SUBJECT = 'NO-SUBJECT'; + +interface FulcioHandlerOptions { + strict?: boolean; + subjectClaim?: string; +} + +export function fulcioHandler( + ca: CA, + opts: FulcioHandlerOptions = {} +): Handler { + return { + path: CREATE_SIGNING_CERT_PATH, + fn: createSigningCertHandler(ca, opts), + }; +} + +function createSigningCertHandler( + ca: CA, + opts: FulcioHandlerOptions +): HandlerFn { + const strict = opts.strict ?? true; + const subjectClaim = opts.subjectClaim || 'sub'; + + return async (body: string): Promise => { + try { + // Extract relevant fields from the request + const { subject, publicKey } = strict + ? parseBody(body, subjectClaim) + : stubBody(); + + // Request certificate from CA + const cert = await ca.issueCertificate({ + publicKey: fromPEM(publicKey), + subjectAltName: subject, + }); + + // Format the response + const response = buildResponse(cert, ca.rootCertificate); + + return { statusCode: 201, response, contentType: 'application/json' }; + } catch (e) { + assert(e instanceof Error); + return { statusCode: 400, response: e.message }; + } + }; +} + +function parseBody( + body: string, + subjectClaim: string +): { subject: string; publicKey: string } { + const json = JSON.parse(body.toString()); + const oidc = json.credentials.oidcIdentityToken; + const pem = json.publicKeyRequest.publicKey.content; + + // Decode the JWT + /* eslint-disable @typescript-eslint/no-explicit-any */ + const claims = jose.decodeJwt(oidc) as any; + + /* istanbul ignore next */ + return { subject: claims[subjectClaim] || DEFAULT_SUBJECT, publicKey: pem }; +} + +function stubBody(): { subject: string; publicKey: string } { + const { publicKey } = generateKeyPairSync('ec', { + namedCurve: 'P-256', + }); + return { + subject: DEFAULT_SUBJECT, + publicKey: publicKey.export({ format: 'pem', type: 'spki' }).toString(), + }; +} + +function buildResponse(leaf: Buffer, root: Buffer): string { + const body = { + signedCertificateEmbeddedSct: { + chain: { + certificates: [toPEM(leaf), toPEM(root)], + }, + }, + }; + return JSON.stringify(body); +} + +// PEM string to DER-encoded byte buffer conversion +function fromPEM(pem: string): Buffer { + return Buffer.from( + pem.replace(/-{5}(BEGIN|END) .*-{5}/gm, '').replace(/\s/gm, ''), + 'base64' + ); +} + +// DER-encoded byte buffer to PEM string conversion +function toPEM(der: Buffer): string { + return [ + '-----BEGIN CERTIFICATE-----', + der.toString('base64'), + '-----END CERTIFICATE-----', + '', + ].join('\n'); +} diff --git a/packages/mock/src/fulcio/index.ts b/packages/mock/src/fulcio/index.ts new file mode 100644 index 00000000..605ebe8a --- /dev/null +++ b/packages/mock/src/fulcio/index.ts @@ -0,0 +1,19 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +export { CA, initializeCA } from './ca'; +export { CTLog, initializeCTLog } from './ctlog'; +export { fulcioHandler } from './handler'; diff --git a/packages/mock/src/index.test.ts b/packages/mock/src/index.test.ts new file mode 100644 index 00000000..657e3499 --- /dev/null +++ b/packages/mock/src/index.test.ts @@ -0,0 +1,75 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +import nock from 'nock'; +import { + HandlerFn, + fulcioHandler, + initializeCA, + initializeCTLog, + initializeTLog, + initializeTSA, + mockFulcio, + mockRekor, + mockTSA, + rekorHandler, + tsaHandler, +} from '.'; + +it('exports types', () => { + const handlerFn: HandlerFn = async () => ({ + statusCode: 200, + response: 'ok', + }); + expect(handlerFn).toBeDefined(); +}); + +it('exports functions', () => { + expect(initializeCA).toBeDefined(); + expect(initializeCTLog).toBeDefined(); + expect(initializeTLog).toBeDefined(); + expect(initializeTSA).toBeDefined(); + expect(fulcioHandler).toBeDefined(); + expect(rekorHandler).toBeDefined(); + expect(tsaHandler).toBeDefined(); +}); + +describe('exports mock functions', () => { + afterEach(() => { + nock.cleanAll(); + }); + + describe('mockFulcio', () => { + it('mocks fulcio', async () => { + await mockFulcio(); + expect(nock.pendingMocks()).toHaveLength(1); + }); + }); + + describe('mockRekor', () => { + it('mocks rekor', async () => { + await mockRekor(); + expect(nock.pendingMocks()).toHaveLength(1); + }); + }); + + describe('mockTSA', () => { + it('mocks tsa', async () => { + await mockTSA(); + expect(nock.pendingMocks()).toHaveLength(1); + }); + }); +}); diff --git a/packages/mock/src/index.ts b/packages/mock/src/index.ts new file mode 100644 index 00000000..6d0c5f52 --- /dev/null +++ b/packages/mock/src/index.ts @@ -0,0 +1,77 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +import { fulcioHandler, initializeCA, initializeCTLog } from './fulcio'; +import { mock } from './mock'; +import { initializeTLog, rekorHandler } from './rekor'; +import { initializeTSA, tsaHandler } from './timestamp'; + +const DEFAULT_FULCIO_URL = 'https://fulcio.sigstore.dev'; +const DEFAULT_REKOR_URL = 'https://rekor.sigstore.dev'; +const DEFAULT_TSA_URL = 'https://timestamp.sigstore.dev'; + +interface FulcioOptions { + baseURL?: string; + strict?: boolean; +} + +interface RekorOptions { + baseURL?: string; + strict?: boolean; +} + +interface TSAOptions { + baseURL?: string; + strict?: boolean; +} + +export async function mockFulcio(options: FulcioOptions = {}) { + const url = options.baseURL || DEFAULT_FULCIO_URL; + const strict = options.strict ?? true; + const handler = await initializeCTLog() + .then((ctlog) => initializeCA(ctlog)) + .then((ca) => fulcioHandler(ca, { strict })); + mock(url, handler); +} + +export async function mockRekor(options: RekorOptions = {}) { + const url = options.baseURL || DEFAULT_REKOR_URL; + const strict = options.strict ?? true; + const handler = await initializeTLog().then((tlog) => + rekorHandler(tlog, { strict }) + ); + mock(url, handler); +} + +export async function mockTSA(options: TSAOptions = {}) { + const url = options.baseURL || DEFAULT_TSA_URL; + const strict = options.strict ?? true; + const handler = await initializeTSA().then((tsa) => + tsaHandler(tsa, { strict }) + ); + mock(url, handler); +} + +export type { HandlerFn } from './shared.types'; +export { + initializeCA, + initializeCTLog, + initializeTLog, + initializeTSA, + fulcioHandler, + rekorHandler, + tsaHandler, +}; diff --git a/packages/mock/src/mock.test.ts b/packages/mock/src/mock.test.ts new file mode 100644 index 00000000..0784feac --- /dev/null +++ b/packages/mock/src/mock.test.ts @@ -0,0 +1,58 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +import fetch from 'make-fetch-happen'; +import { mock } from './mock'; +import type { Handler, HandlerFnResult } from './shared.types'; + +describe('mock', () => { + const result: HandlerFnResult = { + statusCode: 201, + response: 'test', + contentType: 'text/plain', + }; + + const handler: Handler = { + path: '/test', + fn: jest.fn().mockResolvedValue(result), + }; + + describe('when request body is a string', () => { + it('mocks', async () => { + mock('http://example.com', handler); + const response = await fetch('http://example.com/test', { + method: 'POST', + body: 'test', + }); + expect(handler.fn).toBeCalled(); + expect(response.status).toBe(result.statusCode); + await expect(response.text()).resolves.toBe(result.response); + }); + }); + + describe('when request body is JSON', () => { + it('mocks', async () => { + mock('http://example.com', handler); + const response = await fetch('http://example.com/test', { + method: 'POST', + body: JSON.stringify({ test: 'test' }), + }); + expect(handler.fn).toBeCalled(); + expect(response.status).toBe(result.statusCode); + await expect(response.text()).resolves.toBe(result.response); + }); + }); +}); diff --git a/packages/mock/src/mock.ts b/packages/mock/src/mock.ts new file mode 100644 index 00000000..cc94ec90 --- /dev/null +++ b/packages/mock/src/mock.ts @@ -0,0 +1,41 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +import nock from 'nock'; +import type { Handler, HandlerFn } from './shared.types'; + +type NockHandler = ( + uri: string, + request: nock.Body +) => Promise; + +// Sets-up nock-based mocking for the given handler +export function mock(base: string, handler: Handler): void { + nock(base).post(handler.path).reply(adapt(handler.fn)); +} + +// Adapts our HandlerFn to nock's NockHandler format +function adapt(handler: HandlerFn): NockHandler { + /* istanbul ignore next */ + return async (_: string, body: nock.Body): Promise => { + const req = typeof body === 'string' ? body : JSON.stringify(body); + return handler(req).then(({ statusCode, response, contentType }) => [ + statusCode, + response, + { 'Content-Type': contentType || 'text/plain' }, + ]); + }; +} diff --git a/packages/mock/src/rekor/handler.test.ts b/packages/mock/src/rekor/handler.test.ts new file mode 100644 index 00000000..1d7489da --- /dev/null +++ b/packages/mock/src/rekor/handler.test.ts @@ -0,0 +1,96 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +import { fromPartial } from '@total-typescript/shoehorn'; +import crypto from 'crypto'; +import { rekorHandler } from './handler'; +import { initializeTLog, TLog } from './tlog'; + +describe('rekorHandler', () => { + describe('#path', () => { + it('returns the correct path', async () => { + const tlog = await initializeTLog(); + const handler = rekorHandler(tlog); + expect(handler.path).toBe('/api/v1/log/entries'); + }); + }); + + describe('#fn', () => { + it('returns a function', async () => { + const tlog = await initializeTLog(); + const handler = rekorHandler(tlog); + expect(handler.fn).toBeInstanceOf(Function); + }); + + describe('when invoked', () => { + const proposedEntry = { + apiVersion: '0.0.1', + kind: 'hashedrekord', + }; + + it('returns a tlog entry', async () => { + const tlog = await initializeTLog(); + const { fn } = rekorHandler(tlog); + + const resp = await fn(JSON.stringify(proposedEntry)); + expect(resp.statusCode).toBe(201); + + // Check the response + const logID = crypto + .createHash('sha256') + .update(tlog.publicKey) + .digest() + .toString('hex'); + + const body = JSON.parse(resp.response.toString()); + expect(body).toBeDefined(); + expect(Object.keys(body)).toHaveLength(1); + + const uuid = Object.keys(body)[0]; + expect(uuid).toMatch(/^[0-9a-f]{64}$/); + + const entry = body[uuid]; + expect(entry.body).toBeDefined(); + expect( + JSON.parse(Buffer.from(entry.body, 'base64').toString()) + ).toEqual(proposedEntry); + expect(entry.integratedTime).toBeGreaterThan(0); + expect(entry.logID).toBe(logID); + expect(entry.logIndex).toBeGreaterThan(0); + expect(entry.verification).toBeDefined(); + expect(entry.verification?.signedEntryTimestamp).toBeDefined(); + }); + + describe('when the TLog raises an error', () => { + const tlog = fromPartial({ + log: async () => { + throw new Error('oops'); + }, + }); + + it('returns 400 error', async () => { + const { fn } = rekorHandler(tlog, { strict: false }); + + // Make a request + const request = {}; + + const resp = await fn(JSON.stringify(request)); + expect(resp.statusCode).toBe(400); + }); + }); + }); + }); +}); diff --git a/packages/mock/src/rekor/handler.ts b/packages/mock/src/rekor/handler.ts new file mode 100644 index 00000000..884a6fa2 --- /dev/null +++ b/packages/mock/src/rekor/handler.ts @@ -0,0 +1,52 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +import assert from 'assert'; +import type { Handler, HandlerFn, HandlerFnResult } from '../shared.types'; +import type { TLog } from './tlog'; + +const CREATE_ENTRY_PATH = '/api/v1/log/entries'; + +interface RekorHandlerOptions { + strict?: boolean; +} + +export function rekorHandler( + tlog: TLog, + opts: RekorHandlerOptions = {} +): Handler { + return { + path: CREATE_ENTRY_PATH, + fn: createEntryHandler(tlog, opts), + }; +} + +function createEntryHandler(tlog: TLog, opts: RekorHandlerOptions): HandlerFn { + const strict = opts.strict ?? true; + + return async (body: string): Promise => { + try { + const proposedEntry = strict ? JSON.parse(body) : {}; + const tlogEntry = await tlog.log(proposedEntry); + const response = JSON.stringify(tlogEntry); + + return { statusCode: 201, response, contentType: 'application/json' }; + } catch (e) { + assert(e instanceof Error); + return { statusCode: 400, response: e.message }; + } + }; +} diff --git a/packages/mock/src/rekor/index.ts b/packages/mock/src/rekor/index.ts new file mode 100644 index 00000000..1733af9b --- /dev/null +++ b/packages/mock/src/rekor/index.ts @@ -0,0 +1,18 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +export { rekorHandler } from './handler'; +export { TLog, initializeTLog } from './tlog'; diff --git a/packages/mock/src/rekor/tlog.test.ts b/packages/mock/src/rekor/tlog.test.ts new file mode 100644 index 00000000..3d47353f --- /dev/null +++ b/packages/mock/src/rekor/tlog.test.ts @@ -0,0 +1,56 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +import crypto from 'crypto'; +import { initializeTLog } from './tlog'; + +describe('TLog', () => { + describe('#publicKey', () => { + it('should be a public key', async () => { + const subject = await initializeTLog(); + expect(subject.publicKey).toBeDefined(); + }); + }); + + describe('#log', () => { + it('returns an entry', async () => { + const proposedEntry = { foo: 'bar' }; + const subject = await initializeTLog(); + const result = await subject.log(proposedEntry); + + const logID = crypto + .createHash('sha256') + .update(subject.publicKey) + .digest() + .toString('hex'); + + expect(Object.keys(result)).toHaveLength(1); + const uuid = Object.keys(result)[0]; + expect(uuid).toMatch(/^[0-9a-f]{64}$/); + + const entry = result[uuid]; + expect(entry.body).toBeDefined(); + expect(JSON.parse(Buffer.from(entry.body, 'base64').toString())).toEqual( + proposedEntry + ); + expect(entry.integratedTime).toBeGreaterThan(0); + expect(entry.logID).toEqual(logID); + expect(entry.logIndex).toBeGreaterThan(0); + expect(entry.verification).toBeDefined(); + expect(entry.verification?.signedEntryTimestamp).toBeDefined(); + }); + }); +}); diff --git a/packages/mock/src/rekor/tlog.ts b/packages/mock/src/rekor/tlog.ts new file mode 100644 index 00000000..17eff23e --- /dev/null +++ b/packages/mock/src/rekor/tlog.ts @@ -0,0 +1,93 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import { LogEntry } from '@sigstore/rekor-types'; +import canonicalize from 'canonicalize'; +import crypto from 'crypto'; + +type InclusionProof = NonNullable< + LogEntry['x']['verification'] +>['inclusionProof']; + +const EMPTY_INCLUSION_PROOF: InclusionProof = { + checkpoint: '', + hashes: [], + logIndex: 0, + rootHash: '', + treeSize: 0, +}; + +export interface TLog { + publicKey: Buffer; + log(proposedEntry: object): Promise; +} + +export async function initializeTLog(): Promise { + const { publicKey, privateKey } = crypto.generateKeyPairSync('ec', { + namedCurve: 'P-256', + }); + + return new TLogImpl(publicKey, privateKey); +} + +class TLogImpl implements TLog { + public readonly publicKey: Buffer; + private readonly privateKey: crypto.KeyObject; + + constructor(publicKey: crypto.KeyObject, privateKey: crypto.KeyObject) { + this.privateKey = privateKey; + this.publicKey = publicKey.export({ format: 'der', type: 'spki' }); + } + + public async log(proposedEntry: object): Promise { + const uuid = crypto.randomBytes(32).toString('hex'); + const timestamp = Math.floor(Date.now() / 1000); + const logID = crypto + .createHash('sha256') + .update(this.publicKey) + .digest() + .toString('hex'); + const body = canonicalize(proposedEntry); + + // Random number for logIndex + const logIndex = Math.floor(Math.random() * 9000000) + 1000000; + + // Calculate SET + // https://github.com/sigstore/rekor/blob/9eb7ec628a41ffed291b605a57e716e86ef0d680/pkg/api/entries.go#L71 + const setData = { + body: body, + integratedTime: timestamp, + logIndex: logIndex, + logID: logID, + }; + const setBuffer = Buffer.from(canonicalize(setData)!, 'utf8'); + const set = crypto.sign('sha256', setBuffer, this.privateKey); + + return { + [uuid]: { + body: Buffer.from(body!).toString('base64'), + integratedTime: timestamp, + logID: logID, + logIndex: logIndex, + verification: { + inclusionProof: EMPTY_INCLUSION_PROOF, + signedEntryTimestamp: set.toString('base64'), + }, + }, + }; + } +} diff --git a/packages/mock/src/shared.types.ts b/packages/mock/src/shared.types.ts new file mode 100644 index 00000000..69c5f118 --- /dev/null +++ b/packages/mock/src/shared.types.ts @@ -0,0 +1,27 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +export type HandlerFnResult = { + statusCode: number; + response: string | Buffer; + contentType?: string; +}; +export type HandlerFn = (request: string) => Promise; + +export type Handler = { + path: string; + fn: HandlerFn; +}; diff --git a/packages/mock/src/timestamp/handler.test.ts b/packages/mock/src/timestamp/handler.test.ts new file mode 100644 index 00000000..5d32d26b --- /dev/null +++ b/packages/mock/src/timestamp/handler.test.ts @@ -0,0 +1,74 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +import { fromPartial } from '@total-typescript/shoehorn'; +import { tsaHandler } from './handler'; +import { initializeTSA, TSA } from './tsa'; + +describe('tsaHandler', () => { + describe('#path', () => { + it('returns the correct path', async () => { + const tsa = await initializeTSA(); + const handler = tsaHandler(tsa); + expect(handler.path).toBe('/api/v1/timestamp'); + }); + }); + + describe('#fn', () => { + it('returns a function', async () => { + const tsa = await initializeTSA(); + const handler = tsaHandler(tsa); + expect(handler.fn).toBeInstanceOf(Function); + }); + + describe('when invoked', () => { + const timestampRequest = { + artifactHash: Buffer.from('foo').toString('base64'), + hashAlgorithm: 'sha256', + }; + + it('returns a tlog entry', async () => { + const tsa = await initializeTSA(); + const { fn } = tsaHandler(tsa); + + const resp = await fn(JSON.stringify(timestampRequest)); + expect(resp.statusCode).toBe(201); + + // Check the response + const body = resp.response; + expect(body).toBeDefined(); + }); + + describe('when the TLog raises an error', () => { + const tsa = fromPartial({ + timestamp: async () => { + throw new Error('oops'); + }, + }); + + it('returns 400 error', async () => { + const { fn } = tsaHandler(tsa, { strict: false }); + + // Make a request + const request = {}; + + const resp = await fn(JSON.stringify(request)); + expect(resp.statusCode).toBe(400); + }); + }); + }); + }); +}); diff --git a/packages/mock/src/timestamp/handler.ts b/packages/mock/src/timestamp/handler.ts new file mode 100644 index 00000000..a7ff8933 --- /dev/null +++ b/packages/mock/src/timestamp/handler.ts @@ -0,0 +1,95 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +import assert from 'assert'; +import type { Handler, HandlerFn, HandlerFnResult } from '../shared.types'; +import type { TSA, TimestampRequest } from './tsa'; + +const OID_SHA256_ALGO_ID = '2.16.840.1.101.3.4.2.1'; +const OID_SHA384_ALGO_ID = '2.16.840.1.101.3.4.2.2'; +const OID_SHA512_ALGO_ID = '2.16.840.1.101.3.4.2.3'; + +const OID_TSA_POLICY = '1.3.6.1.4.1.57264.2'; + +const DEFAULT_NONCE = 1234567890; + +const CREATE_TIMESTAMP_PATH = '/api/v1/timestamp'; + +interface TSAHandlerOptions { + strict?: boolean; +} + +export function tsaHandler(tsa: TSA, opts: TSAHandlerOptions = {}): Handler { + return { + path: CREATE_TIMESTAMP_PATH, + fn: createTimestampHandler(tsa, opts), + }; +} + +function createTimestampHandler(tsa: TSA, opts: TSAHandlerOptions): HandlerFn { + const strict = opts.strict ?? true; + + return async (body: string): Promise => { + try { + const tsr = strict ? parseRequest(body) : stubRequest(); + const timestamp = await tsa.timestamp(tsr); + + return { + statusCode: 201, + response: timestamp, + contentType: 'application/timestamp-reply', + }; + } catch (e) { + assert(e instanceof Error); + return { statusCode: 400, response: e.message }; + } + }; +} + +function parseRequest(body: string): TimestampRequest { + const json = JSON.parse(body.toString()); + + return { + artifactHash: Buffer.from(json.artifactHash, 'base64'), + hashAlgorithmOID: hashToOID(json.hashAlgorithm), + nonce: json.nonce || DEFAULT_NONCE, + policyOID: json.tsaPolicyOID || OID_TSA_POLICY, + certReq: json.certificates ?? false, + }; +} + +function stubRequest(): TimestampRequest { + return { + artifactHash: Buffer.from('deadbeef', 'hex'), + hashAlgorithmOID: OID_SHA256_ALGO_ID, + nonce: DEFAULT_NONCE, + policyOID: OID_TSA_POLICY, + certReq: false, + }; +} + +function hashToOID(hash: string): string { + switch (true) { + /* istanbul ignore next */ + case /512/.test(hash): + return OID_SHA512_ALGO_ID; + /* istanbul ignore next */ + case /384/.test(hash): + return OID_SHA384_ALGO_ID; + default: + return OID_SHA256_ALGO_ID; + } +} diff --git a/packages/mock/src/timestamp/index.ts b/packages/mock/src/timestamp/index.ts new file mode 100644 index 00000000..b0f2743d --- /dev/null +++ b/packages/mock/src/timestamp/index.ts @@ -0,0 +1,18 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +export { tsaHandler } from './handler'; +export { TSA, initializeTSA } from './tsa'; diff --git a/packages/mock/src/timestamp/tsa.test.ts b/packages/mock/src/timestamp/tsa.test.ts new file mode 100644 index 00000000..141d72cf --- /dev/null +++ b/packages/mock/src/timestamp/tsa.test.ts @@ -0,0 +1,59 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +import * as pkijs from 'pkijs'; +import { initializeTSA, TimestampRequest } from './tsa'; + +const OID_TSA_POLICY = '1.3.6.1.4.1.57264.2'; +const OID_SHA256_ALGO_ID = '2.16.840.1.101.3.4.2.1'; + +describe('TSA', () => { + describe('rootCertificate', () => { + it('returns the root certificate', async () => { + const tsa = await initializeTSA(); + const root = tsa.rootCertificate; + + expect(root).toBeDefined(); + + const cert = pkijs.Certificate.fromBER(root); + expect(cert.issuer.typesAndValues[0].value.valueBlock.value).toBe('tsa'); + expect(cert.issuer.typesAndValues[1].value.valueBlock.value).toBe( + 'sigstore.mock' + ); + }); + }); + + describe('#timestamp', () => { + const request: TimestampRequest = { + hashAlgorithmOID: OID_SHA256_ALGO_ID, + artifactHash: Buffer.from('hello world'), + nonce: 12345, + policyOID: OID_TSA_POLICY, + }; + + it('returns a timestamp', async () => { + const tsa = await initializeTSA(); + const result = await tsa.timestamp(request); + expect(result).toBeDefined(); + + const timestamp = pkijs.TimeStampResp.fromBER(result); + expect(timestamp.status.status).toBe(0); + expect(timestamp.timeStampToken?.contentType).toBe( + '1.2.840.113549.1.7.2' + ); + }); + }); +}); diff --git a/packages/mock/src/timestamp/tsa.ts b/packages/mock/src/timestamp/tsa.ts new file mode 100644 index 00000000..e4c6db4e --- /dev/null +++ b/packages/mock/src/timestamp/tsa.ts @@ -0,0 +1,180 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +import { Crypto } from '@peculiar/webcrypto'; +import * as asn1js from 'asn1js'; +import * as pkijs from 'pkijs'; +import { + DIGEST_SHA256, + KEY_ALGORITHM_ECDSA_P256, + SIGNING_ALGORITHM_ECDSA_SHA384, +} from '../constants'; +import { createRootCertificate } from '../util/root-cert'; + +const ISSUER = 'CN=tsa,O=sigstore.mock'; +const OID_TSTINFO_CONTENT_TYPE = '1.2.840.113549.1.9.16.1.4'; +const OID_SIGNED_DATA_CONTENT_TYPE = '1.2.840.113549.1.7.2'; + +export interface TSA { + rootCertificate: Buffer; + timestamp: (req: TimestampRequest) => Promise; +} + +export interface TimestampRequest { + artifactHash: Buffer; + hashAlgorithmOID: string; + nonce: number; + policyOID: string; + certReq?: boolean; +} + +export async function initializeTSA(): Promise { + const root = await createRootCertificate( + ISSUER, + KEY_ALGORITHM_ECDSA_P256, + SIGNING_ALGORITHM_ECDSA_SHA384 + ); + return new TSAImpl({ + rootCertificate: pkijs.Certificate.fromBER(root.cert.rawData), + keyPair: root.keyPair, + }); +} + +interface TSAOptions { + rootCertificate: pkijs.Certificate; + keyPair: CryptoKeyPair; +} + +class TSAImpl implements TSA { + private rootCert: pkijs.Certificate; + private keyPair: CryptoKeyPair; + private crypto: pkijs.ICryptoEngine; + constructor(options: TSAOptions) { + this.rootCert = options.rootCertificate; + this.keyPair = options.keyPair; + this.crypto = new pkijs.CryptoEngine({ crypto: new Crypto() }); + } + + public get rootCertificate(): Buffer { + return Buffer.from(this.rootCert.toSchema().toBER(false)); + } + + // Create a timestamp according to + // https://www.rfc-editor.org/rfc/rfc3161.html + public async timestamp(req: TimestampRequest): Promise { + const includeCerts = req.certReq ?? false; + + // Create the TSTInfo structure and sign it + const tstInfo = this.tstInfo(req); + const signedData = await this.signedData(tstInfo, includeCerts); + + // Encode the SignedData structure + const content = new pkijs.ContentInfo({ + contentType: OID_SIGNED_DATA_CONTENT_TYPE, + content: signedData.toSchema(true), + }); + + const tspResponse = new pkijs.TimeStampResp({ + status: new pkijs.PKIStatusInfo({ status: 0 }), + timeStampToken: new pkijs.ContentInfo({ schema: content.toSchema() }), + }); + + return Buffer.from(tspResponse.toSchema().toBER(false)); + } + + // Assemble the TSTInfo structure from the request + private tstInfo(req: TimestampRequest): pkijs.TSTInfo { + return new pkijs.TSTInfo({ + version: 1, + policy: req.policyOID, + messageImprint: new pkijs.MessageImprint({ + hashAlgorithm: new pkijs.AlgorithmIdentifier({ + algorithmId: req.hashAlgorithmOID, + }), + hashedMessage: new asn1js.OctetString({ valueHex: req.artifactHash }), + }), + serialNumber: new asn1js.Integer({ value: 1 }), + genTime: new Date(), + accuracy: new pkijs.Accuracy({ seconds: 1 }), + nonce: new asn1js.Integer({ value: req.nonce }), + tsa: generalName('tsa', 'sigstore.mock'), + }); + } + + // Wrap the TSTInfo structure in a SignedData structure + private async signedData( + tstInfo: pkijs.TSTInfo, + includeCerts: boolean + ): Promise { + // The isConstructed flag makes the encoding of the + // EncapsulatedContentInfo look more like what the real TSA returns, + // however, it results in a reponse that is not parseable by openssl. + // I guess we should leave it at the default but let's revisit this + // later if we run into verification problems. + const encapContent = new pkijs.EncapsulatedContentInfo({ + eContentType: OID_TSTINFO_CONTENT_TYPE, + eContent: new asn1js.OctetString({ + valueHex: tstInfo.toSchema().toBER(false), + // idBlock: { isConstructed: true }, + }), + }); + + /* istanbul ignore next */ + const signedData = new pkijs.SignedData({ + version: 1, + encapContentInfo: encapContent, + certificates: includeCerts ? [this.rootCert] : undefined, + signerInfos: [ + new pkijs.SignerInfo({ + version: 1, + sid: new pkijs.IssuerAndSerialNumber({ + issuer: this.rootCert.issuer, + serialNumber: this.rootCert.serialNumber, + }), + }), + ], + }); + + // Sign the SignedData structure + await signedData.sign( + this.keyPair.privateKey, + 0, + DIGEST_SHA256, + undefined, + this.crypto + ); + + return signedData; + } +} + +function generalName(commonName: string, orgName: string): pkijs.GeneralName { + return new pkijs.GeneralName({ + type: 4, + value: new pkijs.RelativeDistinguishedNames({ + typesAndValues: [ + new pkijs.AttributeTypeAndValue({ + type: '2.5.4.10', + value: new asn1js.PrintableString({ value: orgName }), + }), + new pkijs.AttributeTypeAndValue({ + type: '2.5.4.3', + value: new asn1js.PrintableString({ value: commonName }), + }), + ], + }), + }); +} diff --git a/packages/mock/src/trust-root.ts b/packages/mock/src/trust-root.ts new file mode 100644 index 00000000..f8ba5edc --- /dev/null +++ b/packages/mock/src/trust-root.ts @@ -0,0 +1,80 @@ +/* +Copyright 2023 The Sigstore 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. +*/ + +import { + CertificateAuthority, + HashAlgorithm, + PublicKeyDetails, + TransparencyLogInstance, +} from '@sigstore/protobuf-specs'; +import crypto from 'crypto'; +import type { CA, CTLog } from './fulcio'; +import type { TLog } from './rekor'; + +/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ +function trustCA(ca: CA): CertificateAuthority { + return { + subject: { + commonName: 'sigstore', + organization: 'sigstore.mock', + }, + uri: 'https://fulcio.sigstore.dev', + certChain: { + certificates: [ + { + rawBytes: ca.rootCertificate, + }, + ], + }, + validFor: { + start: new Date(), + }, + }; +} + +/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ +function trustTLog(tlog: TLog): TransparencyLogInstance { + return { + baseUrl: 'https://rekor.sigstore.dev', + logId: { + keyId: crypto.createHash('sha256').update(tlog.publicKey).digest(), + }, + hashAlgorithm: HashAlgorithm.SHA2_256, + publicKey: { + rawBytes: tlog.publicKey, + keyDetails: PublicKeyDetails.PKIX_ECDSA_P256_SHA_256, + validFor: { + start: new Date(), + }, + }, + }; +} + +/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ +function trustCTLog(ctlog: CTLog): TransparencyLogInstance { + return { + baseUrl: 'https://ctfe.sigstore.dev', + logId: { keyId: ctlog.logID }, + hashAlgorithm: HashAlgorithm.SHA2_256, + publicKey: { + rawBytes: ctlog.publicKey, + keyDetails: PublicKeyDetails.PKIX_ECDSA_P256_SHA_256, + validFor: { + start: new Date(), + }, + }, + }; +} diff --git a/packages/mock/src/util/root-cert.ts b/packages/mock/src/util/root-cert.ts new file mode 100644 index 00000000..697c8c9f --- /dev/null +++ b/packages/mock/src/util/root-cert.ts @@ -0,0 +1,67 @@ +/* +Copyright 2023 The Sigstore 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. +*/ +import { Crypto } from '@peculiar/webcrypto'; +import x509 from '@peculiar/x509'; + +const MS_PER_DAY = 1000 * 60 * 60 * 24; + +interface CertWithKey { + cert: x509.X509Certificate; + keyPair: CryptoKeyPair; +} + +export async function createRootCertificate( + name: string, + keyAlgo: EcKeyGenParams, + signAlgo: EcdsaParams +): Promise { + const crypto = new Crypto(); + const keyPair = await crypto.subtle.generateKey(keyAlgo, true, [ + 'sign', + 'verify', + ]); + + const tbs: x509.X509CertificateCreateSelfSignedParams = { + serialNumber: '01', + name: name, + notBefore: new Date(), + notAfter: new Date(Date.now() + 365 * MS_PER_DAY), + signingAlgorithm: signAlgo, + keys: keyPair, + extensions: [ + new x509.BasicConstraintsExtension(true, undefined, true), + new x509.KeyUsagesExtension( + x509.KeyUsageFlags.cRLSign | x509.KeyUsageFlags.keyCertSign, + true + ), + await x509.SubjectKeyIdentifierExtension.create( + keyPair.publicKey, + false, + crypto + ), + await x509.AuthorityKeyIdentifierExtension.create( + keyPair.publicKey, + false, + crypto + ), + ], + }; + + return { + cert: await x509.X509CertificateGenerator.createSelfSigned(tbs, crypto), + keyPair, + }; +} diff --git a/packages/mock/tsconfig.json b/packages/mock/tsconfig.json new file mode 100644 index 00000000..9a73af07 --- /dev/null +++ b/packages/mock/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "dist", + "composite": true + }, + "exclude": [ + "./dist", + "**/__tests__", + "jest.setup.ts" + ], + "references": [ + { "path": "../rekor-types" } + ] +} diff --git a/packages/rekor-types/package.json b/packages/rekor-types/package.json index bbfe4d7f..092a087f 100644 --- a/packages/rekor-types/package.json +++ b/packages/rekor-types/package.json @@ -28,10 +28,8 @@ "provenance": true }, "devDependencies": { - "json-schema-to-typescript": "^13.0.0", - "openapi-typescript-codegen": "^0.24.0", - "shx": "^0.3.3", - "typescript": "^5.1.3" + "json-schema-to-typescript": "^13.0.2", + "openapi-typescript-codegen": "^0.24.0" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" diff --git a/packages/tuf/CHANGELOG.md b/packages/tuf/CHANGELOG.md index 3bfba9cb..aba4961e 100644 --- a/packages/tuf/CHANGELOG.md +++ b/packages/tuf/CHANGELOG.md @@ -1,5 +1,11 @@ # @sigstore/tuf +## 1.0.1 + +### Patch Changes + +- b97be71: Bump tuf-js from 1.1.6 to 1.1.7 + ## 1.0.0 ### Major Changes diff --git a/packages/tuf/README.md b/packages/tuf/README.md index 13f9c2bc..eed1dd69 100644 --- a/packages/tuf/README.md +++ b/packages/tuf/README.md @@ -1,4 +1,4 @@ -# @sigstore/tuf · [![npm version](https://img.shields.io/npm/v/@sigstore/tuf.svg?style=flat)](https://www.npmjs.com/package/sigstore) [![CI Status](https://github.com/sigstore/sigstore-js/workflows/CI/badge.svg)](https://github.com/sigstore/sigstore-js/actions/workflows/ci.yml) [![Smoke Test Status](https://github.com/sigstore/sigstore-js/workflows/smoke-test/badge.svg)](https://github.com/sigstore/sigstore-js/actions/workflows/smoke-test.yml) +# @sigstore/tuf · [![npm version](https://img.shields.io/npm/v/@sigstore/tuf.svg?style=flat)](https://www.npmjs.com/package/@sigstore/tuf) [![CI Status](https://github.com/sigstore/sigstore-js/workflows/CI/badge.svg)](https://github.com/sigstore/sigstore-js/actions/workflows/ci.yml) [![Smoke Test Status](https://github.com/sigstore/sigstore-js/workflows/smoke-test/badge.svg)](https://github.com/sigstore/sigstore-js/actions/workflows/smoke-test.yml) A JavaScript library for securely retrieving targets from the Sigstore [TUF][1] repository. diff --git a/packages/tuf/jest.config.js b/packages/tuf/jest.config.js index 98d00e05..b72848c1 100644 --- a/packages/tuf/jest.config.js +++ b/packages/tuf/jest.config.js @@ -13,10 +13,11 @@ 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. */ -const base = require('../../jest.config.base') +const base = require('../../jest.config.base'); module.exports = { ...base, displayName: 'tuf', + setupFilesAfterEnv: ['@sigstore/jest/all'], testPathIgnorePatterns: ['/dist/'], }; diff --git a/packages/tuf/package.json b/packages/tuf/package.json index 241dc32b..746a4465 100644 --- a/packages/tuf/package.json +++ b/packages/tuf/package.json @@ -1,6 +1,6 @@ { "name": "@sigstore/tuf", - "version": "1.0.0", + "version": "1.0.1", "description": "Client for the Sigstore TUF repository", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -27,17 +27,13 @@ "provenance": true }, "devDependencies": { - "@total-typescript/shoehorn": "^0.1.0", - "@tufjs/repo-mock": "^1.1.0", - "@types/node": "^20.2.5", - "nock": "^13.2.4", - "shx": "^0.3.3", - "typescript": "^5.1.3" + "@sigstore/jest": "^0.0.0", + "@tufjs/repo-mock": "^1.1.0" }, "dependencies": { "@sigstore/protobuf-specs": "^0.1.0", - "tuf-js": "^1.1.3", - "make-fetch-happen": "^11.0.1" + "@types/make-fetch-happen": "^10.0.0", + "tuf-js": "^1.1.7" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" diff --git a/packages/tuf/src/__tests__/client.test.ts b/packages/tuf/src/__tests__/client.test.ts index 4cbeacc7..01c24360 100644 --- a/packages/tuf/src/__tests__/client.test.ts +++ b/packages/tuf/src/__tests__/client.test.ts @@ -91,15 +91,10 @@ describe('TUFClient', () => { it('throws an error', async () => { const subject = new TUFClient(options!); await subject.refresh(); - await expect(subject.getTarget('baz')).rejects.toThrowError(TUFError); - }); - - it('throws an error with code TUF_FIND_TARGET_ERROR', async () => { - const subject = new TUFClient(options!); - expect.assertions(1); - await subject.getTarget('baz').catch((err) => { - expect(err.code).toEqual('TUF_FIND_TARGET_ERROR'); - }); + await expect(subject.getTarget('baz')).rejects.toThrowWithCode( + TUFError, + 'TUF_FIND_TARGET_ERROR' + ); }); }); }); diff --git a/packages/tuf/src/__tests__/target.test.ts b/packages/tuf/src/__tests__/target.test.ts index b68db9c8..b4256d3b 100644 --- a/packages/tuf/src/__tests__/target.test.ts +++ b/packages/tuf/src/__tests__/target.test.ts @@ -77,17 +77,11 @@ describe('readTarget', () => { }); it('throw an error', async () => { - await expect(readTarget(tuf, targetPath)).rejects.toThrowError( - TUFError + await expect(readTarget(tuf, targetPath)).rejects.toThrowWithCode( + TUFError, + 'TUF_DOWNLOAD_TARGET_ERROR' ); }); - - it('throws an error with code TUF_DOWNLOAD_TARGET_ERROR', async () => { - expect.assertions(1); - await readTarget(tuf, targetPath).catch((err) => { - expect(err.code).toEqual('TUF_DOWNLOAD_TARGET_ERROR'); - }); - }); }); }); @@ -97,14 +91,10 @@ describe('readTarget', () => { }); it('throws an error', async () => { - await expect(readTarget(tuf, targetPath)).rejects.toThrow(TUFError); - }); - - it('throws an error with code TUF_REFRESH_METADATA_ERROR', async () => { - expect.assertions(1); - await readTarget(tuf, targetPath).catch((err) => { - expect(err.code).toEqual('TUF_REFRESH_METADATA_ERROR'); - }); + await expect(readTarget(tuf, targetPath)).rejects.toThrowWithCode( + TUFError, + 'TUF_REFRESH_METADATA_ERROR' + ); }); }); @@ -115,14 +105,10 @@ describe('readTarget', () => { }); it('throws an error', async () => { - await expect(readTarget(tuf, targetPath)).rejects.toThrow(TUFError); - }); - - it('throws an error with code TUF_FIND_TARGET_ERROR', async () => { - expect.assertions(1); - await readTarget(tuf, targetPath).catch((err) => { - expect(err.code).toEqual('TUF_FIND_TARGET_ERROR'); - }); + await expect(readTarget(tuf, targetPath)).rejects.toThrowWithCode( + TUFError, + 'TUF_FIND_TARGET_ERROR' + ); }); }); @@ -134,14 +120,10 @@ describe('readTarget', () => { }); it('throws an error', async () => { - await expect(readTarget(tuf, targetPath)).rejects.toThrow(TUFError); - }); - - it('throws an error with code TUF_READ_TARGET_ERROR', async () => { - expect.assertions(1); - await readTarget(tuf, targetPath).catch((err) => { - expect(err.code).toEqual('TUF_READ_TARGET_ERROR'); - }); + await expect(readTarget(tuf, targetPath)).rejects.toThrowWithCode( + TUFError, + 'TUF_READ_TARGET_ERROR' + ); }); }); }); diff --git a/packages/tuf/tsconfig.json b/packages/tuf/tsconfig.json index 55a4ecda..f08e66bb 100644 --- a/packages/tuf/tsconfig.json +++ b/packages/tuf/tsconfig.json @@ -9,5 +9,8 @@ "./dist", "**/__tests__", "jest.setup.ts" + ], + "references": [ + { "path": "../jest" } ] } diff --git a/tsconfig.build.json b/tsconfig.build.json index 9efc7cb3..ddfc6651 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -3,7 +3,9 @@ "references": [ { "path": "packages/cli" }, { "path": "packages/client" }, + { "path": "packages/mock" }, { "path": "packages/rekor-types" }, + { "path": "packages/jest" }, { "path": "packages/jest-types" }, { "path": "packages/tuf" } ]