203 Commits
v0.1.9 ... main

Author SHA1 Message Date
dependabot[bot]
de602565c0 feat(deps): bump github.com/aws/aws-sdk-go-v2/config from 1.28.4 to 1.28.5 (#223)
Some checks failed
Release Drafter / update_release_draft (push) Has been cancelled
test code / golang (1.22.x, macos-latest) (push) Has been cancelled
test code / golang (1.22.x, ubuntu-latest) (push) Has been cancelled
test code / golang (1.23.x, macos-latest) (push) Has been cancelled
test code / golang (1.23.x, ubuntu-latest) (push) Has been cancelled
Bumps
[github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2)
from 1.28.4 to 1.28.5.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="d125de3792"><code>d125de3</code></a>
Release 2024-11-18</li>
<li><a
href="fec51f3fff"><code>fec51f3</code></a>
Regenerated Clients</li>
<li><a
href="fba5997045"><code>fba5997</code></a>
Update API model</li>
<li><a
href="0b8e5c842f"><code>0b8e5c8</code></a>
Bump smithy-go dependency (<a
href="https://redirect.github.com/aws/aws-sdk-go-v2/issues/2902">#2902</a>)</li>
<li><a
href="50ba45ce16"><code>50ba45c</code></a>
Release 2024-11-15.2</li>
<li><a
href="444bdffccd"><code>444bdff</code></a>
Regenerated Clients</li>
<li><a
href="55ab381b20"><code>55ab381</code></a>
Update endpoints model</li>
<li><a
href="94c083768b"><code>94c0837</code></a>
Update API model</li>
<li><a
href="2398a7903c"><code>2398a79</code></a>
Remove elastictranscoder service's integration test (<a
href="https://redirect.github.com/aws/aws-sdk-go-v2/issues/2901">#2901</a>)</li>
<li><a
href="93e0f294f6"><code>93e0f29</code></a>
Release 2024-11-15</li>
<li>Additional commits viewable in <a
href="https://github.com/aws/aws-sdk-go-v2/compare/config/v1.28.4...config/v1.28.5">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/config&package-manager=go_modules&previous-version=1.28.4&new-version=1.28.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-19 11:16:04 +00:00
dependabot[bot]
dea2686365 feat(deps): bump github.com/aws/aws-sdk-go-v2/config from 1.28.3 to 1.28.4 (#221)
Bumps
[github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2)
from 1.28.3 to 1.28.4.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="f0fcf5955d"><code>f0fcf59</code></a>
Release 2024-11-14</li>
<li><a
href="af5e138e30"><code>af5e138</code></a>
Regenerated Clients</li>
<li><a
href="6b6d9d09c4"><code>6b6d9d0</code></a>
Update endpoints model</li>
<li><a
href="6646f21285"><code>6646f21</code></a>
Update API model</li>
<li><a
href="27326538a1"><code>2732653</code></a>
Release 2024-11-13</li>
<li><a
href="91f9f43858"><code>91f9f43</code></a>
Regenerated Clients</li>
<li><a
href="b95013d5d8"><code>b95013d</code></a>
Update endpoints model</li>
<li><a
href="673ae94b2b"><code>673ae94</code></a>
Update API model</li>
<li><a
href="10b8b14449"><code>10b8b14</code></a>
Release 2024-11-12</li>
<li><a
href="c96e678745"><code>c96e678</code></a>
Regenerated Clients</li>
<li>Additional commits viewable in <a
href="https://github.com/aws/aws-sdk-go-v2/compare/config/v1.28.3...config/v1.28.4">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/config&package-manager=go_modules&previous-version=1.28.3&new-version=1.28.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-18 15:07:33 +00:00
dependabot[bot]
00bc2fa831 chore(deps): bump codecov/codecov-action from 4 to 5 (#220)
Bumps
[codecov/codecov-action](https://github.com/codecov/codecov-action) from
4 to 5.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/codecov/codecov-action/releases">codecov/codecov-action's
releases</a>.</em></p>
<blockquote>
<h2>v5.0.0</h2>
<h2>v5 Release</h2>
<p><code>v5</code> of the Codecov GitHub Action will use the <a
href="https://github.com/codecov/wrapper">Codecov Wrapper</a> to
encapsulate the <a
href="https://github.com/codecov/codecov-cli">CLI</a>. This will help
ensure that the Action gets updates quicker.</p>
<h3>Migration Guide</h3>
<p>The <code>v5</code> release also coincides with the opt-out feature
for tokens for public repositories. In the <code>Global Upload
Token</code> section of the settings page of an organization in
codecov.io, you can set the ability for Codecov to receive a coverage
reports from any source. This will allow contributors or other members
of a repository to upload without needing access to the Codecov token.
For more details see <a
href="https://docs.codecov.com/docs/codecov-tokens#uploading-without-a-token">how
to upload without a token</a>.</p>
<blockquote>
<p>[!WARNING]<br />
<strong>The following arguments have been changed</strong></p>
<ul>
<li><code>file</code> (this has been deprecated in favor of
<code>files</code>)</li>
<li><code>plugin</code> (this has been deprecated in favor of
<code>plugins</code>)</li>
</ul>
</blockquote>
<p>The following arguments have been added:</p>
<ul>
<li><code>binary</code></li>
<li><code>gcov_args</code></li>
<li><code>gcov_executable</code></li>
<li><code>gcov_ignore</code></li>
<li><code>gcov_include</code></li>
<li><code>report_type</code></li>
<li><code>skip_validation</code></li>
<li><code>swift_project</code></li>
</ul>
<p>You can see their usage in the <code>action.yml</code> <a
href="https://github.com/codecov/codecov-action/blob/main/action.yml">file</a>.</p>
<h2>What's Changed</h2>
<ul>
<li>chore(deps): bump to eslint9+ and remove eslint-config-google by <a
href="https://github.com/thomasrockhu-codecov"><code>@​thomasrockhu-codecov</code></a>
in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1591">codecov/codecov-action#1591</a></li>
<li>build(deps-dev): bump <code>@​octokit/webhooks-types</code> from
7.5.1 to 7.6.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1595">codecov/codecov-action#1595</a></li>
<li>build(deps-dev): bump typescript from 5.6.2 to 5.6.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1604">codecov/codecov-action#1604</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/parser</code> from
8.8.0 to 8.8.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1601">codecov/codecov-action#1601</a></li>
<li>build(deps): bump <code>@​actions/core</code> from 1.11.0 to 1.11.1
by <a href="https://github.com/dependabot"><code>@​dependabot</code></a>
in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1597">codecov/codecov-action#1597</a></li>
<li>build(deps): bump github/codeql-action from 3.26.9 to 3.26.11 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1596">codecov/codecov-action#1596</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/eslint-plugin</code>
from 8.8.0 to 8.8.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1600">codecov/codecov-action#1600</a></li>
<li>build(deps-dev): bump eslint from 9.11.1 to 9.12.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1598">codecov/codecov-action#1598</a></li>
<li>build(deps): bump github/codeql-action from 3.26.11 to 3.26.12 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1609">codecov/codecov-action#1609</a></li>
<li>build(deps): bump actions/checkout from 4.2.0 to 4.2.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1608">codecov/codecov-action#1608</a></li>
<li>build(deps): bump actions/upload-artifact from 4.4.0 to 4.4.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1607">codecov/codecov-action#1607</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/parser</code> from
8.8.1 to 8.9.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1612">codecov/codecov-action#1612</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/eslint-plugin</code>
from 8.8.1 to 8.9.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1611">codecov/codecov-action#1611</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/eslint-plugin</code>
from 8.9.0 to 8.10.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1615">codecov/codecov-action#1615</a></li>
<li>build(deps-dev): bump eslint from 9.12.0 to 9.13.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1618">codecov/codecov-action#1618</a></li>
<li>build(deps): bump github/codeql-action from 3.26.12 to 3.26.13 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1617">codecov/codecov-action#1617</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/parser</code> from
8.9.0 to 8.10.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1614">codecov/codecov-action#1614</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/eslint-plugin</code>
from 8.10.0 to 8.11.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1620">codecov/codecov-action#1620</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/parser</code> from
8.10.0 to 8.11.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1619">codecov/codecov-action#1619</a></li>
<li>build(deps-dev): bump <code>@​types/jest</code> from 29.5.13 to
29.5.14 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1622">codecov/codecov-action#1622</a></li>
<li>build(deps): bump actions/checkout from 4.2.1 to 4.2.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1625">codecov/codecov-action#1625</a></li>
<li>build(deps): bump github/codeql-action from 3.26.13 to 3.27.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1624">codecov/codecov-action#1624</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/eslint-plugin</code>
from 8.11.0 to 8.12.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1626">codecov/codecov-action#1626</a></li>
<li>build(deps-dev): bump <code>@​typescript-eslint/eslint-plugin</code>
from 8.12.1 to 8.12.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/codecov/codecov-action/pull/1629">codecov/codecov-action#1629</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md">codecov/codecov-action's
changelog</a>.</em></p>
<blockquote>
<h2>4.0.0-beta.2</h2>
<h3>Fixes</h3>
<ul>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/1085">#1085</a>
not adding -n if empty to do-upload command</li>
</ul>
<h2>4.0.0-beta.1</h2>
<p><code>v4</code> represents a move from the <a
href="https://github.com/codecov/uploader">universal uploader</a> to the
<a href="https://github.com/codecov/codecov-cli">Codecov CLI</a>.
Although this will unlock new features for our users, the CLI is not yet
at feature parity with the universal uploader.</p>
<h3>Breaking Changes</h3>
<ul>
<li>No current support for <code>aarch64</code> and <code>alpine</code>
architectures.</li>
<li>Tokenless uploading is unsuported</li>
<li>Various arguments to the Action have been removed</li>
</ul>
<h2>3.1.4</h2>
<h3>Fixes</h3>
<ul>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/967">#967</a>
Fix typo in README.md</li>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/971">#971</a>
fix: add back in working dir</li>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/969">#969</a>
fix: CLI option names for uploader</li>
</ul>
<h3>Dependencies</h3>
<ul>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/970">#970</a>
build(deps-dev): bump <code>@​types/node</code> from 18.15.12 to
18.16.3</li>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/979">#979</a>
build(deps-dev): bump <code>@​types/node</code> from 20.1.0 to
20.1.2</li>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/981">#981</a>
build(deps-dev): bump <code>@​types/node</code> from 20.1.2 to
20.1.4</li>
</ul>
<h2>3.1.3</h2>
<h3>Fixes</h3>
<ul>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/960">#960</a>
fix: allow for aarch64 build</li>
</ul>
<h3>Dependencies</h3>
<ul>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/957">#957</a>
build(deps-dev): bump jest-junit from 15.0.0 to 16.0.0</li>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/958">#958</a>
build(deps): bump openpgp from 5.7.0 to 5.8.0</li>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/959">#959</a>
build(deps-dev): bump <code>@​types/node</code> from 18.15.10 to
18.15.12</li>
</ul>
<h2>3.1.2</h2>
<h3>Fixes</h3>
<ul>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/718">#718</a>
Update README.md</li>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/851">#851</a>
Remove unsupported path_to_write_report argument</li>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/898">#898</a>
codeql-analysis.yml</li>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/901">#901</a>
Update README to contain correct information - inputs and negate
feature</li>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/955">#955</a>
fix: add in all the extra arguments for uploader</li>
</ul>
<h3>Dependencies</h3>
<ul>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/819">#819</a>
build(deps): bump openpgp from 5.4.0 to 5.5.0</li>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/835">#835</a>
build(deps): bump node-fetch from 3.2.4 to 3.2.10</li>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/840">#840</a>
build(deps): bump ossf/scorecard-action from 1.1.1 to 2.0.4</li>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/841">#841</a>
build(deps): bump <code>@​actions/core</code> from 1.9.1 to 1.10.0</li>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/843">#843</a>
build(deps): bump <code>@​actions/github</code> from 5.0.3 to 5.1.1</li>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/869">#869</a>
build(deps): bump node-fetch from 3.2.10 to 3.3.0</li>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/872">#872</a>
build(deps-dev): bump jest-junit from 13.2.0 to 15.0.0</li>
<li><a
href="https://redirect.github.com/codecov/codecov-action/issues/879">#879</a>
build(deps): bump decode-uri-component from 0.2.0 to 0.2.2</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="968872560f"><code>9688725</code></a>
Update README.md</li>
<li><a
href="2112eaec1b"><code>2112eae</code></a>
chore(deps): bump wrapper to 0.0.23 (<a
href="https://redirect.github.com/codecov/codecov-action/issues/1644">#1644</a>)</li>
<li><a
href="193421c5b3"><code>193421c</code></a>
fixL use the correct source (<a
href="https://redirect.github.com/codecov/codecov-action/issues/1642">#1642</a>)</li>
<li><a
href="6018df70b0"><code>6018df7</code></a>
fix: update container builds (<a
href="https://redirect.github.com/codecov/codecov-action/issues/1640">#1640</a>)</li>
<li><a
href="eff1a643d6"><code>eff1a64</code></a>
fix: add missing vars (<a
href="https://redirect.github.com/codecov/codecov-action/issues/1638">#1638</a>)</li>
<li><a
href="4582d54fd3"><code>4582d54</code></a>
Update README.md (<a
href="https://redirect.github.com/codecov/codecov-action/issues/1639">#1639</a>)</li>
<li><a
href="bb7467c2bc"><code>bb7467c</code></a>
feat: use wrapper (<a
href="https://redirect.github.com/codecov/codecov-action/issues/1621">#1621</a>)</li>
<li><a
href="1d6059880c"><code>1d60598</code></a>
build(deps-dev): bump <code>@​typescript-eslint/eslint-plugin</code>
from 8.12.2 to 8.13.0 ...</li>
<li><a
href="e587ce276e"><code>e587ce2</code></a>
build(deps-dev): bump <code>@​typescript-eslint/parser</code> from
8.12.2 to 8.13.0 (<a
href="https://redirect.github.com/codecov/codecov-action/issues/1635">#1635</a>)</li>
<li><a
href="e43f28e103"><code>e43f28e</code></a>
build(deps-dev): bump <code>@​typescript-eslint/parser</code> from
8.11.0 to 8.12.2 (<a
href="https://redirect.github.com/codecov/codecov-action/issues/1628">#1628</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/codecov/codecov-action/compare/v4...v5">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=codecov/codecov-action&package-manager=github_actions&previous-version=4&new-version=5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-18 10:25:02 +00:00
dependabot[bot]
32e3d1b480 feat(deps): bump github.com/aws/aws-sdk-go-v2/config from 1.28.2 to 1.28.3 (#219)
Bumps
[github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2)
from 1.28.2 to 1.28.3.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="2f70834c69"><code>2f70834</code></a>
Release 2024-11-07</li>
<li><a
href="ef9a3c319f"><code>ef9a3c3</code></a>
Regenerated Clients</li>
<li><a
href="c054fe7021"><code>c054fe7</code></a>
Update endpoints model</li>
<li><a
href="b68675cf59"><code>b68675c</code></a>
Update API model</li>
<li><a
href="1d989f31b0"><code>1d989f3</code></a>
send opt-in query-compatible header where applicable (<a
href="https://redirect.github.com/aws/aws-sdk-go-v2/issues/2891">#2891</a>)</li>
<li><a
href="5d0eb2386a"><code>5d0eb23</code></a>
Merge pull request <a
href="https://redirect.github.com/aws/aws-sdk-go-v2/issues/2889">#2889</a>
from aws/customize-identity-store-exception-message</li>
<li><a
href="a39caf38c1"><code>a39caf3</code></a>
adding new line and inline comments</li>
<li><a
href="2ae3246d27"><code>2ae3246</code></a>
refactor logic to use switch case</li>
<li><a
href="7c4bde0ae1"><code>7c4bde0</code></a>
add changelog</li>
<li><a
href="f01c284662"><code>f01c284</code></a>
regenerating clients</li>
<li>Additional commits viewable in <a
href="https://github.com/aws/aws-sdk-go-v2/compare/config/v1.28.2...config/v1.28.3">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/config&package-manager=go_modules&previous-version=1.28.2&new-version=1.28.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-08 10:27:01 +00:00
dependabot[bot]
f6db6f56a1 feat(deps): bump google.golang.org/api from 0.204.0 to 0.205.0 (#217)
Bumps
[google.golang.org/api](https://github.com/googleapis/google-api-go-client)
from 0.204.0 to 0.205.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/googleapis/google-api-go-client/releases">google.golang.org/api's
releases</a>.</em></p>
<blockquote>
<h2>v0.205.0</h2>
<h2><a
href="https://github.com/googleapis/google-api-go-client/compare/v0.204.0...v0.205.0">0.205.0</a>
(2024-11-06)</h2>
<h3>Features</h3>
<ul>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2852">#2852</a>)
(<a
href="e3868f25db">e3868f2</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2855">#2855</a>)
(<a
href="47ea8e4b72">47ea8e4</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2857">#2857</a>)
(<a
href="78320944b8">7832094</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2858">#2858</a>)
(<a
href="eb00c845e2">eb00c84</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2860">#2860</a>)
(<a
href="3347fa1ef8">3347fa1</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md">google.golang.org/api's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/googleapis/google-api-go-client/compare/v0.204.0...v0.205.0">0.205.0</a>
(2024-11-06)</h2>
<h3>Features</h3>
<ul>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2852">#2852</a>)
(<a
href="e3868f25db">e3868f2</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2855">#2855</a>)
(<a
href="47ea8e4b72">47ea8e4</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2857">#2857</a>)
(<a
href="78320944b8">7832094</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2858">#2858</a>)
(<a
href="eb00c845e2">eb00c84</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2860">#2860</a>)
(<a
href="3347fa1ef8">3347fa1</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="69dcf2750e"><code>69dcf27</code></a>
chore(main): release 0.205.0 (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2853">#2853</a>)</li>
<li><a
href="a01d19843e"><code>a01d198</code></a>
chore(all): upgrade cloud.google.com/go/auth to v0.10.1 (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2861">#2861</a>)</li>
<li><a
href="3347fa1ef8"><code>3347fa1</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2860">#2860</a>)</li>
<li><a
href="eb00c845e2"><code>eb00c84</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2858">#2858</a>)</li>
<li><a
href="78320944b8"><code>7832094</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2857">#2857</a>)</li>
<li><a
href="47ea8e4b72"><code>47ea8e4</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2855">#2855</a>)</li>
<li><a
href="e3868f25db"><code>e3868f2</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2852">#2852</a>)</li>
<li>See full diff in <a
href="https://github.com/googleapis/google-api-go-client/compare/v0.204.0...v0.205.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/api&package-manager=go_modules&previous-version=0.204.0&new-version=0.205.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: James Carnegie <kipz@users.noreply.github.com>
2024-11-07 11:33:32 +00:00
dependabot[bot]
6727d529ed feat(deps): bump github.com/aws/aws-sdk-go-v2/config from 1.28.1 to 1.28.2 (#218)
Bumps
[github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2)
from 1.28.1 to 1.28.2.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="70eb57ac77"><code>70eb57a</code></a>
Release 2024-11-06</li>
<li><a
href="cd2c6b1af3"><code>cd2c6b1</code></a>
Regenerated Clients</li>
<li><a
href="2b2a737b17"><code>2b2a737</code></a>
Update API model</li>
<li><a
href="8c9892f042"><code>8c9892f</code></a>
bump smithy-go codegen to latest (<a
href="https://redirect.github.com/aws/aws-sdk-go-v2/issues/2890">#2890</a>)</li>
<li><a
href="82897becac"><code>82897be</code></a>
fix potential for user-agent lang value mismatch in tests (<a
href="https://redirect.github.com/aws/aws-sdk-go-v2/issues/2888">#2888</a>)</li>
<li><a
href="061540b5a7"><code>061540b</code></a>
Cloudfront - add expire time in signed cookie. (<a
href="https://redirect.github.com/aws/aws-sdk-go-v2/issues/2862">#2862</a>)</li>
<li><a
href="aa3bd1f75d"><code>aa3bd1f</code></a>
fix makefile to not spam releases for feature/dynamodb/attributevalue
(<a
href="https://redirect.github.com/aws/aws-sdk-go-v2/issues/2885">#2885</a>)</li>
<li><a
href="eb96051d5b"><code>eb96051</code></a>
Release 2024-11-01</li>
<li><a
href="7f2d000cf7"><code>7f2d000</code></a>
Regenerated Clients</li>
<li><a
href="8542f2f22d"><code>8542f2f</code></a>
Update endpoints model</li>
<li>Additional commits viewable in <a
href="https://github.com/aws/aws-sdk-go-v2/compare/config/v1.28.1...config/v1.28.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/config&package-manager=go_modules&previous-version=1.28.1&new-version=1.28.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-07 09:20:05 +00:00
dependabot[bot]
f7f8802e6c feat(deps): bump github.com/containerd/containerd/v2 from 2.0.0-rc.6 to 2.0.0 (#216)
Bumps
[github.com/containerd/containerd/v2](https://github.com/containerd/containerd)
from 2.0.0-rc.6 to 2.0.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/containerd/containerd/releases">github.com/containerd/containerd/v2's
releases</a>.</em></p>
<blockquote>
<h2>containerd 2.0.0</h2>
<p>Welcome to the v2.0.0 release of containerd!</p>
<p>The first major release of containerd 2.x focuses on the continued
stability of
containerd's core feature set with an easy upgrade from containerd 1.x.
This
release includes the stabilization of new features added in the last 1.x
release
as well as the removal of features which were deprecated in 1.x. The
goal is to
support the vast community of containerd users well into the future
along with
their ever increasing deployment footprints and variety of use
cases.</p>
<p>See <a
href="https://github.com/containerd/containerd/blob/main/docs/containerd-2.0.md">containerd
2.0</a> documentation for details on what is new and has changed in this
release.</p>
<h3>Highlights</h3>
<ul>
<li>Allow sections of Plugins to be merged, and not overwritten as
entire sections. (<a
href="https://redirect.github.com/containerd/containerd/pull/9982">#9982</a>)</li>
<li>Add Update API for sandbox controller (<a
href="https://redirect.github.com/containerd/containerd/pull/9903">#9903</a>)</li>
<li>Configure otel from env instead of config.toml (<a
href="https://redirect.github.com/containerd/containerd/pull/8970">#8970</a>)</li>
<li>Enable NRI by default (<a
href="https://redirect.github.com/containerd/containerd/pull/9744">#9744</a>)</li>
<li>Add PluginInfo to introspection API (<a
href="https://redirect.github.com/containerd/containerd/pull/9442">#9442</a>)</li>
<li>Remove overlayfs volatile option on temp mounts (<a
href="https://redirect.github.com/containerd/containerd/pull/9555">#9555</a>)</li>
<li>Expose usage of deprecated features (<a
href="https://redirect.github.com/containerd/containerd/pull/9258">#9258</a>)</li>
<li>Use Intel ISA-L's igzip if available (<a
href="https://redirect.github.com/containerd/containerd/pull/9200">#9200</a>)</li>
<li>Introduce top level config migration (<a
href="https://redirect.github.com/containerd/containerd/pull/9223">#9223</a>)</li>
<li>Add image delete target (<a
href="https://redirect.github.com/containerd/containerd/pull/8989">#8989</a>)</li>
<li>Remove <code>LimitNOFILE</code> from <code>containerd.service</code>
(<a
href="https://redirect.github.com/containerd/containerd/pull/8924">#8924</a>)</li>
<li>Add support for image expiration during garbage collection (<a
href="https://redirect.github.com/containerd/containerd/pull/9022">#9022</a>)</li>
<li>Reduce the contention between ref lock and boltdb lock in content
store (<a
href="https://redirect.github.com/containerd/containerd/pull/8792">#8792</a>)</li>
<li>Remove &quot;containerd.io/restart.logpath&quot; label (<a
href="https://redirect.github.com/containerd/containerd/pull/8264">#8264</a>)</li>
<li>Remove <code>aufs</code> snapshotter (<a
href="https://redirect.github.com/containerd/containerd/pull/8263">#8263</a>)</li>
<li>Fix deadlock during NRI plugin registration (<a
href="https://redirect.github.com/containerd/nri/pull/79">containerd/nri#79</a>)</li>
<li>Support arm64/v9 and minor variants (<a
href="https://redirect.github.com/containerd/platforms/pull/8">containerd/platforms#8</a>)</li>
<li>Fix deadlock when writing to pipe blocks (<a
href="https://redirect.github.com/containerd/ttrpc/pull/168">containerd/ttrpc#168</a>)</li>
</ul>
<h4>Build and Release Toolchain</h4>
<ul>
<li>Generate attestation for artifacts during release (<a
href="https://redirect.github.com/containerd/containerd/pull/10543">#10543</a>)</li>
<li>Remove <code>cri-containerd-*.tar.gz</code> release bundles (<a
href="https://redirect.github.com/containerd/containerd/pull/9096">#9096</a>)</li>
</ul>
<h4>Container Runtime Interface (CRI)</h4>
<ul>
<li>Use 'UserSpecifiedImage' from CRI to set the image-name annotation
(<a
href="https://redirect.github.com/containerd/containerd/pull/10747">#10747</a>)</li>
<li>Fine-grained SupplementalGroups control (<a
href="https://redirect.github.com/containerd/containerd/pull/9737">#9737</a>)</li>
<li>Add support to set loopback to up (<a
href="https://redirect.github.com/containerd/containerd/pull/10238">#10238</a>)</li>
<li>KEP-3857: Recursive Read-only (RRO) mounts (<a
href="https://redirect.github.com/containerd/containerd/pull/9787">#9787</a>)</li>
<li>Add support for multiple subscribers to CRI container events (<a
href="https://redirect.github.com/containerd/containerd/pull/9661">#9661</a>)</li>
<li>Enable CDI by default (<a
href="https://redirect.github.com/containerd/containerd/pull/9621">#9621</a>)</li>
<li>Remove non-sandboxed CRI implementation (<a
href="https://redirect.github.com/containerd/containerd/pull/9228">#9228</a>)</li>
<li>Add support for userns in stateless and stateful pods with idmap
mounts (KEP-127, k8s &gt;= 1.27) (<a
href="https://redirect.github.com/containerd/containerd/pull/8287">#8287</a>)</li>
<li>Use sandboxed CRI by default (<a
href="https://redirect.github.com/containerd/containerd/pull/8994">#8994</a>)</li>
<li>Implement RuntimeConfig CRI call (<a
href="https://redirect.github.com/containerd/containerd/pull/8722">#8722</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/containerd/containerd/blob/main/RELEASES.md">github.com/containerd/containerd/v2's
changelog</a>.</em></p>
<blockquote>
<h1>Versioning and Release</h1>
<p>This document details the versioning and release plan for containerd.
Stability
is a top goal for this project, and we hope that this document and the
processes
it entails will help to achieve that. It covers the release process,
versioning
numbering, backporting, API stability and support horizons.</p>
<p>If you rely on containerd, it would be good to spend time
understanding the
areas of the API that are and are not supported and how they impact your
project in the future.</p>
<p>This document will be considered a living document. Supported
timelines,
backport targets and API stability guarantees will be updated here as
they
change.</p>
<p>If there is something that you require or this document leaves out,
please
reach out by <a
href="https://github.com/containerd/containerd/issues">filing an
issue</a>.</p>
<h2>Releases</h2>
<p>Releases of containerd will be versioned using dotted triples,
similar to
<a href="http://semver.org/">Semantic Version</a>. For the purposes of
this document, we
will refer to the respective components of this triple as
<code>&lt;major&gt;.&lt;minor&gt;.&lt;patch&gt;</code>. The version
number may have additional information,
such as alpha, beta and release candidate qualifications. Such releases
will be
considered &quot;pre-releases&quot;.</p>
<h3>Major and Minor Releases</h3>
<p>Major and minor releases of containerd will be made from main.
Releases of
containerd will be marked with GPG signed tags and announced at
<a
href="https://github.com/containerd/containerd/releases">https://github.com/containerd/containerd/releases</a>.
The tag will be of the
format <code>v&lt;major&gt;.&lt;minor&gt;.&lt;patch&gt;</code> and
should be made with the command <code>git tag -s
v&lt;major&gt;.&lt;minor&gt;.&lt;patch&gt;</code>.</p>
<p>After a minor release, a branch will be created, with the format
<code>release/&lt;major&gt;.&lt;minor&gt;</code> from the minor tag. All
further patch releases will
be done from that branch. For example, once we release
<code>v1.0.0</code>, a branch
<code>release/1.0</code> will be created from that tag. All future patch
releases will be
done against that branch.</p>
<h3>Pre-releases</h3>
<p>Pre-releases, such as alphas, betas and release candidates will be
conducted
from their source branch. For major and minor releases, these releases
will be
done from main. For patch releases, these pre-releases should be done
within
the corresponding release branch.</p>
<p>While pre-releases are done to assist in the stabilization process,
no
guarantees are provided.</p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="207ad711ea"><code>207ad71</code></a>
Merge pull request <a
href="https://redirect.github.com/containerd/containerd/issues/10939">#10939</a>
from dmcgowan/prepare-v2.0.0</li>
<li><a
href="03ba4ce1f7"><code>03ba4ce</code></a>
Update release notes for v2.0.0</li>
<li><a
href="f2da3fd688"><code>f2da3fd</code></a>
Update release docs for v2.0.0</li>
<li><a
href="6369206870"><code>6369206</code></a>
Merge pull request <a
href="https://redirect.github.com/containerd/containerd/issues/10954">#10954</a>
from dmcgowan/update-typeurl-2.2.2</li>
<li><a
href="ff09b428e1"><code>ff09b42</code></a>
Update typeurl to v2.2.2</li>
<li><a
href="18caa33fdc"><code>18caa33</code></a>
Merge pull request <a
href="https://redirect.github.com/containerd/containerd/issues/10944">#10944</a>
from containerd/dependabot/github_actions/softprops...</li>
<li><a
href="545605d5b4"><code>545605d</code></a>
Merge pull request <a
href="https://redirect.github.com/containerd/containerd/issues/10945">#10945</a>
from containerd/dependabot/github_actions/google-gi...</li>
<li><a
href="71c274bb81"><code>71c274b</code></a>
Merge pull request <a
href="https://redirect.github.com/containerd/containerd/issues/10947">#10947</a>
from containerd/dependabot/go_modules/github.com/co...</li>
<li><a
href="e841240997"><code>e841240</code></a>
Merge pull request <a
href="https://redirect.github.com/containerd/containerd/issues/10946">#10946</a>
from containerd/dependabot/go_modules/github.com/co...</li>
<li><a
href="9fe6f7c067"><code>9fe6f7c</code></a>
Merge pull request <a
href="https://redirect.github.com/containerd/containerd/issues/10943">#10943</a>
from containerd/dependabot/github_actions/google-gi...</li>
<li>Additional commits viewable in <a
href="https://github.com/containerd/containerd/compare/v2.0.0-rc.6...v2.0.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/containerd/containerd/v2&package-manager=go_modules&previous-version=2.0.0-rc.6&new-version=2.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-06 12:16:34 +00:00
dependabot[bot]
1fd228fb5c feat(deps): bump github.com/open-policy-agent/opa from 0.69.0 to 0.70.0 (#215)
Bumps
[github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa)
from 0.69.0 to 0.70.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/open-policy-agent/opa/releases">github.com/open-policy-agent/opa's
releases</a>.</em></p>
<blockquote>
<h2>v0.70.0</h2>
<p>This release contains a mix of features, performance improvements,
and bugfixes.</p>
<h3>Optimized read mode for OPA's in-memory store (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7125">#7125</a>)</h3>
<p>A new optimized read mode has been added to the default in-memory
store, where data written to the store is eagerly converted
to AST values (the data format used during evaluation). This removes the
time spent converting raw data values to AST
during policy evaluation, thereby improving performance.</p>
<p>The memory footprint of the store will increase, as processed AST
values generally take up more space in memory than the
corresponding raw data values, but overall memory usage of OPA might
remain more stable over time, as pre-converted data
is shared across evaluations and isn't recomputed for each evaluation,
which can cause spikes in memory usage.</p>
<p>This mode can be enabled for <code>opa run</code>, <code>opa
eval</code>, and <code>opa bench</code> by setting the
<code>--optimize-store-for-read-speed</code> flag.</p>
<p>More information about this feature can be found <a
href="https://www.openpolicyagent.org/docs/v0.70.0/policy-performance/#storage-optimization">here</a>.</p>
<p>Co-authored by <a
href="https://github.com/johanfylling"><code>@​johanfylling</code></a>
and <a
href="https://github.com/ashutosh-narkar"><code>@​ashutosh-narkar</code></a>.</p>
<h3>Topdown and Rego</h3>
<ul>
<li>topdown: Use new Inter-Query Value Cache for
<code>json.match_schema</code> built-in function (<a
href="https://redirect.github.com/open-policy-agent/opa/issues/7011">#7011</a>)
authored by <a
href="https://github.com/anderseknert"><code>@​anderseknert</code></a>
reported by <a
href="https://github.com/lcarva"><code>@​lcarva</code></a></li>
<li>ast: Fix location text attribute for multi-value rules with
generated body (<a
href="https://redirect.github.com/open-policy-agent/opa/issues/7128">#7128</a>)
authored by <a
href="https://github.com/anderseknert"><code>@​anderseknert</code></a></li>
<li>ast: Fix regression in <code>opa check</code> where a file that
referenced non-provided schemas failed validation (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7124">#7124</a>)
authored by <a
href="https://github.com/tjons"><code>@​tjons</code></a></li>
<li>test/cases/testdata: Fix bug in test by replacing unification by
explicit equality check (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7093">#7093</a>)
authored by <a
href="https://github.com/matajoh"><code>@​matajoh</code></a></li>
<li>ast: Replace use of yaml.v2 library with yaml.v3. The earlier
version would parse <code>yes</code>/<code>no</code> values as boolean.
The usage of yaml.v2 in the parser was unintentional and now has been
updated to yaml.v3 (<a
href="https://redirect.github.com/open-policy-agent/opa/issues/7090">#7090</a>)
authored by <a
href="https://github.com/anderseknert"><code>@​anderseknert</code></a></li>
</ul>
<h3>Runtime, Tooling, SDK</h3>
<ul>
<li>cmd: Make <code>opa check</code> respect <code>--ignore</code> when
<code>--bundle</code> flag is set (<a
href="https://redirect.github.com/open-policy-agent/opa/issues/7136">#7136</a>)
authored by <a
href="https://github.com/anderseknert"><code>@​anderseknert</code></a></li>
<li>server/writer: Properly handle result encoding errors which earlier
on failure would emit logs such as <code>superfluous call to
WriteHeader()</code> while still returning <code>200</code> HTTP status
code. Now, errors encoding the payload properly lead to <code>500</code>
HTTP status code, without extra logs. Also use Header().Set() not
Header().Add() to avoid duplicate content-type headers (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7114">#7114</a>)
authored by <a
href="https://github.com/srenatus"><code>@​srenatus</code></a></li>
<li>cmd: Support <code>file://</code> format for TLS key material file
flags in <code>opa run</code> (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7094">#7094</a>)
authored by <a
href="https://github.com/alexrohozneanu"><code>@​alexrohozneanu</code></a></li>
<li>plugins/rest/azure: Support managed identity for App Service /
Container Apps (<a
href="https://redirect.github.com/open-policy-agent/opa/issues/7085">#7085</a>)
reported and authored by <a
href="https://github.com/apc-kamezaki"><code>@​apc-kamezaki</code></a></li>
<li>debug: Fix step-over behaviour when exiting partial rules (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7096">#7096</a>)
authored by <a
href="https://github.com/johanfylling"><code>@​johanfylling</code></a></li>
<li>util+plugins: Fix potential memory leaks with explicit timer
cancellation (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7089">#7089</a>)
authored by <a
href="https://github.com/philipaconrad"><code>@​philipaconrad</code></a></li>
</ul>
<h3>Docs, Website, Ecosystem</h3>
<ul>
<li>docs: Fix OCI example with updated flag used by the ORAS CLI (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7130">#7130</a>)
authored by <a
href="https://github.com/b3n3d17"><code>@​b3n3d17</code></a></li>
<li>docs: Delete Atom editor from supported editor integrations (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7111">#7111</a>)
authored by <a
href="https://github.com/KaranbirSingh7"><code>@​KaranbirSingh7</code></a></li>
<li>docs/website: Add Styra OPA ASP.NET Core SDK integration (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7073">#7073</a>)
authored by <a
href="https://github.com/philipaconrad"><code>@​philipaconrad</code></a></li>
<li>docs/website: Update compatibility information on the rego-cpp
integration (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7078">#7078</a>)
authored by <a
href="https://github.com/matajoh"><code>@​matajoh</code></a></li>
</ul>
<h3>Miscellaneous</h3>
<ul>
<li>Dependency updates; notably:
<ul>
<li>build(deps): bump github.com/containerd/containerd from 1.7.22 to
1.7.23</li>
<li>build(deps): bump github.com/prometheus/client_golang from 1.20.4 to
1.20.5</li>
<li>build(deps): bump golang.org/x/net from 0.29.0 to 0.30.0</li>
<li>build(deps): bump golang.org/x/time from 0.6.0 to 0.7.0</li>
<li>build(deps): bump google.golang.org/grpc from 1.67.0 to 1.67.1</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/open-policy-agent/opa/blob/main/CHANGELOG.md">github.com/open-policy-agent/opa's
changelog</a>.</em></p>
<blockquote>
<h2>0.70.0</h2>
<p>This release contains a mix of features, performance improvements,
and bugfixes.</p>
<h3>Optimized read mode for OPA's in-memory store (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7125">#7125</a>)</h3>
<p>A new optimized read mode has been added to the default in-memory
store, where data written to the store is eagerly converted
to AST values (the data format used during evaluation). This removes the
time spent converting raw data values to AST
during policy evaluation, thereby improving performance.</p>
<p>The memory footprint of the store will increase, as processed AST
values generally take up more space in memory than the
corresponding raw data values, but overall memory usage of OPA might
remain more stable over time, as pre-converted data
is shared across evaluations and isn't recomputed for each evaluation,
which can cause spikes in memory usage.</p>
<p>This mode can be enabled for <code>opa run</code>, <code>opa
eval</code>, and <code>opa bench</code> by setting the
<code>--optimize-store-for-read-speed</code> flag.</p>
<p>More information about this feature can be found <a
href="https://www.openpolicyagent.org/docs/v0.70.0/policy-performance/#storage-optimization">here</a>.</p>
<p>Co-authored by <a
href="https://github.com/johanfylling"><code>@​johanfylling</code></a>
and <a
href="https://github.com/ashutosh-narkar"><code>@​ashutosh-narkar</code></a>.</p>
<h3>Topdown and Rego</h3>
<ul>
<li>topdown: Use new Inter-Query Value Cache for
<code>json.match_schema</code> built-in function (<a
href="https://redirect.github.com/open-policy-agent/opa/issues/7011">#7011</a>)
authored by <a
href="https://github.com/anderseknert"><code>@​anderseknert</code></a>
reported by <a
href="https://github.com/lcarva"><code>@​lcarva</code></a></li>
<li>ast: Fix location text attribute for multi-value rules with
generated body (<a
href="https://redirect.github.com/open-policy-agent/opa/issues/7128">#7128</a>)
authored by <a
href="https://github.com/anderseknert"><code>@​anderseknert</code></a></li>
<li>ast: Fix regression in <code>opa check</code> where a file that
referenced non-provided schemas failed validation (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7124">#7124</a>)
authored by <a
href="https://github.com/tjons"><code>@​tjons</code></a></li>
<li>test/cases/testdata: Fix bug in test by replacing unification by
explicit equality check (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7093">#7093</a>)
authored by <a
href="https://github.com/matajoh"><code>@​matajoh</code></a></li>
<li>ast: Replace use of yaml.v2 library with yaml.v3. The earlier
version would parse <code>yes</code>/<code>no</code> values as boolean.
The usage of yaml.v2 in the parser was unintentional and now has been
updated to yaml.v3 (<a
href="https://redirect.github.com/open-policy-agent/opa/issues/7090">#7090</a>)
authored by <a
href="https://github.com/anderseknert"><code>@​anderseknert</code></a></li>
</ul>
<h3>Runtime, Tooling, SDK</h3>
<ul>
<li>cmd: Make <code>opa check</code> respect <code>--ignore</code> when
<code>--bundle</code> flag is set (<a
href="https://redirect.github.com/open-policy-agent/opa/issues/7136">#7136</a>)
authored by <a
href="https://github.com/anderseknert"><code>@​anderseknert</code></a></li>
<li>server/writer: Properly handle result encoding errors which earlier
on failure would emit logs such as <code>superfluous call to
WriteHeader()</code> while still returning <code>200</code> HTTP status
code. Now, errors encoding the payload properly lead to <code>500</code>
HTTP status code, without extra logs. Also use Header().Set() not
Header().Add() to avoid duplicate content-type headers (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7114">#7114</a>)
authored by <a
href="https://github.com/srenatus"><code>@​srenatus</code></a></li>
<li>cmd: Support <code>file://</code> format for TLS key material file
flags in <code>opa run</code> (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7094">#7094</a>)
authored by <a
href="https://github.com/alexrohozneanu"><code>@​alexrohozneanu</code></a></li>
<li>plugins/rest/azure: Support managed identity for App Service /
Container Apps (<a
href="https://redirect.github.com/open-policy-agent/opa/issues/7085">#7085</a>)
reported and authored by <a
href="https://github.com/apc-kamezaki"><code>@​apc-kamezaki</code></a></li>
<li>debug: Fix step-over behaviour when exiting partial rules (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7096">#7096</a>)
authored by <a
href="https://github.com/johanfylling"><code>@​johanfylling</code></a></li>
<li>util+plugins: Fix potential memory leaks with explicit timer
cancellation (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7089">#7089</a>)
authored by <a
href="https://github.com/philipaconrad"><code>@​philipaconrad</code></a></li>
</ul>
<h3>Docs, Website, Ecosystem</h3>
<ul>
<li>docs: Fix OCI example with updated flag used by the ORAS CLI (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7130">#7130</a>)
authored by <a
href="https://github.com/b3n3d17"><code>@​b3n3d17</code></a></li>
<li>docs: Delete Atom editor from supported editor integrations (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7111">#7111</a>)
authored by <a
href="https://github.com/KaranbirSingh7"><code>@​KaranbirSingh7</code></a></li>
<li>docs/website: Add Styra OPA ASP.NET Core SDK integration (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7073">#7073</a>)
authored by <a
href="https://github.com/philipaconrad"><code>@​philipaconrad</code></a></li>
<li>docs/website: Update compatibility information on the rego-cpp
integration (<a
href="https://redirect.github.com/open-policy-agent/opa/pull/7078">#7078</a>)
authored by <a
href="https://github.com/matajoh"><code>@​matajoh</code></a></li>
</ul>
<h3>Miscellaneous</h3>
<ul>
<li>Dependency updates; notably:
<ul>
<li>build(deps): bump github.com/containerd/containerd from 1.7.22 to
1.7.23</li>
<li>build(deps): bump github.com/prometheus/client_golang from 1.20.4 to
1.20.5</li>
<li>build(deps): bump golang.org/x/net from 0.29.0 to 0.30.0</li>
<li>build(deps): bump golang.org/x/time from 0.6.0 to 0.7.0</li>
<li>build(deps): bump google.golang.org/grpc from 1.67.0 to 1.67.1</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="2ea031ea04"><code>2ea031e</code></a>
Prepare v0.70.0 release</li>
<li><a
href="6af5e79bd9"><code>6af5e79</code></a>
storage: Optimized read mode for default data storage</li>
<li><a
href="1b797d9c1b"><code>1b797d9</code></a>
Make <code>opa check</code> respect <code>--ignore</code> when
<code>--bundle</code> flag is set (<a
href="https://redirect.github.com/open-policy-agent/opa/issues/7137">#7137</a>)</li>
<li><a
href="8e44b98993"><code>8e44b98</code></a>
build(deps): bump actions/setup-go from 5.0.2 to 5.1.0 (<a
href="https://redirect.github.com/open-policy-agent/opa/issues/7138">#7138</a>)</li>
<li><a
href="ad6ffdae6a"><code>ad6ffda</code></a>
build(deps): bump actions/checkout from 4.2.1 to 4.2.2 (<a
href="https://redirect.github.com/open-policy-agent/opa/issues/7135">#7135</a>)</li>
<li><a
href="67fe53bfbe"><code>67fe53b</code></a>
Update Andrew Peabody to emeritus (<a
href="https://redirect.github.com/open-policy-agent/opa/issues/7133">#7133</a>)</li>
<li><a
href="30f374713b"><code>30f3747</code></a>
build(deps): bump github/codeql-action from 3.26.13 to 3.27.0</li>
<li><a
href="f7957bdd73"><code>f7957bd</code></a>
🐛 fix: oras cli changed to --config</li>
<li><a
href="58ec50b4b0"><code>58ec50b</code></a>
Fix location for multivalue rules with generated bodies (<a
href="https://redirect.github.com/open-policy-agent/opa/issues/7129">#7129</a>)</li>
<li><a
href="555fe84094"><code>555fe84</code></a>
only check schemas when schemas are provided (<a
href="https://redirect.github.com/open-policy-agent/opa/issues/7124">#7124</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/open-policy-agent/opa/compare/v0.69.0...v0.70.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/open-policy-agent/opa&package-manager=go_modules&previous-version=0.69.0&new-version=0.70.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-04 08:46:23 +00:00
dependabot[bot]
d481832f61 feat(deps): bump google.golang.org/api from 0.203.0 to 0.204.0 (#214)
Bumps
[google.golang.org/api](https://github.com/googleapis/google-api-go-client)
from 0.203.0 to 0.204.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/googleapis/google-api-go-client/releases">google.golang.org/api's
releases</a>.</em></p>
<blockquote>
<h2>v0.204.0</h2>
<h2><a
href="https://github.com/googleapis/google-api-go-client/compare/v0.203.0...v0.204.0">0.204.0</a>
(2024-10-31)</h2>
<h3>Features</h3>
<ul>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2837">#2837</a>)
(<a
href="343ae0e822">343ae0e</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2839">#2839</a>)
(<a
href="37b271e98c">37b271e</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2841">#2841</a>)
(<a
href="fb3747b8f9">fb3747b</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2842">#2842</a>)
(<a
href="7221d2c798">7221d2c</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2844">#2844</a>)
(<a
href="56c5ddb8ea">56c5ddb</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2845">#2845</a>)
(<a
href="9d5f008642">9d5f008</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2848">#2848</a>)
(<a
href="5bc448d649">5bc448d</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2850">#2850</a>)
(<a
href="7955ec454d">7955ec4</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li><strong>transport/grpc:</strong> Pass through cert source to new
auth lib (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2840">#2840</a>)
(<a
href="c67e7c09f9">c67e7c0</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Mark WithUniverseDomain as stable (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2847">#2847</a>)
(<a
href="29e20f6029">29e20f6</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md">google.golang.org/api's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/googleapis/google-api-go-client/compare/v0.203.0...v0.204.0">0.204.0</a>
(2024-10-31)</h2>
<h3>Features</h3>
<ul>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2837">#2837</a>)
(<a
href="343ae0e822">343ae0e</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2839">#2839</a>)
(<a
href="37b271e98c">37b271e</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2841">#2841</a>)
(<a
href="fb3747b8f9">fb3747b</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2842">#2842</a>)
(<a
href="7221d2c798">7221d2c</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2844">#2844</a>)
(<a
href="56c5ddb8ea">56c5ddb</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2845">#2845</a>)
(<a
href="9d5f008642">9d5f008</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2848">#2848</a>)
(<a
href="5bc448d649">5bc448d</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2850">#2850</a>)
(<a
href="7955ec454d">7955ec4</a>)</li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li><strong>transport/grpc:</strong> Pass through cert source to new
auth lib (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2840">#2840</a>)
(<a
href="c67e7c09f9">c67e7c0</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>Mark WithUniverseDomain as stable (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2847">#2847</a>)
(<a
href="29e20f6029">29e20f6</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="bcf158044a"><code>bcf1580</code></a>
chore(main): release 0.204.0 (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2838">#2838</a>)</li>
<li><a
href="c67e7c09f9"><code>c67e7c0</code></a>
fix(transport/grpc): pass through cert source to new auth lib (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2840">#2840</a>)</li>
<li><a
href="29e20f6029"><code>29e20f6</code></a>
docs: mark WithUniverseDomain as stable (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2847">#2847</a>)</li>
<li><a
href="4b4eacf4f2"><code>4b4eacf</code></a>
chore: bump auth deps (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2851">#2851</a>)</li>
<li><a
href="7955ec454d"><code>7955ec4</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2850">#2850</a>)</li>
<li><a
href="5bc448d649"><code>5bc448d</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2848">#2848</a>)</li>
<li><a
href="9d5f008642"><code>9d5f008</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2845">#2845</a>)</li>
<li><a
href="48dda95162"><code>48dda95</code></a>
chore(all): update all to 324edc3 (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2843">#2843</a>)</li>
<li><a
href="56c5ddb8ea"><code>56c5ddb</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2844">#2844</a>)</li>
<li><a
href="7221d2c798"><code>7221d2c</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2842">#2842</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/googleapis/google-api-go-client/compare/v0.203.0...v0.204.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/api&package-manager=go_modules&previous-version=0.203.0&new-version=0.204.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-04 08:42:08 +00:00
dependabot[bot]
dbac7405c7 feat(deps): bump github.com/aws/aws-sdk-go-v2/config from 1.28.0 to 1.28.1 (#213)
Bumps
[github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2)
from 1.28.0 to 1.28.1.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="6b53348f84"><code>6b53348</code></a>
Release 2024-10-28</li>
<li><a
href="784d2d39b0"><code>784d2d3</code></a>
Regenerated Clients</li>
<li><a
href="7258bd236c"><code>7258bd2</code></a>
Update endpoints model</li>
<li><a
href="f322198c04"><code>f322198</code></a>
Update API model</li>
<li><a
href="b65b80a89b"><code>b65b80a</code></a>
Merge pull request <a
href="https://redirect.github.com/aws/aws-sdk-go-v2/issues/2852">#2852</a>
from RanVaknin/signature-header-parsing-fix</li>
<li><a
href="803614d34f"><code>803614d</code></a>
Fixing changelog description and implementation to use TrimSpace</li>
<li><a
href="b12c8cf885"><code>b12c8cf</code></a>
adding changelog</li>
<li><a
href="f0caa97e86"><code>f0caa97</code></a>
patching GetSignedRequestSignature to cover edge cases with the
signature</li>
<li><a
href="e05890387e"><code>e058903</code></a>
drop service/nimble (<a
href="https://redirect.github.com/aws/aws-sdk-go-v2/issues/2851">#2851</a>)</li>
<li><a
href="896793a682"><code>896793a</code></a>
Release 2024-10-25</li>
<li>Additional commits viewable in <a
href="https://github.com/aws/aws-sdk-go-v2/compare/v1.28.0...config/v1.28.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/aws-sdk-go-v2/config&package-manager=go_modules&previous-version=1.28.0&new-version=1.28.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-04 08:33:57 +00:00
dependabot[bot]
868e44228e feat(deps): bump github.com/containerd/containerd/v2 from 2.0.0-rc.5 to 2.0.0-rc.6 (#212)
Bumps
[github.com/containerd/containerd/v2](https://github.com/containerd/containerd)
from 2.0.0-rc.5 to 2.0.0-rc.6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/containerd/containerd/releases">github.com/containerd/containerd/v2's
releases</a>.</em></p>
<blockquote>
<h2>containerd 2.0.0-rc.6</h2>
<p>Welcome to the v2.0.0-rc.6 release of containerd!
<em>This is a pre-release of containerd</em></p>
<p>The first major release of containerd 2.x focuses on the continued
stability of
containerd's core feature set with an easy upgrade from containerd 1.x.
This
release includes the stabilization of new features added in the last 1.x
release
as well as the removal of features which were deprecated in 1.x. The
goal is to
support the vast community of containerd users well into the future
along with
their ever increasing deployment footprints and variety of use
cases.</p>
<h3>Highlights</h3>
<ul>
<li>Allow sections of Plugins to be merged, and not overwritten as
entire sections. (<a
href="https://redirect.github.com/containerd/containerd/pull/9982">#9982</a>)</li>
<li>Add Update API for sandbox controller (<a
href="https://redirect.github.com/containerd/containerd/pull/9903">#9903</a>)</li>
<li>Configure otel from env instead of config.toml (<a
href="https://redirect.github.com/containerd/containerd/pull/8970">#8970</a>)</li>
<li>Enable NRI by default (<a
href="https://redirect.github.com/containerd/containerd/pull/9744">#9744</a>)</li>
<li>Add PluginInfo to introspection API (<a
href="https://redirect.github.com/containerd/containerd/pull/9442">#9442</a>)</li>
<li>Remove overlayfs volatile option on temp mounts (<a
href="https://redirect.github.com/containerd/containerd/pull/9555">#9555</a>)</li>
<li>Expose usage of deprecated features (<a
href="https://redirect.github.com/containerd/containerd/pull/9258">#9258</a>)</li>
<li>Use Intel ISA-L's igzip if available (<a
href="https://redirect.github.com/containerd/containerd/pull/9200">#9200</a>)</li>
<li>Introduce top level config migration (<a
href="https://redirect.github.com/containerd/containerd/pull/9223">#9223</a>)</li>
<li>Add image delete target (<a
href="https://redirect.github.com/containerd/containerd/pull/8989">#8989</a>)</li>
<li>Remove <code>LimitNOFILE</code> from <code>containerd.service</code>
(<a
href="https://redirect.github.com/containerd/containerd/pull/8924">#8924</a>)</li>
<li>Add support for image expiration during garbage collection (<a
href="https://redirect.github.com/containerd/containerd/pull/9022">#9022</a>)</li>
<li>Reduce the contention between ref lock and boltdb lock in content
store (<a
href="https://redirect.github.com/containerd/containerd/pull/8792">#8792</a>)</li>
<li>Remove &quot;containerd.io/restart.logpath&quot; label (<a
href="https://redirect.github.com/containerd/containerd/pull/8264">#8264</a>)</li>
<li>Remove <code>aufs</code> snapshotter (<a
href="https://redirect.github.com/containerd/containerd/pull/8263">#8263</a>)</li>
<li>Fix deadlock during NRI plugin registration (<a
href="https://redirect.github.com/containerd/nri/pull/79">containerd/nri#79</a>)</li>
<li>Fix deadlock when writing to pipe blocks (<a
href="https://redirect.github.com/containerd/ttrpc/pull/168">containerd/ttrpc#168</a>)</li>
</ul>
<h4>Build and Release Toolchain</h4>
<ul>
<li>Generate attestation for artifacts during release (<a
href="https://redirect.github.com/containerd/containerd/pull/10543">#10543</a>)</li>
<li>Remove <code>cri-containerd-*.tar.gz</code> release bundles (<a
href="https://redirect.github.com/containerd/containerd/pull/9096">#9096</a>)</li>
</ul>
<h4>Container Runtime Interface (CRI)</h4>
<ul>
<li>Use 'UserSpecifiedImage' from CRI to set the image-name annotation
(<a
href="https://redirect.github.com/containerd/containerd/pull/10747">#10747</a>)</li>
<li>Fine-grained SupplementalGroups control (<a
href="https://redirect.github.com/containerd/containerd/pull/9737">#9737</a>)</li>
<li>Add support to set loopback to up (<a
href="https://redirect.github.com/containerd/containerd/pull/10238">#10238</a>)</li>
<li>Add support for multiple subscribers to CRI container events (<a
href="https://redirect.github.com/containerd/containerd/pull/9661">#9661</a>)</li>
<li>Enable CDI by default (<a
href="https://redirect.github.com/containerd/containerd/pull/9621">#9621</a>)</li>
<li>Remove non-sandboxed CRI implementation (<a
href="https://redirect.github.com/containerd/containerd/pull/9228">#9228</a>)</li>
<li>Add support for userns in stateless and stateful pods with idmap
mounts (KEP-127, k8s &gt;= 1.27) (<a
href="https://redirect.github.com/containerd/containerd/pull/8287">#8287</a>)</li>
<li>Use sandboxed CRI by default (<a
href="https://redirect.github.com/containerd/containerd/pull/8994">#8994</a>)</li>
<li>Implement RuntimeConfig CRI call (<a
href="https://redirect.github.com/containerd/containerd/pull/8722">#8722</a>)</li>
<li>Add support for user namespaces (KEP-127) (<a
href="https://redirect.github.com/containerd/containerd/pull/8803">#8803</a>)</li>
<li>Remove CRI v1alpha2 (<a
href="https://redirect.github.com/containerd/containerd/pull/8276">#8276</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="b70cce2085"><code>b70cce2</code></a>
Merge pull request <a
href="https://redirect.github.com/containerd/containerd/issues/10887">#10887</a>
from dmcgowan/prepare-v2.0.0-rc.6</li>
<li><a
href="5c65a3d7b0"><code>5c65a3d</code></a>
Update version to v2.0.0-rc.6</li>
<li><a
href="9aa637b22d"><code>9aa637b</code></a>
Update api vendor to latest</li>
<li><a
href="574f0daa3e"><code>574f0da</code></a>
Merge pull request <a
href="https://redirect.github.com/containerd/containerd/issues/10884">#10884</a>
from samuelkarp/nri-0.7.0</li>
<li><a
href="4b9d6c0144"><code>4b9d6c0</code></a>
deps: bump github.com/containerd/nri</li>
<li><a
href="651757761f"><code>6517577</code></a>
Merge pull request <a
href="https://redirect.github.com/containerd/containerd/issues/10864">#10864</a>
from djdongjin/dedup-cri-util</li>
<li><a
href="deccefc8cf"><code>deccefc</code></a>
Merge pull request <a
href="https://redirect.github.com/containerd/containerd/issues/9982">#9982</a>
from rayburgemeestre/merge-toml-configurations-for-p...</li>
<li><a
href="e370f0e31c"><code>e370f0e</code></a>
Merge pull request <a
href="https://redirect.github.com/containerd/containerd/issues/10882">#10882</a>
from samuelkarp/containerd-2.0-guide</li>
<li><a
href="bc819bc97a"><code>bc819bc</code></a>
docs: add command for finding schema 1 images</li>
<li><a
href="18654db80a"><code>18654db</code></a>
Merge pull request <a
href="https://redirect.github.com/containerd/containerd/issues/10881">#10881</a>
from samuelkarp/containerd-2.0-guide</li>
<li>Additional commits viewable in <a
href="https://github.com/containerd/containerd/compare/v2.0.0-rc.5...v2.0.0-rc.6">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/containerd/containerd/v2&package-manager=go_modules&previous-version=2.0.0-rc.5&new-version=2.0.0-rc.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-24 09:05:49 +00:00
dependabot[bot]
31d303ff9c feat(deps): bump google.golang.org/api from 0.202.0 to 0.203.0 (#211)
Bumps
[google.golang.org/api](https://github.com/googleapis/google-api-go-client)
from 0.202.0 to 0.203.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/googleapis/google-api-go-client/releases">google.golang.org/api's
releases</a>.</em></p>
<blockquote>
<h2>v0.203.0</h2>
<h2><a
href="https://github.com/googleapis/google-api-go-client/compare/v0.202.0...v0.203.0">0.203.0</a>
(2024-10-23)</h2>
<h3>Features</h3>
<ul>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2834">#2834</a>)
(<a
href="c77b5f4cd2">c77b5f4</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md">google.golang.org/api's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/googleapis/google-api-go-client/compare/v0.202.0...v0.203.0">0.203.0</a>
(2024-10-23)</h2>
<h3>Features</h3>
<ul>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2834">#2834</a>)
(<a
href="c77b5f4cd2">c77b5f4</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="5ca1495a58"><code>5ca1495</code></a>
chore(main): release 0.203.0 (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2835">#2835</a>)</li>
<li><a
href="71d3f5c68e"><code>71d3f5c</code></a>
chore(all): upgrade cloud.google.com/go/auth to v0.9.9 (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2836">#2836</a>)</li>
<li><a
href="c77b5f4cd2"><code>c77b5f4</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/2834">#2834</a>)</li>
<li>See full diff in <a
href="https://github.com/googleapis/google-api-go-client/compare/v0.202.0...v0.203.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/api&package-manager=go_modules&previous-version=0.202.0&new-version=0.203.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-24 10:03:31 +01:00
dependabot[bot]
b0d6219e34 feat(deps): bump google.golang.org/api from 0.201.0 to 0.202.0 (#210)
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.201.0 to 0.202.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.201.0...v0.202.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-23 13:37:33 +01:00
Jonny Stoten
b4a9283ec3 Update go git (#209) 2024-10-22 15:31:55 +01:00
Jonny Stoten
ca97a23d07 Skip DCO requirement for org members (#208)
Signed-off-by: Jonny Stoten <jonny.stoten@docker.com>
2024-10-22 14:41:44 +01:00
Jonny Stoten
a078fba81d feat: add internal reproducible git checksum builtin (#203)
Adds a new rego builtin `attest.internals.reproducible_git_checksum`.
This is needed for verifying DOI provenance, see
https://github.com/docker/doi-image-policy/blob/main/slsa.md#doi-build-reproducible-git-checksum.

We use https://github.com/go-git/go-git for as much of this as possible,
but it doesn't support the actual archive operation, so we shell out to
`git` for that.

There is some similar unexported code in bashbrew, and we should
probably be using the same code in the build process as we are here.
I'll create a follow-up ticket to sort that out.
2024-10-22 14:30:27 +01:00
Joel Kamp
3cf2d929f7 Merge pull request #206 from docker/feat-add-code-of-conduct
feat: add code of conduct
2024-10-21 10:09:26 -05:00
mrjoelkamp
c7b2ebefac feat: add code of conduct
Signed-off-by: mrjoelkamp <joel.kamp@docker.com>
2024-10-21 10:00:36 -05:00
Joel Kamp
85cf56de49 Merge pull request #205 from docker/feat-add-pr-issue-templates
feat: add pr and issue templates
2024-10-18 10:00:53 -05:00
mrjoelkamp
f426fa367c feat: add pr and issue templates 2024-10-18 09:55:27 -05:00
Joel Kamp
c7c3d23717 Merge pull request #204 from docker/chore-apply-license
chore: apply license headers
2024-10-18 09:45:31 -05:00
mrjoelkamp
01a6a2ab7d refactor: remove copyright year; add newline 2024-10-18 09:25:31 -05:00
mrjoelkamp
6fd73fe45d chore: add notice 2024-10-17 14:08:33 -05:00
mrjoelkamp
0215b620cd chore: apply license headers 2024-10-17 13:43:30 -05:00
Joel Kamp
79bbc9b55b Merge pull request #198 from docker/dependabot/go_modules/github.com/sigstore/sigstore/pkg/signature/kms/aws-1.8.10
feat(deps): bump github.com/sigstore/sigstore/pkg/signature/kms/aws from 1.8.9 to 1.8.10
2024-10-17 08:31:45 -05:00
Joel Kamp
47669993c6 Merge branch 'main' into dependabot/go_modules/github.com/sigstore/sigstore/pkg/signature/kms/aws-1.8.10 2024-10-17 08:25:14 -05:00
Joel Kamp
7414fb7339 Merge pull request #199 from docker/dependabot/go_modules/github.com/sigstore/sigstore/pkg/signature/kms/gcp-1.8.10
feat(deps): bump github.com/sigstore/sigstore/pkg/signature/kms/gcp from 1.8.9 to 1.8.10
2024-10-17 08:24:47 -05:00
dependabot[bot]
0e1005d0f7 feat(deps): bump github.com/sigstore/sigstore/pkg/signature/kms/aws
Bumps [github.com/sigstore/sigstore/pkg/signature/kms/aws](https://github.com/sigstore/sigstore) from 1.8.9 to 1.8.10.
- [Release notes](https://github.com/sigstore/sigstore/releases)
- [Commits](https://github.com/sigstore/sigstore/compare/v1.8.9...v1.8.10)

---
updated-dependencies:
- dependency-name: github.com/sigstore/sigstore/pkg/signature/kms/aws
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-17 13:18:42 +00:00
dependabot[bot]
94f69c75d2 feat(deps): bump github.com/sigstore/sigstore/pkg/signature/kms/gcp
Bumps [github.com/sigstore/sigstore/pkg/signature/kms/gcp](https://github.com/sigstore/sigstore) from 1.8.9 to 1.8.10.
- [Release notes](https://github.com/sigstore/sigstore/releases)
- [Commits](https://github.com/sigstore/sigstore/compare/v1.8.9...v1.8.10)

---
updated-dependencies:
- dependency-name: github.com/sigstore/sigstore/pkg/signature/kms/gcp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-17 13:18:39 +00:00
Joel Kamp
b2e8166079 Merge pull request #200 from docker/dependabot/go_modules/github.com/sigstore/sigstore-1.8.10
feat(deps): bump github.com/sigstore/sigstore from 1.8.9 to 1.8.10
2024-10-17 08:16:22 -05:00
Joel Kamp
8c4ee60f50 Merge branch 'main' into dependabot/go_modules/github.com/sigstore/sigstore-1.8.10 2024-10-17 08:12:39 -05:00
mrjoelkamp
9b6234f0ae chore: go mod tidy 2024-10-17 08:12:10 -05:00
Joel Kamp
17b0978b44 Merge pull request #201 from docker/feat--add-verifier-version-to-vsa
feat: add verifier version to vsa
2024-10-17 08:09:17 -05:00
Joel Kamp
7ff20a9328 Merge branch 'main' into feat--add-verifier-version-to-vsa 2024-10-17 08:03:47 -05:00
James Carnegie
273b61ebd6 Merge branch 'main' into dependabot/go_modules/github.com/sigstore/sigstore-1.8.10 2024-10-17 09:36:58 +01:00
dependabot[bot]
eda0b23910 feat(deps): bump github.com/aws/aws-sdk-go-v2/config (#202)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.43 to 1.28.0.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.43...v1.28.0)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-17 09:36:43 +01:00
mrjoelkamp
4a82bb9981 feat: add version checker test 2024-10-16 15:18:34 -05:00
mrjoelkamp
84c0b116a7 feat: add verifier version to vsa 2024-10-16 12:01:31 -05:00
James Carnegie
16f65fefeb Merge branch 'main' into dependabot/go_modules/github.com/sigstore/sigstore-1.8.10 2024-10-16 10:13:44 +01:00
dependabot[bot]
e39a4ea9f3 feat(deps): bump google.golang.org/api from 0.200.0 to 0.201.0 (#197)
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.200.0 to 0.201.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.200.0...v0.201.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-16 10:13:11 +01:00
dependabot[bot]
2e4f8f79bd feat(deps): bump github.com/sigstore/sigstore from 1.8.9 to 1.8.10
Bumps [github.com/sigstore/sigstore](https://github.com/sigstore/sigstore) from 1.8.9 to 1.8.10.
- [Release notes](https://github.com/sigstore/sigstore/releases)
- [Commits](https://github.com/sigstore/sigstore/compare/v1.8.9...v1.8.10)

---
updated-dependencies:
- dependency-name: github.com/sigstore/sigstore
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-16 09:03:50 +00:00
James Carnegie
da667de610 feat: support arbitrary rego input parameters (#196)
* feat: support arbitrary rego input parameters
2024-10-15 16:07:26 +01:00
Joel Kamp
7027d2d054 Merge pull request #188 from docker/dependabot/go_modules/github.com/sigstore/cosign/v2-2.4.1
feat(deps): bump github.com/sigstore/cosign/v2 from 2.4.0 to 2.4.1
2024-10-15 09:37:02 -05:00
mrjoelkamp
163c1828e3 chore: go mod tidy 2024-10-15 09:28:32 -05:00
dependabot[bot]
168a574c15 feat(deps): bump github.com/sigstore/cosign/v2 from 2.4.0 to 2.4.1
Bumps [github.com/sigstore/cosign/v2](https://github.com/sigstore/cosign) from 2.4.0 to 2.4.1.
- [Release notes](https://github.com/sigstore/cosign/releases)
- [Changelog](https://github.com/sigstore/cosign/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sigstore/cosign/compare/v2.4.0...v2.4.1)

---
updated-dependencies:
- dependency-name: github.com/sigstore/cosign/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-15 14:27:14 +00:00
Joel Kamp
ad2f8befa2 Merge pull request #195 from docker/dependabot/go_modules/google.golang.org/api-0.200.0
feat(deps): bump google.golang.org/api from 0.199.0 to 0.200.0
2024-10-15 08:53:56 -05:00
dependabot[bot]
8460357880 feat(deps): bump google.golang.org/api from 0.199.0 to 0.200.0
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.199.0 to 0.200.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.199.0...v0.200.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-15 13:44:46 +00:00
Joel Kamp
994240018e Merge pull request #187 from docker/dependabot/go_modules/github.com/containerd/containerd/v2-2.0.0-rc.5
feat(deps): bump github.com/containerd/containerd/v2 from 2.0.0-rc.4 to 2.0.0-rc.5
2024-10-15 08:42:03 -05:00
Joel Kamp
5c51ee7c19 Merge pull request #194 from docker/dependabot/go_modules/github.com/aws/aws-sdk-go-v2/config-1.27.43
feat(deps): bump github.com/aws/aws-sdk-go-v2/config from 1.27.39 to 1.27.43
2024-10-15 08:36:49 -05:00
Joel Kamp
8ae43ba5e9 Merge branch 'main' into dependabot/go_modules/github.com/containerd/containerd/v2-2.0.0-rc.5 2024-10-15 08:33:48 -05:00
dependabot[bot]
ec659e62cd feat(deps): bump github.com/aws/aws-sdk-go-v2/config
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.39 to 1.27.43.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.39...config/v1.27.43)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-09 08:42:48 +00:00
Joel Kamp
2d7f6cae3c Merge pull request #191 from docker/feat-vsa-input-attestations
feat: vsa input attestations
2024-10-08 08:30:06 -05:00
mrjoelkamp
a686de72fd feat: add input atts to result summary 2024-10-07 15:07:21 -05:00
mrjoelkamp
d58ce0c600 feat: add reference wrapper for envelope 2024-10-07 13:34:04 -05:00
dependabot[bot]
bf33de5b48 feat(deps): bump github.com/theupdateframework/go-tuf/v2 (#186)
Bumps [github.com/theupdateframework/go-tuf/v2](https://github.com/theupdateframework/go-tuf) from 2.0.1 to 2.0.2.
- [Release notes](https://github.com/theupdateframework/go-tuf/releases)
- [Changelog](https://github.com/theupdateframework/go-tuf/blob/master/.goreleaser.yaml)
- [Commits](https://github.com/theupdateframework/go-tuf/compare/v2.0.1...v2.0.2)

---
updated-dependencies:
- dependency-name: github.com/theupdateframework/go-tuf/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-02 10:05:46 +01:00
dependabot[bot]
b8ca85152d feat(deps): bump github.com/containerd/containerd/v2
Bumps [github.com/containerd/containerd/v2](https://github.com/containerd/containerd) from 2.0.0-rc.4 to 2.0.0-rc.5.
- [Release notes](https://github.com/containerd/containerd/releases)
- [Changelog](https://github.com/containerd/containerd/blob/main/RELEASES.md)
- [Commits](https://github.com/containerd/containerd/compare/v2.0.0-rc.4...v2.0.0-rc.5)

---
updated-dependencies:
- dependency-name: github.com/containerd/containerd/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-02 08:36:57 +00:00
Joel Kamp
e06d8736df Merge pull request #182 from docker/dependabot/go_modules/github.com/aws/aws-sdk-go-v2/config-1.27.39
feat(deps): bump github.com/aws/aws-sdk-go-v2/config from 1.27.38 to 1.27.39
2024-10-01 16:02:00 -05:00
Joel Kamp
fcf98ebc3f Merge branch 'main' into dependabot/go_modules/github.com/aws/aws-sdk-go-v2/config-1.27.39 2024-10-01 15:46:46 -05:00
Joel Kamp
acd8d427a1 Merge pull request #185 from docker/dependabot/go_modules/github.com/open-policy-agent/opa-0.69.0
feat(deps): bump github.com/open-policy-agent/opa from 0.68.0 to 0.69.0
2024-10-01 15:46:34 -05:00
Joel Kamp
f2f13933df Merge branch 'main' into dependabot/go_modules/github.com/open-policy-agent/opa-0.69.0 2024-10-01 15:42:13 -05:00
Joel Kamp
503410bb7b Merge pull request #184 from docker/dependabot/go_modules/github.com/theupdateframework/go-tuf/v2-2.0.1
feat(deps): bump github.com/theupdateframework/go-tuf/v2 from 2.0.0 to 2.0.1
2024-10-01 15:41:54 -05:00
dependabot[bot]
ac04e8a9ea feat(deps): bump github.com/open-policy-agent/opa from 0.68.0 to 0.69.0
Bumps [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) from 0.68.0 to 0.69.0.
- [Release notes](https://github.com/open-policy-agent/opa/releases)
- [Changelog](https://github.com/open-policy-agent/opa/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-policy-agent/opa/compare/v0.68.0...v0.69.0)

---
updated-dependencies:
- dependency-name: github.com/open-policy-agent/opa
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-01 08:30:48 +00:00
dependabot[bot]
e3927acf17 feat(deps): bump github.com/theupdateframework/go-tuf/v2
Bumps [github.com/theupdateframework/go-tuf/v2](https://github.com/theupdateframework/go-tuf) from 2.0.0 to 2.0.1.
- [Release notes](https://github.com/theupdateframework/go-tuf/releases)
- [Changelog](https://github.com/theupdateframework/go-tuf/blob/master/.goreleaser.yaml)
- [Commits](https://github.com/theupdateframework/go-tuf/compare/v2.0.0...v2.0.1)

---
updated-dependencies:
- dependency-name: github.com/theupdateframework/go-tuf/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-01 08:30:33 +00:00
James Carnegie
c0510fb76c Support images as well as indexes in ImageDetailResolvers (#183)
* build: Generate test data for unsigned and no provenance image indexes
* feat: Add function to build index without SBOM or provenance for linux/amd64 platform
* feat: add build_image function to build image without SBOM or provenance for linux/amd64
* feat: Rename NO_SBOM_NO_PROVENANCE_INDEX_DIR to UNSIGNED_IMAGE_DIR
* feat: support images in details resolvers
2024-09-30 20:53:13 +01:00
dependabot[bot]
251506fd9b feat(deps): bump github.com/aws/aws-sdk-go-v2/config
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.38 to 1.27.39.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.38...config/v1.27.39)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-30 08:47:36 +00:00
dependabot[bot]
5e16b97e02 feat(deps): bump google.golang.org/api from 0.198.0 to 0.199.0 (#181)
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.198.0 to 0.199.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.198.0...v0.199.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-27 15:11:28 +01:00
dependabot[bot]
0ff28b2deb feat(deps): bump github.com/aws/aws-sdk-go-v2/config (#180)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.35 to 1.27.38.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.35...config/v1.27.38)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-27 15:05:53 +01:00
Jonny Stoten
4ca962b70c Add function for parsing DOI definition files (#172)
Add a Rego builtin called `attest.internals.parse_library_definition`
for parsing the DOI definition files in
https://github.com/docker-library/official-images/tree/master/library.
This will allow us to verify DOI provenance fields against these files
which are the source of truth for DOI images.

This function just defers to
https://github.com/docker-library/bashbrew/blob/master/manifest/rfc2822.go.
2024-09-27 12:32:24 +01:00
Joel Kamp
2a4bef091e Merge pull request #179 from docker/fix-sign-unsigned-statements
fix: only sign statements
2024-09-26 10:02:41 -05:00
mrjoelkamp
bb0843cd51 fix: only sign statements 2024-09-24 15:12:46 -05:00
David Dooling
203577e965 Remove long-term aspiration from README (#174) 2024-09-20 09:06:02 -05:00
James Carnegie
a98604bdd5 chore: add rekor prod TUF system test (#176) 2024-09-20 11:02:36 +01:00
dependabot[bot]
02b8063d71 feat(deps): bump google.golang.org/api from 0.197.0 to 0.198.0 (#175)
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.197.0 to 0.198.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.197.0...v0.198.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-20 10:01:47 +01:00
Joel Kamp
dcf5c578dd Merge pull request #173 from docker/feat-support-containerd-subject-annotations
feat: support containerd subject annotations
2024-09-19 16:03:32 -05:00
mrjoelkamp
0378c94226 test: make test layouts smaller 2024-09-19 15:36:20 -05:00
mrjoelkamp
fd4e741a1f feat: support containerd subject annotations 2024-09-19 15:10:56 -05:00
James Carnegie
2ace988b1c chore: add test for RegoFnOpts (#171) 2024-09-19 13:54:10 +01:00
dependabot[bot]
be7a17f214 feat(deps): bump github.com/sigstore/sigstore from 1.8.8 to 1.8.9 (#169)
Bumps [github.com/sigstore/sigstore](https://github.com/sigstore/sigstore) from 1.8.8 to 1.8.9.
- [Release notes](https://github.com/sigstore/sigstore/releases)
- [Commits](https://github.com/sigstore/sigstore/compare/v1.8.8...v1.8.9)

---
updated-dependencies:
- dependency-name: github.com/sigstore/sigstore
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-19 11:24:30 +01:00
dependabot[bot]
1a49b5c068 chore(deps): bump actions/create-github-app-token from 1.10.4 to 1.11.0 (#164)
Bumps [actions/create-github-app-token](https://github.com/actions/create-github-app-token) from 1.10.4 to 1.11.0.
- [Release notes](https://github.com/actions/create-github-app-token/releases)
- [Commits](3378cda945...5d869da34e)

---
updated-dependencies:
- dependency-name: actions/create-github-app-token
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-19 11:18:57 +01:00
James Carnegie
3e82338649 refactor: remove explicit closures. expose rego fns (#170) 2024-09-19 11:04:00 +01:00
James Carnegie
4a70e5ae36 Add platform filtering support to mapping.yml (#167)
* chore!: rename package config -> mapping
* feat: add platform filtering support to mapping.yml
2024-09-18 21:11:55 +01:00
James Carnegie
05caa959c4 Use a Factory to create signature verifiers at policy evaluation time (#165)
* Make verifiers composable

* fix: remove unused code and improve signature verification logic

* fix: simplify abstractions and renamed some things

* fix: improve tl interface.

* fix: sort out signer/verifier
2024-09-18 13:34:10 +01:00
dependabot[bot]
5335a56da1 feat(deps): bump github.com/aws/aws-sdk-go-v2/config (#168)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.33 to 1.27.35.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.33...config/v1.27.35)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-18 09:43:50 +01:00
Jonny Stoten
7fffbf9d3f Suppress logs from ecr credential helper (#163)
This gets rid of those annoying logs like:

```
time="2024-09-11T15:22:04Z" level=error msg="Error parsing the serverURL" error="docker-credential-ecr-login can only be used with Amazon Elastic Container Registry." serverURL="localhost:5000"
time="2024-09-11T15:22:04Z" level=error msg="Error parsing the serverURL" error="docker-credential-ecr-login can only be used with Amazon Elastic Container Registry." serverURL="localhost:5000"
time="2024-09-11T15:22:04Z" level=error msg="Error parsing the serverURL" error="docker-credential-ecr-login can only be used with Amazon Elastic Container Registry." serverURL="localhost:5000"
time="2024-09-11T15:22:04Z" level=error msg="Error parsing the serverURL" error="docker-credential-ecr-login can only be used with Amazon Elastic Container Registry." serverURL="localhost:5000"
```
2024-09-11 16:36:28 +01:00
dependabot[bot]
070fa33d0d feat(deps): bump google.golang.org/api from 0.196.0 to 0.197.0 (#162)
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.196.0 to 0.197.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.196.0...v0.197.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-11 12:27:09 +01:00
Jonny Stoten
602295492f fix: regexes for autolabeler (#160)
* Fix regexes for autolabeler

* Remove branch autolabeler rules
2024-09-10 21:02:05 +01:00
Jonny Stoten
6edcc3d5d7 Test on Go 1.23 as well (#161) 2024-09-10 17:40:43 +01:00
Jonny Stoten
c029bcfbaa feat: add a prefix path to TUF client (#159)
This is to allow us to store new policy files in the production TUF repository
under a testing delegation, and for clients to opt-in to using this testing
delegation when retrieving policy from TUF.

If the prefix path is set, it is prepended to every target path on download
with path.Join. For example, if the prefix path is testing and we download
the target a/b, the TUF client with actually download testing/a/b.

Also get the latest testdata from tuf-dev.
2024-09-10 17:40:20 +01:00
James Carnegie
206b33c5d9 fix: expose version and user agent to consumers (#158) 2024-09-09 12:08:01 -05:00
James Carnegie
b4e6767cc6 feature!: support for setting HTTP User-Agent header (#157)
* feature!: support for setting HTTP User-Agent header

* fix lint

* fix e2e

* refactor: move http.go to internal/util/useragent package and rename functions to Get and Set

* Move packages and use attest version
2024-09-09 14:22:17 +01:00
James Carnegie
ed0ae8ecf6 fix: verify mapped image name against subjects (#156)
* fix: verify mapped image name against subjects
2024-09-05 08:08:55 -05:00
Joel Kamp
a363be7f3a Merge pull request #150 from docker/dependabot/go_modules/google.golang.org/api-0.196.0
feat(deps): bump google.golang.org/api from 0.195.0 to 0.196.0
2024-09-04 16:47:27 -05:00
dependabot[bot]
99846a3483 feat(deps): bump google.golang.org/api from 0.195.0 to 0.196.0
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.195.0 to 0.196.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.195.0...v0.196.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-04 21:43:32 +00:00
Joel Kamp
f760b12bb2 Merge pull request #151 from docker/dependabot/go_modules/github.com/sigstore/sigstore/pkg/signature/kms/gcp-1.8.9
feat(deps): bump github.com/sigstore/sigstore/pkg/signature/kms/gcp from 1.8.8 to 1.8.9
2024-09-04 16:41:22 -05:00
Joel Kamp
bab474669f Merge pull request #155 from docker/dependabot/go_modules/github.com/aws/aws-sdk-go-v2/config-1.27.33
feat(deps): bump github.com/aws/aws-sdk-go-v2/config from 1.27.31 to 1.27.33
2024-09-04 16:40:18 -05:00
dependabot[bot]
0705a71115 feat(deps): bump github.com/sigstore/sigstore/pkg/signature/kms/gcp
Bumps [github.com/sigstore/sigstore/pkg/signature/kms/gcp](https://github.com/sigstore/sigstore) from 1.8.8 to 1.8.9.
- [Release notes](https://github.com/sigstore/sigstore/releases)
- [Commits](https://github.com/sigstore/sigstore/compare/v1.8.8...v1.8.9)

---
updated-dependencies:
- dependency-name: github.com/sigstore/sigstore/pkg/signature/kms/gcp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-04 21:37:46 +00:00
dependabot[bot]
b00e02af01 feat(deps): bump github.com/aws/aws-sdk-go-v2/config
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.31 to 1.27.33.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.31...config/v1.27.33)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-04 21:36:36 +00:00
Joel Kamp
ff53657cc9 Merge pull request #153 from docker/dependabot/github_actions/actions/create-github-app-token-1.10.4
chore(deps): bump actions/create-github-app-token from 1.10.3 to 1.10.4
2024-09-04 16:34:38 -05:00
Joel Kamp
c8383f3f5a Merge pull request #149 from docker/dependabot/go_modules/github.com/sigstore/sigstore/pkg/signature/kms/aws-1.8.9
feat(deps): bump github.com/sigstore/sigstore/pkg/signature/kms/aws from 1.8.8 to 1.8.9
2024-09-04 16:33:50 -05:00
Joel Kamp
dc247bd348 Merge pull request #143 from docker/dependabot/go_modules/github.com/open-policy-agent/opa-0.68.0
feat(deps): bump github.com/open-policy-agent/opa from 0.67.1 to 0.68.0
2024-09-04 16:33:28 -05:00
Joel Kamp
ce7d173150 Merge pull request #154 from docker/feat--add-slsa-v1-predicate-type
feat: add slsa v1 predicate type
2024-09-04 16:32:21 -05:00
mrjoelkamp
fb69d9a09b feat: add slsa v1 predicate type 2024-09-04 16:15:56 -05:00
James Carnegie
48e58a9115 Verify input image/platform against attestation subjects before passing to rego (#148)
* feat: verify subjects before passing to rego
2024-09-04 10:20:00 +01:00
dependabot[bot]
bfacaf1de0 chore(deps): bump actions/create-github-app-token from 1.10.3 to 1.10.4
Bumps [actions/create-github-app-token](https://github.com/actions/create-github-app-token) from 1.10.3 to 1.10.4.
- [Release notes](https://github.com/actions/create-github-app-token/releases)
- [Commits](31c86eb3b3...3378cda945)

---
updated-dependencies:
- dependency-name: actions/create-github-app-token
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-04 08:46:09 +00:00
dependabot[bot]
67ad27ac22 feat(deps): bump github.com/sigstore/sigstore/pkg/signature/kms/aws
Bumps [github.com/sigstore/sigstore/pkg/signature/kms/aws](https://github.com/sigstore/sigstore) from 1.8.8 to 1.8.9.
- [Release notes](https://github.com/sigstore/sigstore/releases)
- [Commits](https://github.com/sigstore/sigstore/compare/v1.8.8...v1.8.9)

---
updated-dependencies:
- dependency-name: github.com/sigstore/sigstore/pkg/signature/kms/aws
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-04 08:41:30 +00:00
James Carnegie
41847ef238 fix: escape ! remove .* (global match) (#146) 2024-09-03 12:24:26 +01:00
James Carnegie
1f806f33a8 feat: validate mapping files on load (#147) 2024-09-03 12:21:24 +01:00
James Carnegie
8982778507 refactor! remove pkg directory (#145)
* refactor!: remove pkg directory

* chore: include breaking changes in draft
2024-09-02 16:17:50 +01:00
James Carnegie
23849c1c2e fix: use canonical names inside TUF fetcher (#144)
* fix: use canonical names inside TUF fetcher
* keep hold of reference to Config
2024-08-30 17:03:29 +01:00
dependabot[bot]
16834292de feat(deps): bump github.com/open-policy-agent/opa from 0.67.1 to 0.68.0
Bumps [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) from 0.67.1 to 0.68.0.
- [Release notes](https://github.com/open-policy-agent/opa/releases)
- [Changelog](https://github.com/open-policy-agent/opa/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-policy-agent/opa/compare/v0.67.1...v0.68.0)

---
updated-dependencies:
- dependency-name: github.com/open-policy-agent/opa
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-30 08:37:19 +00:00
dependabot[bot]
bada1df262 feat(deps): bump google.golang.org/api from 0.194.0 to 0.195.0 (#139)
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.194.0 to 0.195.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.194.0...v0.195.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: James Carnegie <kipz@users.noreply.github.com>
2024-08-30 09:29:19 +01:00
James Carnegie
4778d3de6a fix: tuf oci image parsing (#142)
* fix: tuf oci image parsing
2024-08-29 12:27:13 -05:00
James Carnegie
a4ac09e7da refactor! don't use ctx for policy evaluator (#140)
* refactor! don't use ctx for policy evaluator
2024-08-29 17:43:45 +01:00
Joel Kamp
9250552c5b Merge pull request #138 from docker/feat-add-tuf-resolver-tests
feat: add policy resolver tests
2024-08-29 10:28:34 -05:00
mrjoelkamp
2acc30693f fix: remove mock tuf client output 2024-08-29 10:03:07 -05:00
mrjoelkamp
5db1b5c4c1 feat: add tuf resolver test 2024-08-28 17:08:46 -05:00
Jonny Stoten
6f94d59a96 refactor!: add policy.Resolver struct to reduce parameters (#130)
* Add `policy.Resolver` struct to reduce parameters

* Pass image name directly rather than resolver

* Move policy match stuff to its own file
2024-08-28 11:27:00 +01:00
dependabot[bot]
95319494b5 feat(deps): bump github.com/testcontainers/testcontainers-go/modules/registry (#127)
Bumps [github.com/testcontainers/testcontainers-go/modules/registry](https://github.com/testcontainers/testcontainers-go) from 0.32.0 to 0.33.0.
- [Release notes](https://github.com/testcontainers/testcontainers-go/releases)
- [Commits](https://github.com/testcontainers/testcontainers-go/compare/v0.32.0...v0.33.0)

---
updated-dependencies:
- dependency-name: github.com/testcontainers/testcontainers-go/modules/registry
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: James Carnegie <kipz@users.noreply.github.com>
2024-08-28 09:58:09 +01:00
dependabot[bot]
64046df6f8 feat(deps): bump github.com/aws/aws-sdk-go-v2/config (#134)
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.28 to 1.27.31.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.28...config/v1.27.31)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-28 08:57:31 +00:00
dependabot[bot]
57b6df0ab5 feat(deps): bump google.golang.org/api from 0.192.0 to 0.194.0 (#131)
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.192.0 to 0.194.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.192.0...v0.194.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-28 09:56:53 +01:00
dependabot[bot]
857be568b5 feat(deps): bump github.com/Masterminds/semver/v3 from 3.2.1 to 3.3.0 (#136)
Bumps [github.com/Masterminds/semver/v3](https://github.com/Masterminds/semver) from 3.2.1 to 3.3.0.
- [Release notes](https://github.com/Masterminds/semver/releases)
- [Changelog](https://github.com/Masterminds/semver/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Masterminds/semver/compare/v3.2.1...v3.3.0)

---
updated-dependencies:
- dependency-name: github.com/Masterminds/semver/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-28 09:55:28 +01:00
James Carnegie
9d39c5ae3d feat!: remove MockTUFClient (#135)
* feat! remove MockTUFClient

*Breaking*
- use LocalPolicyDir and nil TUFClient instead

Other:
- add stateful Verifier
2024-08-28 09:53:52 +01:00
Jonny Stoten
aed959f858 fix: use a client pointing at Docker's TUF by default (#104)
`policy.Options` now contains the arguments to `tuf.Client`'s constructor rather than an actual Client. If these arguments are not provided, defaults pointing at Docker's TUF repo will be used. An actual TUF client can be passed in on the context (which is useful for testing). If this is not provided `attest.Verify` will create a TUF client using the options on `policy.Options`.

---------

Co-authored-by: Joel Kamp <joel.kamp@docker.com>
2024-08-23 09:33:30 +01:00
James Carnegie
802725caf0 feat: add purl details to policy inputs (#129) 2024-08-21 12:01:11 -05:00
Joel Kamp
9c3f267870 Merge pull request #126 from docker/dependabot/go_modules/go_modules-56f2e24de8
feat(deps): bump github.com/docker/docker from 27.1.0+incompatible to 27.1.1+incompatible in the go_modules group
2024-08-16 09:10:37 -05:00
Joel Kamp
6cc9191e1e Merge branch 'main' into dependabot/go_modules/go_modules-56f2e24de8 2024-08-16 09:06:27 -05:00
Joel Kamp
7ce2817111 Merge pull request #123 from docker/dependabot/go_modules/google.golang.org/api-0.192.0
feat(deps): bump google.golang.org/api from 0.191.0 to 0.192.0
2024-08-16 09:06:00 -05:00
dependabot[bot]
a60aab9338 feat(deps): bump github.com/docker/docker in the go_modules group
Bumps the go_modules group with 1 update: [github.com/docker/docker](https://github.com/docker/docker).


Updates `github.com/docker/docker` from 27.1.0+incompatible to 27.1.1+incompatible
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v27.1.0...v27.1.1)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: indirect
  dependency-group: go_modules
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-16 14:05:57 +00:00
Joel Kamp
2ef3a158ae Merge branch 'main' into dependabot/go_modules/google.golang.org/api-0.192.0 2024-08-16 09:04:20 -05:00
Joel Kamp
4f163f4283 Merge pull request #125 from docker/dependabot/go_modules/github.com/aws/aws-sdk-go-v2/config-1.27.28
feat(deps): bump github.com/aws/aws-sdk-go-v2/config from 1.27.27 to 1.27.28
2024-08-16 09:03:58 -05:00
dependabot[bot]
74e8d8beb3 feat(deps): bump github.com/aws/aws-sdk-go-v2/config
Bumps [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) from 1.27.27 to 1.27.28.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.27...config/v1.27.28)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-16 08:19:46 +00:00
Joel Kamp
a4a0bf3cbe Merge pull request #124 from docker/feat-generate-vsa-policy-uri
feat: add `digest` and `downloadLocation` to VSA policy
2024-08-14 16:50:16 -05:00
mrjoelkamp
52499053d2 feat: add no policy file error 2024-08-14 16:25:41 -05:00
mrjoelkamp
5f17f97229 test: change test to use yaml file instead 2024-08-14 16:13:36 -05:00
mrjoelkamp
8d8f09661f test: add mapping no rego test 2024-08-14 16:10:54 -05:00
mrjoelkamp
059ee8926c refactor: move fullURL only needed for DefaultFetcher 2024-08-14 15:27:02 -05:00
mrjoelkamp
cb47507650 chore: pr comments 2024-08-14 15:01:01 -05:00
Joel Kamp
7c0966de81 Update README.md
Co-authored-by: David Dooling <141646279+whalelines@users.noreply.github.com>
2024-08-14 14:39:06 -05:00
mrjoelkamp
2bf7dec72e feat: add policy.downloadLocation 2024-08-14 12:52:36 -05:00
mrjoelkamp
6de792c1b5 docs: update README with policy.digest 2024-08-14 11:33:15 -05:00
mrjoelkamp
d2a8348ae8 feat: generate vsa policy value from file 2024-08-14 10:57:15 -05:00
dependabot[bot]
881e9d9582 feat(deps): bump google.golang.org/api from 0.191.0 to 0.192.0
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.191.0 to 0.192.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.191.0...v0.192.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-14 08:58:17 +00:00
Joel Kamp
8c6df28540 Merge pull request #122 from docker/feat-mirror-empty-config-image
feat: mirror empty config image
2024-08-13 10:09:35 -05:00
mrjoelkamp
5162cfa404 refactor: ensure tests are in correct pkg 2024-08-13 10:03:33 -05:00
mrjoelkamp
72f6517b2c refactor: move empty config image test 2024-08-13 08:26:36 -05:00
mrjoelkamp
84cadeb97e feat: output comments 2024-08-13 08:13:27 -05:00
mrjoelkamp
57a61cc266 fix: e2e auth test 2024-08-12 16:54:44 -05:00
mrjoelkamp
5a772633b0 feat: use EmptyConfigImage for mirror 2024-08-12 16:43:42 -05:00
mrjoelkamp
1febc55a19 fix: cyclical imports 2024-08-12 16:36:18 -05:00
mrjoelkamp
0db96d56aa fix: err check not needed 2024-08-12 14:20:24 -05:00
Joel Kamp
d97d20eb93 Merge pull request #121 from docker/dependabot/go_modules/google.golang.org/api-0.191.0
feat(deps): bump google.golang.org/api from 0.190.0 to 0.191.0
2024-08-08 15:28:52 -05:00
Joel Kamp
42390b5fc2 Merge branch 'main' into dependabot/go_modules/google.golang.org/api-0.191.0 2024-08-08 15:18:54 -05:00
Joel Kamp
70e6345942 Merge pull request #119 from docker/dependabot/go_modules/github.com/sigstore/cosign/v2-2.4.0
feat(deps): bump github.com/sigstore/cosign/v2 from 2.3.0 to 2.4.0
2024-08-08 15:18:19 -05:00
dependabot[bot]
f853875eea feat(deps): bump github.com/sigstore/cosign/v2 from 2.3.0 to 2.4.0
Bumps [github.com/sigstore/cosign/v2](https://github.com/sigstore/cosign) from 2.3.0 to 2.4.0.
- [Release notes](https://github.com/sigstore/cosign/releases)
- [Changelog](https://github.com/sigstore/cosign/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sigstore/cosign/compare/v2.3.0...v2.4.0)

---
updated-dependencies:
- dependency-name: github.com/sigstore/cosign/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-08 20:11:27 +00:00
Joel Kamp
050497e5a7 Merge pull request #118 from docker/dependabot/go_modules/github.com/sigstore/sigstore/pkg/signature/kms/aws-1.8.8
feat(deps): bump github.com/sigstore/sigstore/pkg/signature/kms/aws from 1.8.7 to 1.8.8
2024-08-08 15:09:20 -05:00
dependabot[bot]
d69334a1e6 feat(deps): bump google.golang.org/api from 0.190.0 to 0.191.0
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.190.0 to 0.191.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.190.0...v0.191.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-08 20:00:21 +00:00
dependabot[bot]
a84268b133 feat(deps): bump github.com/sigstore/sigstore/pkg/signature/kms/aws
Bumps [github.com/sigstore/sigstore/pkg/signature/kms/aws](https://github.com/sigstore/sigstore) from 1.8.7 to 1.8.8.
- [Release notes](https://github.com/sigstore/sigstore/releases)
- [Commits](https://github.com/sigstore/sigstore/compare/v1.8.7...v1.8.8)

---
updated-dependencies:
- dependency-name: github.com/sigstore/sigstore/pkg/signature/kms/aws
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-08 20:00:19 +00:00
Joel Kamp
2cd2e2da96 Merge pull request #117 from docker/dependabot/go_modules/github.com/sigstore/sigstore/pkg/signature/kms/gcp-1.8.8
feat(deps): bump github.com/sigstore/sigstore/pkg/signature/kms/gcp from 1.8.7 to 1.8.8
2024-08-08 14:58:19 -05:00
Joel Kamp
f1ece6893f Merge branch 'main' into dependabot/go_modules/github.com/sigstore/sigstore/pkg/signature/kms/gcp-1.8.8 2024-08-08 14:48:59 -05:00
Joel Kamp
116b9ea770 Merge pull request #120 from docker/refactor-referrers-output
feat!: push attestation artifacts by digest
2024-08-08 14:48:42 -05:00
mrjoelkamp
d291912208 refactor!: move oci output from mirror to oci pkg
BREAKING_CHANGE: output methods to save and push images are now part of the oci pkg
2024-08-08 14:23:46 -05:00
mrjoelkamp
9cad88a687 fix: EmptyConfigImage digest 2024-08-08 13:06:56 -05:00
mrjoelkamp
77ccbc097b feat: use docker/go-containerregistry 2024-08-08 11:37:45 -05:00
mrjoelkamp
45927967c8 test: debug push 2024-08-08 10:04:41 -05:00
mrjoelkamp
9aa56e564d feat: push attestation artifacts by digest 2024-08-07 15:19:48 -05:00
dependabot[bot]
6d0a6de520 feat(deps): bump github.com/sigstore/sigstore/pkg/signature/kms/gcp
Bumps [github.com/sigstore/sigstore/pkg/signature/kms/gcp](https://github.com/sigstore/sigstore) from 1.8.7 to 1.8.8.
- [Release notes](https://github.com/sigstore/sigstore/releases)
- [Commits](https://github.com/sigstore/sigstore/compare/v1.8.7...v1.8.8)

---
updated-dependencies:
- dependency-name: github.com/sigstore/sigstore/pkg/signature/kms/gcp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-07 09:10:08 +00:00
Joel Kamp
8767951fa2 Merge pull request #114 from docker/dependabot/go_modules/google.golang.org/api-0.190.0
feat(deps): bump google.golang.org/api from 0.189.0 to 0.190.0
2024-08-06 10:15:47 -05:00
Joel Kamp
f18b5877d3 Merge branch 'main' into dependabot/go_modules/google.golang.org/api-0.190.0 2024-08-06 10:09:55 -05:00
Joel Kamp
93fd9daeb9 Merge pull request #116 from docker/dependabot/go_modules/github.com/open-policy-agent/opa-0.67.1
feat(deps): bump github.com/open-policy-agent/opa from 0.67.0 to 0.67.1
2024-08-06 10:08:32 -05:00
Joel Kamp
5df79de1c7 Merge branch 'main' into dependabot/go_modules/github.com/open-policy-agent/opa-0.67.1 2024-08-06 09:37:08 -05:00
Joel Kamp
5b5e43b07a Merge pull request #113 from docker/fix-oci-layout-referrers
fix: let OCI layouts use referrers attestations
2024-08-06 09:24:53 -05:00
dependabot[bot]
4c5135eb1b feat(deps): bump github.com/open-policy-agent/opa from 0.67.0 to 0.67.1
Bumps [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) from 0.67.0 to 0.67.1.
- [Release notes](https://github.com/open-policy-agent/opa/releases)
- [Changelog](https://github.com/open-policy-agent/opa/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-policy-agent/opa/compare/v0.67.0...v0.67.1)

---
updated-dependencies:
- dependency-name: github.com/open-policy-agent/opa
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-06 09:01:35 +00:00
mrjoelkamp
0133423f0d feat: add nil pointer test 2024-08-05 16:50:40 -05:00
mrjoelkamp
501b9b442d feat: add CreateAttestationResolver tests 2024-08-05 16:31:39 -05:00
Joel Kamp
d84ed4821c Merge branch 'main' into fix-oci-layout-referrers 2024-08-05 16:01:36 -05:00
Joel Kamp
c9e2ddd448 Merge pull request #115 from docker/chore--disable-codecov-patch-status
chore: disable codecov patch status
2024-08-05 16:01:25 -05:00
mrjoelkamp
165241de42 chore: disable codecov patch status 2024-08-05 15:56:06 -05:00
mrjoelkamp
c7d17faf05 fix: layout attestation resolver 2024-08-05 15:32:24 -05:00
mrjoelkamp
58021646e3 feat: add oci layout test 2024-08-05 11:24:28 -05:00
mrjoelkamp
3e7a85e9b8 fix: nil pointer dereference 2024-08-05 11:24:05 -05:00
mrjoelkamp
bb7a9a257e chore: remove duplicate code 2024-08-05 11:23:32 -05:00
mrjoelkamp
c690d1090c chore: use prefix const 2024-08-05 11:22:49 -05:00
mrjoelkamp
1d1c258f9c fix: referrers resolver only works for registry resolvers 2024-08-05 10:20:40 -05:00
mrjoelkamp
5d096e226f refactor: fix import cycle for mock resolver 2024-08-05 10:19:50 -05:00
dependabot[bot]
7fc7ceaba0 feat(deps): bump google.golang.org/api from 0.189.0 to 0.190.0
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.189.0 to 0.190.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.189.0...v0.190.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-02 08:34:34 +00:00
mrjoelkamp
78ec0b7666 fix: use referrers repo img spec and resolver 2024-08-01 15:24:35 -05:00
Joel Kamp
053f764b8f Merge branch 'main' into fix-oci-layout-referrers 2024-08-01 13:48:53 -05:00
mrjoelkamp
ad3b8b9e49 fix: let OCI layouts use referrers attestations 2024-08-01 13:41:49 -05:00
James Carnegie
9582e69968 fix: standardize casing of initialisms (#112)
* fix: standardize casing of initialisms
* fix: rename intoto -> inToto and Intoto to InToto
* fix: fix all linting errors
2024-08-01 15:35:15 +01:00
James Carnegie
b0b37f73f3 fix: upgrade go to 1.22.x for testing (#110) 2024-08-01 15:34:35 +01:00
dependabot[bot]
d21fc7853c feat(deps): bump github.com/docker/docker (#105)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 27.0.3+incompatible to 27.1.0+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v27.0.3...v27.1.0)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-31 16:50:39 +01:00
Jonny Stoten
008c14e3f3 chore: reformat with gofumpt (#109)
* Reformat with gofumpt

* Suppress issue about laxer perms than 0600

---------

Co-authored-by: Joel Kamp <joel.kamp@docker.com>
2024-07-31 15:48:00 +01:00
Jonny Stoten
fbe9a0c726 Add linting github action (#107)
* Add golangci config

* Add lint action
2024-07-31 14:42:19 +01:00
James Carnegie
9571f17476 fix: add auth to referrers image retrieval (#108) 2024-07-31 14:31:29 +01:00
James Carnegie
63246e2b96 docs: add contribution guidelines (#102)
* docs: add contribution guidelines
2024-07-31 11:08:59 +01:00
Jonny Stoten
91fdf7ece6 Remove dependency on github.com/pkg/errors (#106) 2024-07-30 14:07:19 +01:00
James Carnegie
a1c7bbb991 debt: remove goyaml. Fixup directives (#103) 2024-07-29 17:21:15 +01:00
Jonny Stoten
2ffdfdf0eb docs: first cut of a new README (#99)
Lots of this is taken from image-signer-verifier's README. The stuff on
policy is all new.

Co-authored-by: James Carnegie <kipz@users.noreply.github.com>
2024-07-29 16:43:31 +01:00
dependabot[bot]
781a738b54 feat(deps): bump github.com/open-policy-agent/opa from 0.66.0 to 0.67.0 (#101)
Bumps [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) from 0.66.0 to 0.67.0.
- [Release notes](https://github.com/open-policy-agent/opa/releases)
- [Changelog](https://github.com/open-policy-agent/opa/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-policy-agent/opa/compare/v0.66.0...v0.67.0)

---
updated-dependencies:
- dependency-name: github.com/open-policy-agent/opa
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-26 09:46:59 +01:00
James Carnegie
c735bb0d3f feat: roll out updates on release (#100)
* feat: roll out updates on release

* Use app token. Fix repo
2024-07-25 16:15:35 +01:00
dependabot[bot]
bd2c4d7d8a feat(deps): bump github.com/sigstore/cosign/v2 from 2.2.4 to 2.3.0 (#98)
* feat(deps): bump github.com/sigstore/cosign/v2 from 2.2.4 to 2.3.0

Bumps [github.com/sigstore/cosign/v2](https://github.com/sigstore/cosign) from 2.2.4 to 2.3.0.
- [Release notes](https://github.com/sigstore/cosign/releases)
- [Changelog](https://github.com/sigstore/cosign/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sigstore/cosign/compare/v2.2.4...v2.3.0)

---
updated-dependencies:
- dependency-name: github.com/sigstore/cosign/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* update to go 1.22.5

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: mrjoelkamp <joel.kamp@docker.com>
2024-07-24 13:30:56 +01:00
dependabot[bot]
03ba59c6b9 feat(deps): bump google.golang.org/api from 0.188.0 to 0.189.0 (#97) 2024-07-23 19:08:01 +00:00
dependabot[bot]
ac82c65d7c feat(deps): bump github.com/aws/aws-sdk-go-v2/config (#93) 2024-07-23 19:03:53 +00:00
364 changed files with 11764 additions and 5592 deletions

19
.github/ISSUE_TEMPLATE/bug-report.md vendored Normal file
View File

@@ -0,0 +1,19 @@
---
name: Bug report
about: Create a report to help us improve
title: ""
labels: bug
assignees: ""
---
**What steps did you take and what happened:**
[A clear and concise description of what the bug is.]
**What did you expect to happen:**
**Anything else you would like to add:**
[Miscellaneous information that will assist in solving the issue.]
**Environment:**
- Attest version:

View File

@@ -0,0 +1,13 @@
---
name: Feature request
about: Suggest an idea for this project
title: ""
labels: enhancement
assignees: ""
---
**Describe the solution you'd like**
[A clear and concise description of what you want to happen.]
**Anything else you would like to add:**
[Miscellaneous information that will assist in solving the issue.]

11
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,11 @@
## Summary
<!-- Description of why the pull request is needed and what it changes -->
### Tests
<!-- Provide evidence of testing -->
### Issue
<!-- Link to issue that this is part of -->

2
.github/dco.yml vendored Normal file
View File

@@ -0,0 +1,2 @@
require:
members: false

View File

@@ -14,6 +14,9 @@ categories:
- title: "🧰 Maintenance"
labels:
- "chore"
- title: "💥 Breaking Changes"
labels:
- "breaking"
change-template: "- $TITLE @$AUTHOR (#$NUMBER)"
change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
@@ -21,6 +24,7 @@ version-resolver:
major:
labels:
- "major"
- "breaking"
minor:
labels:
- "minor"
@@ -37,26 +41,19 @@ autolabeler:
- label: "chore"
files:
- "*.md"
branch:
- '/docs{0,1}\/.+/'
- '/tests{0,1}\/.+/'
- '/chore{0,1}\/.+/'
title:
- "/docs/i"
- "/test/i"
- "/chore/i"
- "/^docs!?:/i"
- "/^test!?:/i"
- "/^chore!?:/i"
- "/^refactor!?:/i"
- label: "bug"
branch:
- '/fix\/.+/'
- '/revert\/.+/'
title:
- "/fix/i"
- "/revert/i"
- "/^fix!?:/i"
- "/^revert!?:/i"
- label: "feature"
branch:
- '/feature\/.+/'
- '/feat\/.+/'
- '/add\/.+/'
title:
- "/feat/i"
- "/add/i"
- "/^feat!?:/i"
- "/^add!?:/i"
- label: "breaking"
title:
- "/^[a-zA-Z]+!:/i"

19
.github/workflows/lint.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
name: lint code
on:
pull_request:
workflow_dispatch:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Set git to use LF
run: git config --global core.autocrlf false
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: 1.22.x
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: v1.59
only-new-issues: true

24
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,24 @@
name: release
on:
release:
types: [published]
jobs:
trigger_attest_update:
name: Update attest lib - ALL
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Generate GitHub App Token
id: app-token
uses: actions/create-github-app-token@5d869da34e18e7287c1daad50e0b8ea0f506ce69 # v1.11.0
with:
app-id: ${{ vars.ATTEST_RELEASE_APP_ID }}
private-key: ${{ secrets.ATTEST_RELEASE_APP_PRIVATE_KEY }}
repositories: "attest-actions"
- name: Send repository_dispatch event
uses: peter-evans/repository-dispatch@v3.0.0
with:
token: ${{ steps.app-token.outputs.token }}
event-type: update_attest_all
repository: docker/attest-actions
client-payload: '{"attest_version": "${{ github.ref_name }}"}'

View File

@@ -12,7 +12,7 @@ jobs:
id-token: write
strategy:
matrix:
go-version: [1.21.x]
go-version: [1.22.x, 1.23.x]
# temp disable windows tests see https://github.com/docker/image-signer-verifier/pull/154
# os: [ubuntu-latest, macos-latest, windows-latest]
os: [ubuntu-latest, macos-latest]
@@ -50,13 +50,13 @@ jobs:
token: ${{ secrets.TC_CLOUD_TOKEN }}
- name: go test including e2e
if: matrix.os == 'ubuntu-latest' && github.actor != 'dependabot[bot]'
run: go test -tags=e2e -v ./... -coverprofile=coverage.out -covermode=atomic
run: go test -tags=e2e -v ./... -coverpkg=./... -coverprofile=coverage.out -covermode=atomic
- name: go test excluding e2e
if: matrix.os == 'macos-latest' || github.actor == 'dependabot[bot]'
run: go test -v ./...
- name: Upload coverage to Codecov
if: matrix.os == 'ubuntu-latest' && github.actor != 'dependabot[bot]'
uses: codecov/codecov-action@v4
uses: codecov/codecov-action@v5
with:
file: ./coverage.out
flags: unittests

1
.gitignore vendored
View File

@@ -19,3 +19,4 @@
# Go workspace file
go.work
.aider*

36
.golangci.yaml Normal file
View File

@@ -0,0 +1,36 @@
run:
timeout: 5m
go: "1.22"
linters-settings:
gocritic:
enabled-tags:
- performance
lll:
line-length: 200
misspell:
locale: US
linters:
disable-all: true
enable:
- errcheck
- forcetypeassert
- gocritic
- goconst
- godot
- gofmt
- gofumpt
- goimports
- gosec
- gosimple
- govet
- importas
- ineffassign
- misspell
- revive # replacement for golint
- staticcheck
- typecheck
- unused
- whitespace

131
CODE-OF-CONDUCT.md Normal file
View File

@@ -0,0 +1,131 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official email address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by submitting an [incident report](https://docs.google.com/forms/d/e/1FAIpQLScezna1ZXRPzC_phSDoPEF4c5nvw8yQW-vvtI8xHjv-BB9MOg/viewform?c=0&w=1).
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available
at [https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations

85
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,85 @@
# Contribute to the attest Library
Want to hack on the attest library? This guide will help you to find out how to contribute.
This page contains information about reporting issues as well as some tips and guidelines useful to experienced open source contributors. Finally, make sure you read our [community guidelines](#community-guidelines) before you start participating.
## Topics
* [Reporting Security Issues](#reporting-security-issues)
* [Design and Cleanup Proposals](#design-and-cleanup-proposals)
* [Reporting Issues](#reporting-other-issues)
* [Quick Contribution Tips and Guidelines](#quick-contribution-tips-and-guidelines)
* [Community Guidelines](#community-guidelines)
## Reporting security issues
The attest maintainers take security seriously. If you discover a security issue, please bring it to their attention right away!
Please **DO NOT** file a public issue, instead send your report privately to [security@docker.com](mailto:security@docker.com).
Security reports are greatly appreciated and we will publicly thank you for it, although we keep your name confidential if you request it. We also like to send gifts—if you're into schwag, make sure to let us know. We currently do not offer a paid security bounty program, but are not ruling it out in the future.
## Reporting other issues
A great way to contribute to the project is to send a detailed report when you encounter an issue. We always appreciate a well-written, thorough bug report, and will thank you for it!
Check that [our issue database](https://github.com/docker/attest/issues) doesn't already include that problem or suggestion before submitting an issue. If you find a match, you can use the "subscribe" button to get notified on updates. Do *not* leave random "+1" or "I have this too" comments. Those comments can become annoying very quickly. Instead, use [GitHub reactions](https://docs.github.com/en/free-pro-team@latest/github/writing-on-github/using-emojis).
### How to report a bug
* **Use a clear and descriptive title** for the issue to identify the problem.
* **Describe the exact steps which reproduce the problem** in as many details as possible. When listing steps, **don't just say what you did, but explain how you did it**.
* **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. If you're providing snippets in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
* **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior.
* **Explain which behavior you expected to see instead and why.**
* **Include screenshots and animated GIFs** which show you following the described steps and clearly demonstrate the problem.
* **If the problem is related to performance or memory**, include a [CPU profile capture](https://blog.golang.org/profiling-go-programs) with your report.
* **If the problem wasn't triggered by a specific action**, describe what you were doing before the problem happened.
* **Include the version of attest you are using**.
* **Include the name and version of the OS you're using**.
## Quick contribution tips and guidelines
This section gives a brief overview of how to propose a change to attest.
### Contribution flow
1. Fork the repository on GitHub.
2. Create a topic branch from where you want to base your work.
3. Make commits of logical units.
4. Make sure your commit messages are in the proper format (see below).
5. Push your changes to a topic branch in your fork of the repository.
6. Submit a pull request to the original repository.
### Format of the commit message
We follow a rough convention for commit messages [borrowed from Angular](https://www.conventionalcommits.org/en/v1.0.0/).
- **feat**: A new feature
- **fix**: A bug fix
- **docs**: Documentation only changes
- **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
- **refactor**: A code change that neither fixes a bug nor adds a feature
- **perf**: A code change that improves performance
- **test**: Adding missing or correcting existing tests
- **chore**: Changes to the build process or auxiliary tools and libraries such as documentation generation
### Code review process
All submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose.
### Tips for contributors
1. All code should be formatted with `gofmt -s`.
2. All code should pass the default levels of [`golint`](https://github.com/golang/lint).
3. All code should follow the guidelines covered in [Effective Go](http://golang.org/doc/effective_go.html) and [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments).
4. Comment the code. Tell us the why, the history, and the context.
5. Document _all_ public declarations and methods. Declare expectations, caveats, and anything else that may be important. If a type gets exported, having the comments already there will ensure it's ready.
6. Variable name length should be proportional to its context and no longer. `noCommaALongVariableNameLikeThisIsNotMoreClearWhenASimpleCommentWouldDo`. In practice, short methods will have short variable names and globals will have longer names.
7. No underscores in package names. If you need a compound name, step back, and re-examine why you need a compound name. If you still think you need a compound name, lose the underscore.
8. No utils or helpers packages. If a function is not general enough to warrant its own package, it has not been written generally enough to be a part of a util package. Just leave it unexported and well-documented.
9. All tests should run with `go test` and outside tooling should not be required. No, we don't need another unit testing framework.
10. Even though we call these "rules" above, they are actually just guidelines. Since you've read all the rules, you now know that.
If you are having trouble getting into the mood of idiomatic Go, we recommend reading through [Effective Go](https://go.dev/doc/effective_go). The [Go Blog](https://go.dev/blog/) is also a great resource. Drinking the kool-aid is a lot easier than going thirsty.

15
NOTICE Normal file
View File

@@ -0,0 +1,15 @@
Docker attest
Copyright Docker attest authors
This product includes software developed at Docker, Inc. (https://www.docker.com).
The following is courtesy of our legal counsel:
Use and transfer of Docker may be subject to certain restrictions by the
United States and other governments.
It is your responsibility to ensure that your use and/or transfer does not
violate applicable laws.
For more information, please see https://www.bis.doc.gov
See also https://www.apache.org/dev/crypto.html and/or seek legal counsel.

386
README.md
View File

@@ -1,16 +1,382 @@
# attest
library to create, verify, and evaluate policy for attestations on container images
# `attest`
<div align="center">
Library to create attestation signatures on container images, and verify images against policy.
[![Go Reference](https://pkg.go.dev/badge/github.com/docker/attest.svg)](https://pkg.go.dev/github.com/docker/attest)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/docker/attest/test.yml?branch=main)](https://github.com/docker/attest/actions/workflows/test.yml)
[![codecov](https://codecov.io/gh/docker/attest/graph/badge.svg?token=cGT0f1ACKg)](https://codecov.io/gh/docker/attest)
# usage
## signing and verifying attestations
See [example_sign_test.go](./pkg/attest/example_sign_test.go)
</div>
See [example_verify_test.go](./pkg/attest/example_verify_test.go)
# Table of Contents
## mirroring TUF repositories to OCI
See [example_mirror_test.go](./pkg/mirror/example_mirror_test.go)
- [`attest`](#attest)
- [Table of Contents](#table-of-contents)
- [What is this?](#what-is-this)
- [Features](#features)
- [Installation](#installation)
- [Usage](#usage)
- [Verifying Image Attestations](#verifying-image-attestations)
- [Signing Attestations](#signing-attestations)
- [Rego Policy](#rego-policy)
- [Writing Policy](#writing-policy)
- [Input](#input)
- [Builtin Functions](#builtin-functions)
- [Policy Mapping](#policy-mapping)
- [Public Key IDs](#public-key-ids)
- [Transparency Logging](#transparency-logging)
- [Verification Summary Attestation (VSA)](#verification-summary-attestation-vsa)
- [Example VSA](#example-vsa)
- [API Reference](#api-reference)
- [Project Layout](#project-layout)
- [Versioning](#versioning)
### using `go-tuf` OCI registry client
See [example_registry_test.go](./pkg/tuf/example_registry_test.go)
# What is this?
`attest` is a library for signing and verifying [in-toto](https://in-toto.io/) attestations on container images.
Examples of attestations include statements about the provenance and SBOM of an image.
This library can be used to verify these attestations using Rego policy.
Policy can be used to check whether an attestation is correctly signed, and that the contents of the attestation are correct.
# Features
- Sign in-toto attestations
- Push attestations to container registries using OCI 1.1 compatible artifacts
- Verify attestations on container images using Rego policy and attestations fetched using OCI 1.1 referrers
# Installation
```shell
$ go get github.com/docker/attest
```
# Usage
## Verifying Image Attestations
An image's attestations can be verified against a policy using the `attest.Verify` function.
This function takes an [oci.ImageSpec](https://github.com/docker/attest/blob/781a738b54b9549c1dabfd7ea3f7ea582514ddec/pkg/oci/types.go#L35-L41) for the image to verify, and a set of options for policy resolution.
By default, the policy is resolved from the [the Docker TUF repository](https://github.com/docker/tuf), but the options can be used to specify an alternative TUF repository, a local policy directory, and/or a policy ID to use.
See [Policy Mapping](#policy-mapping) for more details.
The `attest.Verify` function returns a `VerificationSummary` object, which contains the results of the policy evaluation.
See [example_verify_test.go](./example_verify_test.go) for an example of how to verify an image against a policy.
## Signing Attestations
in-toto statements can be signed directly using the `attestation.SignInTotoStatement` function.
This function takes a statement and DSSE signer, and returns a signed DSSE envelope containing a copy of the original statement.
For the common use case of signing a statement and adding it to a manifest, e.g. for pushing to a registry as a referrer to the image being attested, the `attestation.AttestationManifest` type can be used.
See [example_attestation_manifest_test.go](./pkg/attestation/example_attestation_manifest_test.go)
See also [example_sign_test.go](./example_sign_test.go) for an example of how to sign all attached in-toto statements on an image, e.g. those produced by buildkit.
# Rego Policy
An image policy consists of one or more `rego` files and, optionally, `json` or `yaml` data files.
The policies for trusted namespaces `docker.io/docker` and `docker.io/library` are stored in [the Docker TUF root](https://github.com/docker/tuf) under the `docker` and `doi` target sub-directories respectively.
## Writing Policy
`attest` uses [Open Policy Agent](https://www.openpolicyagent.org/) (OPA) for policy evaluation, and policies are written in Rego.
A full guide to writing Rego policies is available in the [Rego documentation](https://www.openpolicyagent.org/docs/latest/policy-language/).
For attest, a policy must contain at a minimum a `result` rule in a package called `attest` that returns an object matching the schema defined by the [`policy.Result`](https://github.com/docker/attest/blob/bd2c4d7d8aa497754b674412b09628be8d02fab5/pkg/policy/types.go#L23-L27) struct.
For example:
```rego
package attest
import rego.v1
result := {
"success": true,
"violations": set(),
"summary": {
"subjects": subjects,
"slsa_levels": ["SLSA_BUILD_LEVEL_3"],
"verifier": "docker-official-images",
"policy_uri": "https://docker.com/official/policy/v0.1",
},
}
```
The meanings of the fields in the `result` object are as follows:
- `success` (bool): whether the policy passes
- `violations` (set): a set of strings describing any policy violations
- `summary` (object): a summary of the policy evaluation, used to construct a Verification Summary Attestation (VSA)
- `subjects` (set): a set of strings representing the subjects of each attestation that was evaluated
- `slsa_levels` (list): a list of strings representing the SLSA levels that the policy complies with
- `verifier` (string): the entity that verified the policy
- `policy_uri` (string): the URI of the policy
The `violations` set may contain policy violations even if `success` is `true`.
This can be useful if there are attestations that are invalid, but are not required by the policy.
### Input
The input to the policy is an object with the following fields:
- `digest` (string): the digest of the image being verified
- `purl` (string): the package URL of the image being verified
- `platform` (string): the platform of the image being verified
- `normalized_name` (string): defaults are filled out. e.g. if the image is `alpine`, this would be `library/alpine`
- `familiar_name` (string): short version of above (e.g. `alpine`)
- `tag`: (string): tag of the image being verified (if present)
### Builtin Functions
There are two builtin functions provided by `attest` that can be used to help with policy evaluation:
- `attest.fetch(predicate_type)`: fetches all attestations for the input image with the given predicate type.
For example, `attest.fetch("https://spdx.dev/Document")` will fetch all SPDX SBOM attestations for the input image.
- `attest.verify(attestation, options)`: verifies the DSSE envelope of the given attestation, and returns the statement.
The options object can contain the following fields:
- `keys` (array): keys to use for signature verification. Each key contains the following fields:
- `id` (string): the key ID as specified in [Public Key IDs](#public-key-ids)
- `key` (string): the PEM-encoded public key
- `from` (string): the time from which the key is valid, or `null` if the key was always valid (default: `null`)
- `status` (string): `active` if the key is active, otherwise the reason the key is inactive.
This is only used in error messages if the `from` date is in the past
- `distrust` (bool): whether the key should be distrusted (default: `false`).
If `true`, the key will be considered invalid
- `signing-format` (string): the format of the signing key, must be `dssev1`
- `skip_tl` (bool): whether to skip transparency log entry verification (see [Transparency Logging](#transparency-logging)) (default: `false`)
Both `attest.fetch` and `attest.verify` return an object with the following fields:
- `value`: the return value of the function if successful
- `error`: an error message if the function failed
This is to allow the policy to easily construct a violation if an error occurs, which isn't usually possible with custom functions in Rego.
The return value of `attest.fetch` is an attestation which can be passed to `attest.verify`.
## Policy Mapping
A `mapping.yaml` file is stored at the root of TUF targets and contains the mapping from repository name to files containing the corresponding policy.
A simple mapping file might look like this:
```yaml
version: v1
kind: policy-mapping
policies:
- id: docker-official-images
description: Docker Official Images
files:
- path: doi/policy.rego
rules:
- pattern: "^docker[.]io/library/(.*)$"
policy-id: docker-official-images
```
The `policies` section contains a list of policies, each with an `id` and a `description`, and a list of `files` containing the policy.
The `rules` section contains a list of rules that map regex expressions to policies.
If the `pattern` regex matches the repository name, the policy with the `policy-id` is used to evaluate the image.
In the above example, any repository in the `docker.io/library` namespace will be evaluated against the policy in `doi/policy.rego`.
Sometimes it is necessary to rewrite the repository name before evaluating the policy.
This can be useful when the repository name which is used to reference the image is different from the repository name in the attestations.
For example, when mirroring images from a public registry to a private registry, the repository name in the attestations will be the public registry, but the image will be referenced by the name of the private registry.
An example of a mapping file with rewrite rules might look like this:
```yaml
version: v1
kind: policy-mapping
policies:
- id: docker-official-images
description: Docker Official Images
files:
- path: doi/policy.rego
rules:
- pattern: "^docker[.]io/library/(.*)$"
policy-id: docker-official-images
- pattern: "^public[.]ecr[.]aws/docker/library/(.*)$"
platforms: ["linux/amd64"] # optional: restrict image platforms for matching policies (default: all)
rewrite: docker.io/library/$1
```
`platforms` in the second rule above is optional and can be used to restrict the platforms for which the policy
is evaluated. If the `platforms` field is not present, the policy will be applied to all platforms.
It's important to note that the `platforms` field is a filter, and is applied before the `pattern`
field is processed, so both `platforms` and `pattern` need to match in order for the policy to be selected
(or the rewrite to be processed if present).
As before, any repository in the `docker.io/library` namespace will be evaluated against the policy in `doi/policy.rego`.
The second rule will rewrite any repository in the `public.ecr.aws/docker/library` namespace to `docker.io/library`.
This means two things:
1. The rules are evaluated again using the rewritten repository name until a policy is found (in this case the first rule will match); and
2. The rewritten name is passed into the actual policy when it is evaluated.
The `rewrite` field is not a simple string replacement, but a regex replacement.
This means that the `rewrite` field can contain capture groups that are referenced in the `pattern` field.
For example, the `rewrite` field in the example above contains `$1`, which is a reference to the first capture group in the `pattern` field.
> [!IMPORTANT]
> It's important to remember to escape the `.` character in the `pattern` field, as it is a special character in regex.
> This is why the `.` character is surrounded by `[]` in the example above.
>
> It's also important to make use of the `^` and `$` characters in the `pattern` field to ensure that the regex matches the entire repository name.
> This is to prevent the regex from matching a subset of the repository name, e.g. `docker.io/library` matching `notdocker.io/library`.
Local policy can also be specified via a local `mapping.yaml`, which can be used to create new mirrors of policies described in the Docker TUF root, as well as describing entirely independent policies. For example:
```golang
// configure policy options
opts := &policy.PolicyOptions{
TufClient: tufClient,
LocalPolicyDir: "<policy-dir>", // overrides TUF policy for local policy files if set
PolicyId: "<policy-id>", // set to ignore policy mapping and select a policy by id
}
src, err := oci.ParseImageSpec(image, oci.WithPlatform(platform))
if err != nil {
panic(err)
}
// verify attestations
result, err := attest.Verify(context.Background(), src, opts)
if err != nil {
panic(err)
}
```
where `<policy-dir>` is a directory containing a `mapping.yaml` file, and any policy files referenced in the `mapping.yaml`. For example:
```
├── myimages
│ ├── data.yaml
| ├── keys.yaml
│ └── policy.rego
└── mapping.yaml
```
> [!NOTE]
>
> `PolicyId` can also be set to select a policy by ID, completely ignoring the `rules` section of the mapping file.
The rules section of a local `mapping.yaml` can refer to the policies described in the `mapping.yaml` file in the Docker TUF root to specify additional mirrors to which the referenced policy can be applied.
For example, it might be desirable to mirror `docker.io/library` to a local registry for testing:
```yaml
version: v1
kind: policy-mapping
rules:
- pattern: "^localhost:5001/(.*)$"
rewrite: docker.io/library/$1
```
The rewritten repository name will match the `docker-official-images` polict in the TUF managed `mapping.yaml`.
> [!WARNING]
> Local `mapping.yaml` policies take precendence over TUF managed policies, so for example, it's possible to apply a custom policy to `docker.io/library` namespace:
>
> ```yaml
> version: v1
> kind: policy-mapping
> policies:
> - id: mydoi
> description: my doi policy
> files:
> - path: "mypolicy.rego"
>
> rules:
> - pattern: "^docker[.]io/library/(.*)$"
> policy-id: mydoi
> ```
# Public Key IDs
When signing attestations, a key-id is generated from the public key and added to envelope.
This is used at verification time to look up the public key.
To generate a key-id from a public key, use `openssl` as follows:
```shell
openssl pkey -in <public-key.pem> -pubin -outform DER | openssl dgst -sha256
```
# Transparency Logging
`attest` supports transparency logging for attestation signatures.
This serves two purposes:
1. the transparency log is a mechanism to ensure that all attestations are logged in a tamper-evident way, and that the logs are publicly auditable; and
2. the transparency log is a trusted source of timestamps for attestations, which allows signatures to be verified even if the key used to sign the attestation has expired.
By default, transparency logging is enabled and the logs are stored in the [public-good Rekor](https://docs.sigstore.dev/logging/overview/) instance.
Another transparency log can be used by creating an implementation of the [tl.TL](https://github.com/docker/attest/blob/781a738b54b9549c1dabfd7ea3f7ea582514ddec/pkg/tlog/tl.go#L57-L62) interface and using [`tl.WithTL`](https://github.com/docker/attest/blob/781a738b54b9549c1dabfd7ea3f7ea582514ddec/pkg/tlog/tl.go#L37) to set in on a context.
Alternatively, transparency logging can be disabled when signing by using `SkipTL` in the `SigningOptions`, and when verifying by using `skip_tl` in the options to `attest.verify` in the Rego policy.
# Verification Summary Attestation (VSA)
Verification of attestations can be expensive, especially when the attestations are large.
For example, an SBOM attestation can be several megabytes in size.
An alternative to consumers verifying the full attestation is to have a trusted entity verify the attestation and publish a [SLSA Verification Summary Attestation](https://slsa.dev/spec/v1.0/verification_summary) (VSA) to the registry.
The VSA can then be verified by the consumer without needing to verify the full attestation, as long as the consumer trusts the entity that signed the VSA.
This is useful when the consumer only needs to know that the attestation was verified by a trusted entity, and does not need to know the details of the attestation.
A useful pattern is to have apply a policy to a third-party image at initial ingress, then publish a VSA when publishing the image to an internal registry to attest that the image complies with the policy.
The VSA can be verified very quickly, for example in a Kubernetes admission controller.
`attest` always generates a [SLSA VSA](https://slsa.dev/spec/v1.0/verification_summary) when verifying attestations on an image.
The VSA can be signed and published to the registry using the signing functions mentioned in [Signing Attestations](#signing-attestations).
## Example VSA
```json
{
"_type": "https://in-toto.io/Statement/v1",
"subject": [
{
"name": "pkg:docker/example.org/example-image@1.0?platform=linux%2Famd64",
"digest": {
"sha256": "49f717386e5462e945232569a97a05831cb83bef8c3369be3bb7ea1793686960"
}
}
],
"predicateType": "https://slsa.dev/verification_summary/v1",
"predicate": {
"verifier": {
"id": "https://example.org/internal-verifier"
},
"timeVerified": "2024-04-19T08:00:00.01Z",
"resourceUri": "pkg:docker/example.org/example-image@1.0?platform=linux%2Famd64&digest=sha256%3A49f717386e5462e945232569a97a05831cb83bef8c3369be3bb7ea1793686960",
"policy": {
"uri": "https://example.org/internal-policy/v1",
"downloadLocation": "https://docker.github.io/tuf-staging/targets/docker/d71d6b8f49fcba1295b16f5394dd5863a14e4277eb663d66d8c48e392509afe0.policy.rego",
"digest": {
"sha256": "d71d6b8f49fcba1295b16f5394dd5863a14e4277eb663d66d8c48e392509afe0"
}
},
"verificationResult": "PASSED",
"verifiedLevels": ["SLSA_BUILD_LEVEL_3"]
}
}
```
# API Reference
Full API reference can be found at [pkg.go.dev/github.com/docker/attest](https://pkg.go.dev/github.com/docker/attest).
# Project Layout
- [pkg/](https://pkg.go.dev/github.com/docker/image-signer-verifier/pkg) => packages that are okay to import for other projects
- [internal/](https://pkg.go.dev/github.com/docker/image-signer-verifier/pkg) => packages that are only for project internal purposes
- [scripts/](scripts/) => build scripts
- [test/](test/) => data for use in tests
# Versioning
`attest` uses [Semantic Versioning](https://semver.org/).
As such, until `attest` reaches version 1.0.0, breaking changes may be introduced in minor versions.
> Anything MAY change at any time. The public API SHOULD NOT be considered stable.

4
attestation/README.md Normal file
View File

@@ -0,0 +1,4 @@
## attestations
This package is for components that deal with the creation, storage, and retrieval of signed attestions using OCI.
For more generic OCI components see the `oci` package.

470
attestation/attestation.go Normal file
View File

@@ -0,0 +1,470 @@
/*
Copyright Docker attest 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.
*/
package attestation
import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"maps"
"strings"
"github.com/docker/attest/oci"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/empty"
"github.com/google/go-containerregistry/pkg/v1/layout"
"github.com/google/go-containerregistry/pkg/v1/match"
"github.com/google/go-containerregistry/pkg/v1/mutate"
"github.com/google/go-containerregistry/pkg/v1/partial"
"github.com/google/go-containerregistry/pkg/v1/static"
"github.com/google/go-containerregistry/pkg/v1/types"
intoto "github.com/in-toto/in-toto-golang/in_toto"
"github.com/secure-systems-lab/go-securesystemslib/dsse"
)
// NewManifest creates a new attestation manifest from a descriptor.
func NewManifest(subject *v1.Descriptor) (*Manifest, error) {
return &Manifest{
OriginalDescriptor: &v1.Descriptor{
MediaType: "application/vnd.oci.image.manifest.v1+json",
},
OriginalLayers: []*Layer{},
SubjectDescriptor: subject,
}, nil
}
// ManifestsFromIndex extracts all attestation manifests from an index.
func ManifestsFromIndex(index v1.ImageIndex) ([]*Manifest, error) {
idx, err := index.IndexManifest()
if err != nil {
return nil, fmt.Errorf("failed to extract IndexManifest from ImageIndex: %w", err)
}
subjects := make(map[string]*v1.Descriptor)
for i := range idx.Manifests {
subject := &idx.Manifests[i]
subjects[subject.Digest.String()] = subject
}
var attestationManifests []*Manifest
for i := range idx.Manifests {
desc := idx.Manifests[i]
if desc.Annotations[DockerReferenceType] == AttestationManifestType {
subject := subjects[desc.Annotations[DockerReferenceDigest]]
if subject == nil {
return nil, fmt.Errorf("failed to find subject for attestation manifest: %w", err)
}
attestationImage, err := index.Image(desc.Digest)
if err != nil {
return nil, fmt.Errorf("failed to extract attestation image with digest %s: %w", desc.Digest.String(), err)
}
attestationLayers, err := layersFromImage(attestationImage)
if err != nil {
return nil, fmt.Errorf("failed to get attestations from image: %w", err)
}
attestationManifests = append(attestationManifests,
&Manifest{
OriginalDescriptor: &desc,
SubjectDescriptor: subject,
OriginalLayers: attestationLayers,
})
}
}
return attestationManifests, nil
}
// LayersFromImage extracts all attestation layers from an image.
func layersFromImage(image v1.Image) ([]*Layer, error) {
layers, err := image.Layers()
if err != nil {
return nil, fmt.Errorf("failed to extract layers from image: %w", err)
}
var attestationLayers []*Layer
for _, layer := range layers {
// parse layer blob as json
r, err := layer.Uncompressed()
if err != nil {
return nil, fmt.Errorf("failed to get layer contents: %w", err)
}
defer r.Close()
mt, err := layer.MediaType()
if err != nil {
return nil, fmt.Errorf("failed to get layer media type: %w", err)
}
layerDesc, err := partial.Descriptor(layer)
if err != nil {
return nil, fmt.Errorf("failed to get descriptor for layer: %w", err)
}
// copy original annotations
ann := maps.Clone(layerDesc.Annotations)
// only decode intoto statements
var stmt *intoto.Statement
if mt == types.MediaType(intoto.PayloadType) {
stmt = new(intoto.Statement)
err = json.NewDecoder(r).Decode(&stmt)
if err != nil {
return nil, fmt.Errorf("failed to decode statement layer contents: %w", err)
}
}
attestationLayers = append(attestationLayers, &Layer{Layer: layer, Statement: stmt, Annotations: ann})
}
return attestationLayers, nil
}
func (manifest *Manifest) Add(ctx context.Context, signer dsse.SignerVerifier, statement *intoto.Statement, opts *SigningOptions) error {
layer, err := createSignedImageLayer(ctx, statement, signer, opts)
if err != nil {
return fmt.Errorf("failed to create signed layer: %w", err)
}
manifest.SignedLayers = append(manifest.SignedLayers, layer)
return nil
}
func createSignedImageLayer(ctx context.Context, statement *intoto.Statement, signer dsse.SignerVerifier, opts *SigningOptions) (*Layer, error) {
// sign the statement
env, err := signInTotoStatement(ctx, statement, signer, opts)
if err != nil {
return nil, fmt.Errorf("failed to sign statement: %w", err)
}
mediaType, err := DSSEMediaType(statement.PredicateType)
if err != nil {
return nil, fmt.Errorf("failed to get DSSE media type: %w", err)
}
data, err := json.Marshal(env)
if err != nil {
return nil, fmt.Errorf("failed to marshal envelope: %w", err)
}
return &Layer{
Statement: statement,
Annotations: map[string]string{
InTotoPredicateType: statement.PredicateType,
InTotoReferenceLifecycleStage: LifecycleStageExperimental,
},
Layer: static.NewLayer(data, types.MediaType(mediaType)),
}, nil
}
func signInTotoStatement(ctx context.Context, statement *intoto.Statement, signer dsse.SignerVerifier, opts *SigningOptions) (*Envelope, error) {
payload, err := json.Marshal(statement)
if err != nil {
return nil, fmt.Errorf("failed to marshal statement: %w", err)
}
env, err := SignDSSE(ctx, payload, signer, opts)
if err != nil {
return nil, fmt.Errorf("failed to sign statement: %w", err)
}
return env, nil
}
func updateImageIndex(
idx v1.ImageIndex,
manifest *Manifest,
options ...func(*ManifestImageOptions) error,
) (v1.ImageIndex, error) {
image, err := manifest.BuildImage(options...)
if err != nil {
return nil, fmt.Errorf("failed to build image: %w", err)
}
newDesc, err := partial.Descriptor(image)
if err != nil {
return nil, fmt.Errorf("failed to get descriptor: %w", err)
}
newDesc.Platform = &v1.Platform{
Architecture: "unknown",
OS: "unknown",
}
newDesc.MediaType = manifest.OriginalDescriptor.MediaType
newDesc.Annotations = manifest.OriginalDescriptor.Annotations
idx = mutate.RemoveManifests(idx, match.Digests(manifest.OriginalDescriptor.Digest))
idx = mutate.AppendManifests(idx, mutate.IndexAddendum{
Add: image,
Descriptor: *newDesc,
})
return idx, nil
}
func UpdateIndexImages(idx v1.ImageIndex, manifest []*Manifest, options ...func(*ManifestImageOptions) error) (v1.ImageIndex, error) {
var err error
for _, m := range manifest {
idx, err = updateImageIndex(idx, m, options...)
if err != nil {
return nil, fmt.Errorf("failed to add image to index: %w", err)
}
}
return idx, nil
}
func newOptions(options ...func(*ManifestImageOptions) error) (*ManifestImageOptions, error) {
opts := &ManifestImageOptions{}
for _, opt := range options {
err := opt(opts)
if err != nil {
return nil, err
}
}
return opts, nil
}
func WithoutSubject(skipSubject bool) func(*ManifestImageOptions) error {
return func(r *ManifestImageOptions) error {
r.skipSubject = skipSubject
return nil
}
}
func WithReplacedLayers(replaceLayers bool) func(*ManifestImageOptions) error {
return func(r *ManifestImageOptions) error {
r.replaceLayers = replaceLayers
return nil
}
}
// build an image with signed attestations, optionally replacing existing layers with signed layers.
func (manifest *Manifest) BuildImage(options ...func(*ManifestImageOptions) error) (v1.Image, error) {
opts, err := newOptions(options...)
if err != nil {
return nil, fmt.Errorf("failed to create options: %w", err)
}
resultLayers := manifest.SignedLayers
for _, existingLayer := range manifest.OriginalLayers {
var found bool
for _, signedLayer := range manifest.SignedLayers {
if existingLayer.Statement == signedLayer.Statement {
found = true
// copy over original annotations
for k, v := range existingLayer.Annotations {
signedLayer.Annotations[k] = v
}
break
}
}
// add existing layers if they've not been signed or we're not replacing them
if !found || !opts.replaceLayers {
resultLayers = append(resultLayers, existingLayer)
}
}
// so that we attach all attestations to a single attestations image - as per current buildkit
opts.laxReferrers = true
newImg, err := buildImageFromLayers(resultLayers, manifest.OriginalDescriptor, manifest.SubjectDescriptor, opts)
if err != nil {
return nil, fmt.Errorf("failed to build image: %w", err)
}
return newImg, nil
}
// build an image per attestation (layer) suitable for use as Referrers.
func (manifest *Manifest) BuildReferringArtifacts() ([]v1.Image, error) {
var images []v1.Image
for _, layer := range manifest.SignedLayers {
opts := &ManifestImageOptions{}
newImg, err := buildImageFromLayers([]*Layer{layer}, manifest.OriginalDescriptor, manifest.SubjectDescriptor, opts)
if err != nil {
return nil, fmt.Errorf("failed to build image: %w", err)
}
images = append(images, newImg)
}
return images, nil
}
// build an image containing only layers provided.
func buildImageFromLayers(layers []*Layer, manifest *v1.Descriptor, subject *v1.Descriptor, opts *ManifestImageOptions) (v1.Image, error) {
newImg := empty.Image
var err error
if len(layers) == 0 {
return nil, fmt.Errorf("no layers supplied to build image")
}
// NB: if we add the subject before the layers, it does not end up being computed/serialized in the output for some reason
// TODO - recreate this bug and push upstream
for _, layer := range layers {
add := mutate.Addendum{
Layer: layer.Layer,
Annotations: layer.Annotations,
}
newImg, err = mutate.Append(newImg, add)
if err != nil {
return nil, fmt.Errorf("failed to add layer to image: %w", err)
}
}
// this is for attaching attestations to an attestation image in the index
if opts.laxReferrers {
newImg = mutate.ConfigMediaType(newImg, "application/vnd.oci.image.config.v1+json")
} else {
dsseMediatType, err := DSSEMediaType(layers[0].Statement.PredicateType)
if err != nil {
return nil, fmt.Errorf("failed to get DSSE media type: %w", err)
}
newImg = mutate.ArtifactType(newImg, dsseMediatType)
newImg = mutate.ConfigMediaType(newImg, "application/vnd.oci.empty.v1+json")
}
// we need to set this even when we set the artifact type otherwise things break (even the go-container-registry client)
// even though it's allowed to be empty by spec when setting artifact type
newImg = mutate.MediaType(newImg, manifest.MediaType)
// see note above - must be added after the layers!
if !opts.skipSubject {
subject.Platform = nil
ok := false
newImg, ok = mutate.Subject(newImg, *subject).(v1.Image)
if !ok {
return nil, fmt.Errorf("failed to set subject: %w", err)
}
}
if !opts.laxReferrers {
// as per https://github.com/opencontainers/image-spec/blob/main/manifest.md#guidance-for-an-empty-descriptor
newImg = &oci.EmptyConfigImage{Image: newImg}
}
return newImg, nil
}
func ExtractEnvelopes(manifest *Manifest, predicateType string) ([]*EnvelopeReference, error) {
var envs []*EnvelopeReference
dsseMediaType, err := DSSEMediaType(predicateType)
if err != nil {
return nil, fmt.Errorf("failed to get DSSE media type for predicate '%s': %w", predicateType, err)
}
for _, attestationLayer := range manifest.OriginalLayers {
mt, err := attestationLayer.Layer.MediaType()
if err != nil {
return nil, fmt.Errorf("failed to get layer media type: %w", err)
}
if string(mt) == dsseMediaType {
reader, err := attestationLayer.Layer.Uncompressed()
if err != nil {
return nil, fmt.Errorf("failed to get layer contents: %w", err)
}
defer reader.Close()
env := new(EnvelopeReference)
err = json.NewDecoder(reader).Decode(&env)
if err != nil {
return nil, fmt.Errorf("failed to decode envelope: %w", err)
}
var uri string
if len(manifest.OriginalDescriptor.URLs) > 0 {
uri = manifest.OriginalDescriptor.URLs[0]
}
env.ResourceDescriptor = &ResourceDescriptor{
MediaType: string(mt),
Digest: map[string]string{manifest.OriginalDescriptor.Digest.Algorithm: manifest.OriginalDescriptor.Digest.Hex},
URI: uri,
}
envs = append(envs, env)
}
}
return envs, nil
}
func ExtractStatementsFromIndex(idx v1.ImageIndex, mediaType string) ([]*AnnotatedStatement, error) {
mfs2, err := idx.IndexManifest()
if err != nil {
return nil, fmt.Errorf("failed to extract IndexManifest from ImageIndex: %w", err)
}
var statements []*AnnotatedStatement
for i := range mfs2.Manifests {
mf := &mfs2.Manifests[i]
if mf.Annotations[DockerReferenceType] != "attestation-manifest" {
continue
}
attestationImage, err := idx.Image(mf.Digest)
if err != nil {
return nil, fmt.Errorf("failed to extract attestation image with digest %s: %w", mf.Digest.String(), err)
}
layers, err := attestationImage.Layers()
if err != nil {
return nil, fmt.Errorf("failed to extract layers from attestation image: %w", err)
}
for _, layer := range layers {
// parse layer blob as json
mt, err := layer.MediaType()
if err != nil {
return nil, fmt.Errorf("failed to get layer media type: %w", err)
}
if string(mt) != mediaType {
continue
}
r, err := layer.Uncompressed()
if err != nil {
return nil, fmt.Errorf("failed to get layer contents: %w", err)
}
defer r.Close()
inTotoStatement := new(intoto.Statement)
var desc *v1.Descriptor
if strings.HasSuffix(string(mt), "+dsse") {
env := new(Envelope)
err = json.NewDecoder(r).Decode(env)
if err != nil {
return nil, fmt.Errorf("failed to decode env: %w", err)
}
payload, err := base64.StdEncoding.Strict().DecodeString(env.Payload)
if err != nil {
return nil, fmt.Errorf("failed to decode payload: %w", err)
}
err = json.Unmarshal([]byte(payload), inTotoStatement)
if err != nil {
return nil, fmt.Errorf("failed to decode %s statement: %w", mediaType, err)
}
} else {
desc := new(v1.Descriptor)
err = json.NewDecoder(r).Decode(desc)
if err != nil {
return nil, fmt.Errorf("failed to decode statement: %w", err)
}
}
layerDesc, err := partial.Descriptor(layer)
if err != nil {
return nil, fmt.Errorf("failed to get descriptor for layer: %w", err)
}
annotations := make(map[string]string)
for k, v := range layerDesc.Annotations {
annotations[k] = v
}
statements = append(statements, &AnnotatedStatement{
OCIDescriptor: desc,
InTotoStatement: inTotoStatement,
Annotations: annotations,
})
}
}
return statements, nil
}
func ExtractAnnotatedStatements(path string, mediaType string) ([]*AnnotatedStatement, error) {
idx, err := layout.ImageIndexFromPath(path)
if err != nil {
return nil, fmt.Errorf("failed to load image index: %w", err)
}
idxm, err := idx.IndexManifest()
if err != nil {
return nil, fmt.Errorf("failed to get digest: %w", err)
}
idxDigest := idxm.Manifests[0].Digest
mfs, err := idx.ImageIndex(idxDigest)
if err != nil {
return nil, fmt.Errorf("failed to extract ImageIndex for digest %s: %w", idxDigest.String(), err)
}
return ExtractStatementsFromIndex(mfs, mediaType)
}

View File

@@ -0,0 +1,34 @@
/*
Copyright Docker attest 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.
*/
package attestation_test
import (
"testing"
"github.com/docker/attest/attestation"
"github.com/docker/attest/internal/test"
intoto "github.com/in-toto/in-toto-golang/in_toto"
"github.com/stretchr/testify/assert"
)
const ExpectedStatements = 4
func TestExtractAnnotatedStatements(t *testing.T) {
statements, err := attestation.ExtractAnnotatedStatements(test.UnsignedTestIndex(".."), intoto.PayloadType)
assert.NoError(t, err)
assert.Equalf(t, len(statements), ExpectedStatements, "expected %d statement, got %d", ExpectedStatements, len(statements))
}

View File

@@ -0,0 +1,106 @@
/*
Copyright Docker attest 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.
*/
package attestation_test
import (
"context"
"time"
"github.com/docker/attest/attestation"
"github.com/docker/attest/oci"
"github.com/docker/attest/signerverifier"
v1 "github.com/google/go-containerregistry/pkg/v1"
intoto "github.com/in-toto/in-toto-golang/in_toto"
"github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common"
)
func ExampleManifest() {
// configure signerverifier
// local signer (unsafe for production)
signer, err := signerverifier.GenKeyPair()
if err != nil {
panic(err)
}
// example using AWS KMS signer
// aws_arn := "arn:aws:kms:us-west-2:123456789012:key/12345678-1234-1234-1234-123456789012"
// aws_region := "us-west-2"
// signer, err := signerverifier.GetAWSSigner(cmd.Context(), aws_arn, aws_region)
// configure signing options
opts := &attestation.SigningOptions{
TransparencyLog: nil, // set this to log to a transparency log
}
ref := "docker/image-signer-verifier:latest"
digest, err := v1.NewHash("sha256:7ae6b41655929ad8e1848064874a98ac3f68884996c79907f6525e3045f75390")
if err != nil {
panic(err)
}
desc := &v1.Descriptor{
Digest: digest,
Size: 1234,
MediaType: "application/vnd.oci.image.manifest.v1+json",
}
// the in-toto statement to be signed
statement := &intoto.Statement{
StatementHeader: intoto.StatementHeader{
PredicateType: attestation.VSAPredicateType,
Subject: []intoto.Subject{{Name: ref, Digest: common.DigestSet{digest.Algorithm: digest.Hex}}},
Type: intoto.StatementInTotoV01,
},
Predicate: attestation.VSAPredicate{
Verifier: attestation.VSAVerifier{
ID: "test-verifier",
},
TimeVerified: time.Now().UTC().Format(time.RFC3339),
ResourceURI: "some-uri",
Policy: attestation.VSAPolicy{URI: "some-uri"},
VerificationResult: "PASSED",
VerifiedLevels: []string{"SLSA_BUILD_LEVEL_1"},
},
}
// create a new manifest to hold the attestation
manifest, err := attestation.NewManifest(desc)
if err != nil {
panic(err)
}
// sign and add the attestation to the manifest
err = manifest.Add(context.Background(), signer, statement, opts)
if err != nil {
panic(err)
}
output, err := oci.ParseImageSpecs("docker/image-signer-verifier-referrers:latest")
if err != nil {
panic(err)
}
// save the manifest to the registry as a referrers artifact
artifacts, err := manifest.BuildReferringArtifacts()
if err != nil {
panic(err)
}
ctx := context.Background()
err = oci.SaveImagesNoTag(ctx, artifacts, output)
if err != nil {
panic(err)
}
}

197
attestation/layout.go Normal file
View File

@@ -0,0 +1,197 @@
/*
Copyright Docker attest 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.
*/
package attestation
import (
"context"
"encoding/json"
"fmt"
containerd "github.com/containerd/containerd/v2/core/images"
"github.com/distribution/reference"
"github.com/docker/attest/oci"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/layout"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
// implementation of Resolver that closes over attestations from an oci layout.
var _ Resolver = (*LayoutResolver)(nil)
type LayoutResolver struct {
*Manifest
*oci.ImageSpec
}
func NewOCILayoutResolver(src *oci.ImageSpec) (*LayoutResolver, error) {
r := &LayoutResolver{
ImageSpec: src,
}
_, err := r.fetchManifest()
if err != nil {
return nil, err
}
return r, nil
}
func (r *LayoutResolver) fetchManifest() (*Manifest, error) {
if r.Manifest == nil {
m, err := manifestFromOCILayout(r.Identifier, r.ImageSpec.Platform)
if err != nil {
return nil, err
}
r.Manifest = m
}
return r.Manifest, nil
}
func (r *LayoutResolver) Attestations(_ context.Context, predicateType string) ([]*EnvelopeReference, error) {
var envs []*EnvelopeReference
dsseMediaType, err := DSSEMediaType(predicateType)
if err != nil {
return nil, fmt.Errorf("failed to get DSSE media type for predicate '%s': %w", predicateType, err)
}
for _, attestationLayer := range r.Manifest.OriginalLayers {
mt, err := attestationLayer.Layer.MediaType()
if err != nil {
return nil, fmt.Errorf("failed to get layer media type: %w", err)
}
mts := string(mt)
if mts != dsseMediaType {
continue
}
env := new(EnvelopeReference)
// parse layer blob as json
layer, err := attestationLayer.Layer.Uncompressed()
if err != nil {
return nil, fmt.Errorf("failed to get layer contents: %w", err)
}
defer layer.Close()
err = json.NewDecoder(layer).Decode(env)
if err != nil {
return nil, fmt.Errorf("failed to decode envelope: %w", err)
}
var uri string
if len(r.Manifest.OriginalDescriptor.URLs) > 0 {
uri = r.Manifest.OriginalDescriptor.URLs[0]
}
env.ResourceDescriptor = &ResourceDescriptor{
MediaType: string(mt),
Digest: map[string]string{r.Manifest.OriginalDescriptor.Digest.Algorithm: r.Manifest.OriginalDescriptor.Digest.Hex},
URI: uri,
}
envs = append(envs, env)
}
return envs, nil
}
func (r *LayoutResolver) ImageName(_ context.Context) (string, error) {
return r.SubjectName, nil
}
func (r *LayoutResolver) ImageDescriptor(_ context.Context) (*v1.Descriptor, error) {
return r.SubjectDescriptor, nil
}
func (r *LayoutResolver) ImagePlatform(_ context.Context) (*v1.Platform, error) {
return r.ImageSpec.Platform, nil
}
func manifestFromOCILayout(path string, platform *v1.Platform) (*Manifest, error) {
layoutIndex, err := layout.ImageIndexFromPath(path)
if err != nil {
return nil, err
}
layoutIndexManifest, err := layoutIndex.IndexManifest()
if err != nil {
return nil, fmt.Errorf("failed to get digest: %w", err)
}
layoutDescriptor := layoutIndexManifest.Manifests[0]
layoutDescriptorDigest := layoutDescriptor.Digest
subjectName := layoutDescriptor.Annotations[ocispec.AnnotationRefName]
if _, err := reference.ParseNamed(subjectName); err != nil {
// try the containerd annotation if the org.opencontainers.image.ref.name is not a full name
subjectName = layoutDescriptor.Annotations[containerd.AnnotationImageName]
if _, err := reference.ParseNamed(subjectName); err != nil {
return nil, fmt.Errorf("failed to find subject name in annotations")
}
}
// check if digest refers to an image or an index
_, err = layoutIndex.Image(layoutDescriptorDigest)
if err == nil {
return &Manifest{
OriginalLayers: nil,
OriginalDescriptor: nil,
SubjectName: subjectName,
SubjectDescriptor: &layoutDescriptor,
}, nil
}
subjectIndex, err := layoutIndex.ImageIndex(layoutDescriptorDigest)
if err != nil {
return nil, fmt.Errorf("failed to extract ImageIndex for digest %s: %w", layoutDescriptorDigest.String(), err)
}
subjectIndexManifest, err := subjectIndex.IndexManifest()
if err != nil {
return nil, fmt.Errorf("failed to extract IndexManifest from ImageIndex: %w", err)
}
var subjectDescriptor *v1.Descriptor
for i := range subjectIndexManifest.Manifests {
manifest := &subjectIndexManifest.Manifests[i]
if manifest.Platform != nil {
if manifest.Platform.Equals(*platform) {
subjectDescriptor = manifest
break
}
}
}
if subjectDescriptor == nil {
return nil, fmt.Errorf("platform not found in index")
}
for i := range subjectIndexManifest.Manifests {
mf := &subjectIndexManifest.Manifests[i]
if mf.Annotations[DockerReferenceType] != AttestationManifestType {
continue
}
if mf.Annotations[DockerReferenceDigest] != subjectDescriptor.Digest.String() {
continue
}
attestationImage, err := subjectIndex.Image(mf.Digest)
if err != nil {
return nil, fmt.Errorf("failed to extract attestation image with digest %s: %w", mf.Digest.String(), err)
}
layers, err := layersFromImage(attestationImage)
if err != nil {
return nil, fmt.Errorf("failed to get attestations from image: %w", err)
}
attest := &Manifest{
OriginalLayers: layers,
OriginalDescriptor: mf,
SubjectName: subjectName,
SubjectDescriptor: subjectDescriptor,
}
return attest, nil
}
return nil, fmt.Errorf("attestation manifest not found")
}

123
attestation/layout_test.go Normal file
View File

@@ -0,0 +1,123 @@
/*
Copyright Docker attest 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.
*/
package attestation_test
import (
"context"
"path/filepath"
"strings"
"testing"
"github.com/docker/attest"
"github.com/docker/attest/attestation"
"github.com/docker/attest/internal/test"
"github.com/docker/attest/oci"
"github.com/docker/attest/policy"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestAttestationFromOCILayout(t *testing.T) {
ctx, signer := test.Setup(t)
outputLayout := test.CreateTempDir(t, "", "attest-oci-layout")
invalidPlatform := &v1.Platform{
Architecture: "invalid",
OS: "invalid",
}
opts := &attestation.SigningOptions{}
attIdx, err := oci.IndexFromPath(test.UnsignedTestIndex(".."))
require.NoError(t, err)
signedManifests, err := attest.SignStatements(ctx, attIdx.Index, signer, opts)
require.NoError(t, err)
signedIndex := attIdx.Index
signedIndex, err = attestation.UpdateIndexImages(signedIndex, signedManifests)
require.NoError(t, err)
spec, err := oci.ParseImageSpec(oci.LocalPrefix + outputLayout)
require.NoError(t, err)
err = oci.SaveIndex(ctx, []*oci.ImageSpec{spec}, signedIndex, "docker.io/library/test-image:test")
require.NoError(t, err)
testCases := []struct {
name string
platform *v1.Platform
errorStr string
}{
{name: "nominal", platform: spec.Platform},
{name: "invalid platform", platform: invalidPlatform, errorStr: "platform not found in index"},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
spec := &oci.ImageSpec{
Type: oci.OCI,
Identifier: outputLayout,
Platform: tc.platform,
}
resolver, err := policy.CreateImageDetailsResolver(spec)
if tc.errorStr != "" {
require.Error(t, err)
assert.Contains(t, err.Error(), tc.errorStr)
return
}
require.NoError(t, err)
desc, err := resolver.ImageDescriptor(ctx)
require.NoError(t, err)
digest := desc.Digest.String()
assert.True(t, strings.Contains(digest, "sha256:"))
})
}
}
func TestSubjectNameAnnotations(t *testing.T) {
testCases := []struct {
name string
ociLayoutPath string
errorStr string
}{
{name: "oci annotation", ociLayoutPath: test.UnsignedTestIndex("..")},
{name: "containerd annotation", ociLayoutPath: filepath.Join("..", "test", "testdata", "containerd-subject-layout")},
{name: "missing subject name", ociLayoutPath: filepath.Join("..", "test", "testdata", "missing-subject-layout"), errorStr: "failed to find subject name in annotations"},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
spec, err := oci.ParseImageSpec(oci.LocalPrefix+tc.ociLayoutPath, oci.WithPlatform("linux/arm64"))
require.NoError(t, err)
_, err = policy.CreateImageDetailsResolver(spec)
if tc.errorStr != "" {
require.Error(t, err)
assert.Contains(t, err.Error(), tc.errorStr)
return
}
require.NoError(t, err)
})
}
}
func TestImageDetailsFromImageLayout(t *testing.T) {
spec, err := oci.ParseImageSpec(oci.LocalPrefix+test.UnsignedTestImage(".."), oci.WithPlatform("linux/arm64"))
require.NoError(t, err)
resolver, err := policy.CreateImageDetailsResolver(spec)
require.NoError(t, err)
desc, err := resolver.ImageDescriptor(context.Background())
require.NoError(t, err)
digest := desc.Digest.String()
assert.Equal(t, "sha256:7ae6b41655929ad8e1848064874a98ac3f68884996c79907f6525e3045f75390", digest)
}

86
attestation/mock.go Normal file
View File

@@ -0,0 +1,86 @@
/*
Copyright Docker attest 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.
*/
package attestation
import (
"context"
"github.com/docker/attest/internal/test"
"github.com/docker/attest/oci"
v1 "github.com/google/go-containerregistry/pkg/v1"
)
// ensure MockResolver implements Resolver.
var _ oci.ImageDetailsResolver = MockResolver{}
type MockResolver struct {
Envs []*EnvelopeReference
Image string
PlatformFn func() (*v1.Platform, error)
DescriptorFn func() (*v1.Descriptor, error)
ImangeNameFn func() (string, error)
}
func (r MockResolver) Attestations(_ context.Context, _ string) ([]*EnvelopeReference, error) {
return r.Envs, nil
}
func (r MockResolver) ImageName(_ context.Context) (string, error) {
if r.Image != "" {
return r.Image, nil
}
if r.ImangeNameFn != nil {
return r.ImangeNameFn()
}
return "library/alpine:latest", nil
}
func (r MockResolver) ImageDescriptor(_ context.Context) (*v1.Descriptor, error) {
if r.DescriptorFn != nil {
return r.DescriptorFn()
}
digest, err := v1.NewHash(test.UnsignedLinuxAMD64ImageDigest)
if err != nil {
return nil, err
}
return &v1.Descriptor{
Digest: digest,
Size: 1234,
MediaType: "application/vnd.oci.image.manifest.v1+json",
}, nil
}
func (r MockResolver) ImagePlatform(_ context.Context) (*v1.Platform, error) {
if r.PlatformFn != nil {
return r.PlatformFn()
}
return oci.ParsePlatform("linux/amd64")
}
type MockRegistryResolver struct {
Subject *v1.Descriptor
ImageNameStr string
*MockResolver
}
func (r *MockRegistryResolver) ImageDescriptor(_ context.Context) (*v1.Descriptor, error) {
return r.Subject, nil
}
func (r *MockRegistryResolver) ImageName(_ context.Context) (string, error) {
return r.ImageNameStr, nil
}

View File

@@ -1,21 +1,40 @@
package oci
/*
Copyright Docker attest 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.
*/
package attestation
import (
"context"
"fmt"
"strings"
"github.com/docker/attest/pkg/attestation"
att "github.com/docker/attest/pkg/attestation"
"github.com/docker/attest/oci"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote"
)
// ensure ReferrersResolver implements Resolver.
var _ Resolver = &ReferrersResolver{}
type ReferrersResolver struct {
referrersRepo string
ImageDetailsResolver
oci.ImageDetailsResolver
}
func NewReferrersAttestationResolver(src ImageDetailsResolver, options ...func(*ReferrersResolver) error) (*ReferrersResolver, error) {
func NewReferrersResolver(src oci.ImageDetailsResolver, options ...func(*ReferrersResolver) error) (*ReferrersResolver, error) {
res := &ReferrersResolver{
ImageDetailsResolver: src,
}
@@ -35,9 +54,8 @@ func WithReferrersRepo(repo string) func(*ReferrersResolver) error {
}
}
func (r *ReferrersResolver) resolveAttestations(ctx context.Context, predicateType string) ([]*attestation.AttestationManifest,
error) {
dsseMediaType, err := attestation.DSSEMediaType(predicateType)
func (r *ReferrersResolver) resolveAttestations(ctx context.Context, predicateType string) ([]*Manifest, error) {
dsseMediaType, err := DSSEMediaType(predicateType)
if err != nil {
return nil, fmt.Errorf("failed to get DSSE media type for predicate '%s': %w", predicateType, err)
}
@@ -54,19 +72,16 @@ func (r *ReferrersResolver) resolveAttestations(ctx context.Context, predicateTy
return nil, fmt.Errorf("failed to get descriptor: %w", err)
}
subjectDigest := desc.Digest.String()
if err != nil {
return nil, fmt.Errorf("failed to get digest: %w", err)
}
var referrersSubjectRef name.Digest
if r.referrersRepo != "" {
referrersSubjectRef, err = name.NewDigest(fmt.Sprintf("%s@%s", r.referrersRepo, subjectDigest))
referrersSubjectRef, err = name.NewDigest(fmt.Sprintf("%s@%s", strings.TrimPrefix(r.referrersRepo, oci.RegistryPrefix), subjectDigest))
if err != nil {
return nil, fmt.Errorf("failed to create referrers reference: %w", err)
}
} else {
referrersSubjectRef = subjectRef.Context().Digest(subjectDigest)
}
options := WithOptions(ctx, nil)
options := oci.WithOptions(ctx, nil)
options = append(options, remote.WithFilter("artifactType", dsseMediaType))
referrersIndex, err := remote.Referrers(referrersSubjectRef, options...)
if err != nil {
@@ -76,14 +91,16 @@ func (r *ReferrersResolver) resolveAttestations(ctx context.Context, predicateTy
if err != nil {
return nil, fmt.Errorf("failed to get index manifest: %w", err)
}
aManifests := make([]*attestation.AttestationManifest, 0)
for _, m := range referrersIndexManifest.Manifests {
aManifests := make([]*Manifest, 0)
for i := range referrersIndexManifest.Manifests {
m := referrersIndexManifest.Manifests[i]
remoteRef := referrersSubjectRef.Context().Digest(m.Digest.String())
attestationImage, err := remote.Image(remoteRef)
options = oci.WithOptions(ctx, nil)
attestationImage, err := remote.Image(remoteRef, options...)
if err != nil {
return nil, fmt.Errorf("failed to get referred image: %w", err)
}
layers, err := attestation.GetAttestationsFromImage(attestationImage)
layers, err := layersFromImage(attestationImage)
if err != nil {
return nil, fmt.Errorf("failed to get attestations from image: %w", err)
}
@@ -97,7 +114,7 @@ func (r *ReferrersResolver) resolveAttestations(ctx context.Context, predicateTy
if string(mt) != dsseMediaType {
return nil, fmt.Errorf("expected layer media type %s, got %s", dsseMediaType, mt)
}
attest := &attestation.AttestationManifest{
attest := &Manifest{
SubjectName: imageName,
OriginalLayers: layers,
OriginalDescriptor: &m,
@@ -108,12 +125,12 @@ func (r *ReferrersResolver) resolveAttestations(ctx context.Context, predicateTy
return aManifests, nil
}
func (r *ReferrersResolver) Attestations(ctx context.Context, predicateType string) ([]*att.Envelope, error) {
func (r *ReferrersResolver) Attestations(ctx context.Context, predicateType string) ([]*EnvelopeReference, error) {
manifests, err := r.resolveAttestations(ctx, predicateType)
if err != nil {
return nil, fmt.Errorf("failed to resolve attestations: %w", err)
}
var envs []*att.Envelope
var envs []*EnvelopeReference
for _, attest := range manifests {
es, err := ExtractEnvelopes(attest, predicateType)
if err != nil {

View File

@@ -1,3 +1,19 @@
/*
Copyright Docker attest 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.
*/
package attestation_test
import (
@@ -7,13 +23,12 @@ import (
"path/filepath"
"testing"
"github.com/docker/attest"
"github.com/docker/attest/attestation"
"github.com/docker/attest/internal/test"
"github.com/docker/attest/pkg/attest"
"github.com/docker/attest/pkg/attestation"
"github.com/docker/attest/pkg/config"
"github.com/docker/attest/pkg/mirror"
"github.com/docker/attest/pkg/oci"
"github.com/docker/attest/pkg/policy"
"github.com/docker/attest/mapping"
"github.com/docker/attest/oci"
"github.com/docker/attest/policy"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/registry"
"github.com/google/go-containerregistry/pkg/v1/remote"
@@ -22,19 +37,17 @@ import (
)
var (
UnsignedTestImage = filepath.Join("..", "..", "test", "testdata", "unsigned-test-image")
NoProvenanceImage = filepath.Join("..", "..", "test", "testdata", "no-provenance-image")
PassPolicyDir = filepath.Join("..", "..", "test", "testdata", "local-policy-pass")
LocalPolicy = filepath.Join("..", "..", "test", "testdata", "local-policy")
LocalPolicyAttached = filepath.Join("..", "..", "test", "testdata", "local-policy-attached")
PassNoTLPolicyDir = filepath.Join("..", "..", "test", "testdata", "local-policy-no-tl")
FailPolicyDir = filepath.Join("..", "..", "test", "testdata", "local-policy-fail")
NoProvenanceImage = filepath.Join("..", "test", "testdata", "no-provenance-image")
PassPolicyDir = filepath.Join("..", "test", "testdata", "local-policy-pass")
LocalPolicy = filepath.Join("..", "test", "testdata", "local-policy")
LocalPolicyAttached = filepath.Join("..", "test", "testdata", "local-policy-attached")
PassNoTLPolicyDir = filepath.Join("..", "test", "testdata", "local-policy-no-tl")
FailPolicyDir = filepath.Join("..", "test", "testdata", "local-policy-fail")
TestTempDir = "attest-sign-test"
)
func TestAttestationReferenceTypes(t *testing.T) {
ctx, signer := test.Setup(t)
ctx = policy.WithPolicyEvaluator(ctx, policy.NewRegoEvaluator(true))
platforms := []string{"linux/amd64", "linux/arm64"}
for _, tc := range []struct {
name string
@@ -42,42 +55,43 @@ func TestAttestationReferenceTypes(t *testing.T) {
referrersServer *httptest.Server
useDigest bool
referrersRepo string
attestationSource config.AttestationStyle
attestationSource mapping.AttestationStyle
expectFailure bool
}{
{
name: "referrers support, defaults",
server: httptest.NewServer(registry.New(registry.WithReferrersSupport(true))),
server: test.NewLocalRegistry(ctx, registry.WithReferrersSupport(true)),
},
{
name: "use digest",
server: httptest.NewServer(registry.New(registry.WithReferrersSupport(true))),
server: test.NewLocalRegistry(ctx, registry.WithReferrersSupport(true)),
useDigest: true,
},
{
name: "attached attestations, referrers repo (mismatched args)",
server: httptest.NewServer(registry.New(registry.WithReferrersSupport(true))),
expectFailure: true, //mismatched args
attestationSource: config.AttestationStyleAttached,
server: test.NewLocalRegistry(ctx, registry.WithReferrersSupport(true)),
expectFailure: true, // mismatched args
attestationSource: mapping.AttestationStyleAttached,
referrersRepo: "referrers",
},
{
name: "referrers attestations, referrers repo (no policy)",
server: httptest.NewServer(registry.New(registry.WithReferrersSupport(true))),
server: test.NewLocalRegistry(ctx, registry.WithReferrersSupport(true)),
expectFailure: true, // no policy
attestationSource: config.AttestationStyleReferrers,
attestationSource: mapping.AttestationStyleReferrers,
referrersRepo: "referrers",
},
{
name: "referrers attestations",
server: httptest.NewServer(registry.New(registry.WithReferrersSupport(true))),
attestationSource: config.AttestationStyleReferrers,
server: test.NewLocalRegistry(ctx, registry.WithReferrersSupport(true)),
attestationSource: mapping.AttestationStyleReferrers,
},
{
name: "referrers attestations, no referrers support on server",
server: httptest.NewServer(registry.New(registry.WithReferrersSupport(false))),
attestationSource: config.AttestationStyleReferrers,
referrersServer: httptest.NewServer(registry.New(registry.WithReferrersSupport(true))),
name: "referrers attestations, no referrers support on server",
server: test.NewLocalRegistry(ctx, registry.WithReferrersSupport(false)),
attestationSource: mapping.AttestationStyleReferrers,
referrersServer: test.NewLocalRegistry(ctx, registry.WithReferrersSupport(true)),
},
} {
t.Run(tc.name, func(t *testing.T) {
@@ -90,10 +104,8 @@ func TestAttestationReferenceTypes(t *testing.T) {
u, err := url.Parse(s.URL)
require.NoError(t, err)
opts := &attestation.SigningOptions{
SkipTL: true,
}
attIdx, err := oci.IndexFromPath(UnsignedTestImage)
opts := &attestation.SigningOptions{}
attIdx, err := oci.IndexFromPath(test.UnsignedTestIndex(".."))
require.NoError(t, err)
indexName := fmt.Sprintf("%s/repo:root", u.Host)
@@ -112,14 +124,16 @@ func TestAttestationReferenceTypes(t *testing.T) {
// push subject image so that it can be resolved
require.NoError(t, err)
err = mirror.PushIndexToRegistry(attIdx.Index, indexName)
err = oci.PushIndexToRegistry(ctx, attIdx.Index, indexName)
require.NoError(t, err)
// upload referrers
output, err := oci.ParseImageSpec(outputRepo)
require.NoError(t, err)
for _, attIdx := range signedManifests {
err = mirror.SaveReferrers(attIdx, []*oci.ImageSpec{output})
images, err := attIdx.BuildReferringArtifacts()
require.NoError(t, err)
err = oci.SaveImagesNoTag(ctx, images, []*oci.ImageSpec{output})
require.NoError(t, err)
}
@@ -137,8 +151,9 @@ func TestAttestationReferenceTypes(t *testing.T) {
ref = fmt.Sprintf("%s/repo@%s", u.Host, idxDigest.String())
}
policyOpts := &policy.PolicyOptions{
policyOpts := &policy.Options{
LocalPolicyDir: LocalPolicy,
DisableTUF: true,
}
if tc.referrersRepo != "" {
@@ -190,33 +205,31 @@ func TestReferencesInDifferentRepo(t *testing.T) {
}{
{
name: "referrers support",
server: httptest.NewServer(registry.New(registry.WithReferrersSupport(true))),
refServer: httptest.NewServer(registry.New(registry.WithReferrersSupport(true))),
server: test.NewLocalRegistry(ctx, registry.WithReferrersSupport(true)),
refServer: test.NewLocalRegistry(ctx, registry.WithReferrersSupport(true)),
},
{
name: "no referrers support",
server: httptest.NewServer(registry.New()),
refServer: httptest.NewServer(registry.New(registry.WithReferrersSupport(true))),
server: test.NewLocalRegistry(ctx, registry.WithReferrersSupport(false)),
refServer: test.NewLocalRegistry(ctx, registry.WithReferrersSupport(true)),
},
} {
server := tc.server
defer server.Close()
serverUrl, err := url.Parse(server.URL)
serverURL, err := url.Parse(server.URL)
require.NoError(t, err)
refServer := tc.refServer
defer refServer.Close()
refServerUrl, err := url.Parse(refServer.URL)
refServerURL, err := url.Parse(refServer.URL)
require.NoError(t, err)
opts := &attestation.SigningOptions{
SkipTL: true,
}
attIdx, err := oci.IndexFromPath(UnsignedTestImage)
opts := &attestation.SigningOptions{}
attIdx, err := oci.IndexFromPath(test.UnsignedTestIndex(".."))
require.NoError(t, err)
indexName := fmt.Sprintf("%s/%s:latest", serverUrl.Host, repoName)
err = mirror.PushIndexToRegistry(attIdx.Index, indexName)
indexName := fmt.Sprintf("%s/%s:latest", serverURL.Host, repoName)
err = oci.PushIndexToRegistry(ctx, attIdx.Index, indexName)
require.NoError(t, err)
signedManifests, err := attest.SignStatements(ctx, attIdx.Index, signer, opts)
@@ -225,24 +238,22 @@ func TestReferencesInDifferentRepo(t *testing.T) {
// push signed attestation image to the ref server
for _, signedManifest := range signedManifests {
// push references using subject-digest.att convention
image, err := signedManifest.BuildAttestationImage()
image, err := signedManifest.BuildImage()
require.NoError(t, err)
err = mirror.PushImageToRegistry(image, fmt.Sprintf("%s/%s:tag-does-not-matter", refServerUrl.Host, repoName))
err = oci.PushImageToRegistry(ctx, image, fmt.Sprintf("%s/%s:tag-does-not-matter", refServerURL.Host, repoName))
require.NoError(t, err)
refServer := tc.refServer
defer refServer.Close()
refServerUrl, err := url.Parse(refServer.URL)
refServerURL, err := url.Parse(refServer.URL)
require.NoError(t, err)
opts := &attestation.SigningOptions{
SkipTL: true,
}
attIdx, err := oci.IndexFromPath(UnsignedTestImage)
opts := &attestation.SigningOptions{}
attIdx, err := oci.IndexFromPath(test.UnsignedTestIndex(".."))
require.NoError(t, err)
indexName := fmt.Sprintf("%s/%s:latest", serverUrl.Host, repoName)
err = mirror.PushIndexToRegistry(attIdx.Index, indexName)
indexName := fmt.Sprintf("%s/%s:latest", serverURL.Host, repoName)
err = oci.PushIndexToRegistry(ctx, attIdx.Index, indexName)
require.NoError(t, err)
signedManifests, err := attest.SignStatements(ctx, attIdx.Index, signer, opts)
@@ -254,21 +265,22 @@ func TestReferencesInDifferentRepo(t *testing.T) {
imgs, err := mf.BuildReferringArtifacts()
require.NoError(t, err)
for _, img := range imgs {
err = mirror.PushImageToRegistry(img, fmt.Sprintf("%s/%s:tag-does-not-matter", refServerUrl.Host, repoName))
err = oci.PushImageToRegistry(ctx, img, fmt.Sprintf("%s/%s:tag-does-not-matter", refServerURL.Host, repoName))
require.NoError(t, err)
}
}
mfs2, err := attIdx.Index.IndexManifest()
require.NoError(t, err)
for _, mf := range mfs2.Manifests {
//skip signed/unsigned attestations
// skip signed/unsigned attestations
if mf.Annotations[attestation.DockerReferenceType] == attestation.AttestationManifestType {
continue
}
// can evaluate policy using referrers in a different repo
referencedImage := fmt.Sprintf("%s@%s", indexName, mf.Digest.String())
policyOpts := &policy.PolicyOptions{
policyOpts := &policy.Options{
LocalPolicyDir: PassPolicyDir,
DisableTUF: true,
}
src, err := oci.ParseImageSpec(referencedImage)
require.NoError(t, err)
@@ -282,22 +294,19 @@ func TestReferencesInDifferentRepo(t *testing.T) {
func TestCorrectArtifactTypeInTagFallback(t *testing.T) {
ctx, signer := test.Setup(t)
server := httptest.NewServer(registry.New())
defer server.Close()
serverUrl, err := url.Parse(server.URL)
regServer := test.NewLocalRegistry(ctx, registry.WithReferrersSupport(false))
defer regServer.Close()
serverURL, err := url.Parse(regServer.URL)
require.NoError(t, err)
repoName := "repo"
opts := &attestation.SigningOptions{
SkipTL: true,
}
attIdx, err := oci.IndexFromPath(UnsignedTestImage)
opts := &attestation.SigningOptions{}
attIdx, err := oci.IndexFromPath(test.UnsignedTestIndex(".."))
require.NoError(t, err)
indexName := fmt.Sprintf("%s/%s:latest", serverUrl.Host, repoName)
err = mirror.PushIndexToRegistry(attIdx.Index, indexName)
indexName := fmt.Sprintf("%s/%s:latest", serverURL.Host, repoName)
err = oci.PushIndexToRegistry(ctx, attIdx.Index, indexName)
require.NoError(t, err)
signedManifests, err := attest.SignStatements(ctx, attIdx.Index, signer, opts)
@@ -308,14 +317,14 @@ func TestCorrectArtifactTypeInTagFallback(t *testing.T) {
imgs, err := mf.BuildReferringArtifacts()
require.NoError(t, err)
for _, img := range imgs {
err = mirror.PushImageToRegistry(img, fmt.Sprintf("%s/%s:tag-does-not-matter", serverUrl.Host, repoName))
err = oci.PushImageToRegistry(ctx, img, fmt.Sprintf("%s/%s:tag-does-not-matter", serverURL.Host, repoName))
require.NoError(t, err)
mf, err := img.Manifest()
require.NoError(t, err)
subject := mf.Subject
subjectRef, err := name.ParseReference(fmt.Sprintf("%s/%s:sha256-%s", serverUrl.Host, repoName, subject.Digest.Hex))
subjectRef, err := name.ParseReference(fmt.Sprintf("%s/%s:sha256-%s", serverURL.Host, repoName, subject.Digest.Hex))
require.NoError(t, err)
idx, err := remote.Index(subjectRef)
idx, err := remote.Index(subjectRef, oci.WithOptions(ctx, nil)...)
require.NoError(t, err)
imf, err := idx.IndexManifest()
require.NoError(t, err)

120
attestation/registry.go Normal file
View File

@@ -0,0 +1,120 @@
/*
Copyright Docker attest 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.
*/
package attestation
import (
"context"
"fmt"
"github.com/docker/attest/oci"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/remote"
)
// ensure RegistryResolver implements Resolver.
var _ Resolver = &RegistryResolver{}
type RegistryResolver struct {
*oci.RegistryImageDetailsResolver
*Manifest
}
func NewRegistryResolver(src *oci.RegistryImageDetailsResolver) (*RegistryResolver, error) {
return &RegistryResolver{
RegistryImageDetailsResolver: src,
}, nil
}
func (r *RegistryResolver) Attestations(ctx context.Context, predicateType string) ([]*EnvelopeReference, error) {
if r.Manifest == nil {
attest, err := FetchManifest(ctx, r.Identifier, r.ImageSpec.Platform)
if err != nil {
return nil, err
}
r.Manifest = attest
}
return ExtractEnvelopes(r.Manifest, predicateType)
}
func attestationDigestForImage(ix *v1.IndexManifest, imageDigest string, attestType string) (string, error) {
for i := range ix.Manifests {
m := &ix.Manifests[i]
if v, ok := m.Annotations[DockerReferenceType]; ok && v == attestType {
if d, ok := m.Annotations[DockerReferenceDigest]; ok && d == imageDigest {
return m.Digest.String(), nil
}
}
}
return "", fmt.Errorf("no attestation found for image %s", imageDigest)
}
func FetchManifest(ctx context.Context, image string, platform *v1.Platform) (*Manifest, error) {
// we want to get to the image index, so ignoring platform for now
options := oci.WithOptions(ctx, nil)
ref, err := name.ParseReference(image)
if err != nil {
return nil, fmt.Errorf("failed to parse reference: %w", err)
}
index, err := remote.Index(ref, options...)
if err != nil {
return nil, fmt.Errorf("failed to get index: %w", err)
}
indexManifest, err := index.IndexManifest()
if err != nil {
return nil, fmt.Errorf("failed to get index manifest: %w", err)
}
subjectDescriptor, err := oci.ImageDescriptor(indexManifest, platform)
if err != nil {
return nil, fmt.Errorf("failed to obtain image for platform: %w", err)
}
digest := subjectDescriptor.Digest.String()
ref, err = name.ParseReference(fmt.Sprintf("%s@%s", ref.Context().Name(), digest))
if err != nil {
return nil, fmt.Errorf("failed to parse attestation reference: %w", err)
}
attestationDigest, err := attestationDigestForImage(indexManifest, digest, "attestation-manifest")
if err != nil {
return nil, fmt.Errorf("failed to obtain attestation for image: %w", err)
}
ref, err = name.ParseReference(fmt.Sprintf("%s@%s", ref.Context().Name(), attestationDigest))
if err != nil {
return nil, fmt.Errorf("failed to parse attestation reference: %w", err)
}
remoteDescriptor, err := remote.Get(ref, options...)
if err != nil {
return nil, fmt.Errorf("failed to get attestation: %w", err)
}
attestationImage, err := remoteDescriptor.Image()
if err != nil {
return nil, fmt.Errorf("failed to get attestation image: %w", err)
}
layers, err := layersFromImage(attestationImage)
if err != nil {
return nil, fmt.Errorf("failed to get attestations from image: %w", err)
}
attest := &Manifest{
OriginalLayers: layers,
OriginalDescriptor: &remoteDescriptor.Descriptor,
SubjectName: image,
SubjectDescriptor: subjectDescriptor,
}
return attest, nil
}

View File

@@ -0,0 +1,75 @@
/*
Copyright Docker attest 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.
*/
package attestation_test
import (
"fmt"
"net/url"
"strings"
"testing"
"github.com/docker/attest"
"github.com/docker/attest/attestation"
"github.com/docker/attest/internal/test"
"github.com/docker/attest/oci"
"github.com/docker/attest/policy"
"github.com/google/go-containerregistry/pkg/registry"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestRegistry(t *testing.T) {
ctx, signer := test.Setup(t)
regServer := test.NewLocalRegistry(ctx, registry.WithReferrersSupport(false))
defer regServer.Close()
u, err := url.Parse(regServer.URL)
require.NoError(t, err)
opts := &attestation.SigningOptions{}
attIdx, err := oci.IndexFromPath(test.UnsignedTestIndex(".."))
require.NoError(t, err)
signedManifests, err := attest.SignStatements(ctx, attIdx.Index, signer, opts)
require.NoError(t, err)
signedIndex := attIdx.Index
signedIndex, err = attestation.UpdateIndexImages(signedIndex, signedManifests)
require.NoError(t, err)
indexName := fmt.Sprintf("%s/repo:root", u.Host)
require.NoError(t, err)
err = oci.PushIndexToRegistry(ctx, signedIndex, indexName)
require.NoError(t, err)
spec, err := oci.ParseImageSpec(indexName)
require.NoError(t, err)
resolver, err := policy.CreateImageDetailsResolver(spec)
require.NoError(t, err)
desc, err := resolver.ImageDescriptor(ctx)
require.NoError(t, err)
digest := desc.Digest.String()
assert.True(t, strings.Contains(digest, "sha256:"))
// resolver also works with platform specific digest
spec, err = oci.ParseImageSpec(fmt.Sprintf("%s@%s", indexName, digest))
require.NoError(t, err)
resolver, err = policy.CreateImageDetailsResolver(spec)
require.NoError(t, err)
desc, err = resolver.ImageDescriptor(ctx)
require.NoError(t, err)
assert.Equal(t, desc.Digest.String(), digest)
}

28
attestation/resolver.go Normal file
View File

@@ -0,0 +1,28 @@
/*
Copyright Docker attest 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.
*/
package attestation
import (
"context"
"github.com/docker/attest/oci"
)
type Resolver interface {
oci.ImageDetailsResolver
Attestations(ctx context.Context, mediaType string) ([]*EnvelopeReference, error)
}

View File

@@ -1,3 +1,19 @@
/*
Copyright Docker attest 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.
*/
package attestation
import (
@@ -5,12 +21,12 @@ import (
"fmt"
"github.com/docker/attest/internal/util"
"github.com/docker/attest/pkg/tlog"
"github.com/docker/attest/tlog"
intoto "github.com/in-toto/in-toto-golang/in_toto"
"github.com/secure-systems-lab/go-securesystemslib/dsse"
)
// SignDSSE signs a payload with a given signer and uploads the signature to the transparency log
// SignDSSE signs a payload with a given signer and uploads the signature to the transparency log.
func SignDSSE(ctx context.Context, payload []byte, signer dsse.SignerVerifier, opts *SigningOptions) (*Envelope, error) {
payloadType := intoto.PayloadType
env := new(Envelope)
@@ -28,50 +44,44 @@ func SignDSSE(ctx context.Context, payload []byte, signer dsse.SignerVerifier, o
}
// get Key ID from signer
keyId, err := signer.KeyID()
keyID, err := signer.KeyID()
if err != nil {
return nil, fmt.Errorf("error getting public key ID: %w", err)
}
dsseSig := Signature{
KeyID: keyId,
dsseSig := &Signature{
KeyID: keyID,
Sig: base64Encoding.EncodeToString(sig),
}
if !opts.SkipTL {
ext, err := logSignature(ctx, tlog.GetTL(ctx), &sig, &encPayload, signer)
if opts.TransparencyLog != nil {
ext, err := logSignature(ctx, opts.TransparencyLog, sig, encPayload, signer)
if err != nil {
return nil, fmt.Errorf("failed to log to rekor: %w", err)
return nil, fmt.Errorf("failed to log signature: %w", err)
}
dsseSig.Extension = *ext
dsseSig.Extension = ext
}
// add signature to dsse envelope
env.Signatures = []Signature{dsseSig}
env.Signatures = []*Signature{dsseSig}
return env, nil
}
// returns a new envelope with the transparency log entry added to the signature extension
func logSignature(ctx context.Context, t tlog.TL, sig *[]byte, encPayload *[]byte, signer dsse.SignerVerifier) (*Extension, error) {
// returns a new envelope with the transparency log entry added to the signature extension.
func logSignature(ctx context.Context, t tlog.TransparencyLog, sig []byte, encPayload []byte, signer dsse.SignerVerifier) (*Extension, error) {
// get Key ID from signer
keyId, err := signer.KeyID()
keyID, err := signer.KeyID()
if err != nil {
return nil, fmt.Errorf("error getting public key ID: %w", err)
}
entry, err := t.UploadLogEntry(ctx, keyId, *encPayload, *sig, signer)
entry, err := t.UploadEntry(ctx, keyID, encPayload, sig, signer)
if err != nil {
return nil, fmt.Errorf("error uploading TL entry: %w", err)
}
entryObj, err := t.UnmarshalEntry(entry)
if err != nil {
return nil, fmt.Errorf("error unmarshaling tl entry: %w", err)
}
return &Extension{
Kind: DockerDsseExtKind,
Ext: DockerDsseExtension{
Tl: DockerTlExtension{
Kind: RekorTlExtKind,
Data: entryObj, // transparency log entry metadata
},
Kind: DockerDSSEExtKind,
Ext: &DockerDSSEExtension{
TL: entry,
},
}, nil
}

329
attestation/sign_test.go Normal file
View File

@@ -0,0 +1,329 @@
/*
Copyright Docker attest 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.
*/
package attestation_test
import (
"context"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"encoding/json"
"fmt"
"net/url"
"testing"
"time"
"github.com/docker/attest/attestation"
"github.com/docker/attest/internal/test"
"github.com/docker/attest/oci"
"github.com/docker/attest/signerverifier"
"github.com/docker/attest/tlog"
"github.com/google/go-containerregistry/pkg/registry"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/static"
"github.com/google/go-containerregistry/pkg/v1/types"
intoto "github.com/in-toto/in-toto-golang/in_toto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestSignVerifyAttestation(t *testing.T) {
ctx, signer := test.Setup(t)
stmt := &intoto.Statement{
StatementHeader: intoto.StatementHeader{
Type: intoto.StatementInTotoV01,
PredicateType: intoto.PredicateSPDX,
},
Predicate: "test",
}
payload, err := json.Marshal(stmt)
require.NoError(t, err)
tl := tlog.GetMockTL()
opts := &attestation.SigningOptions{
TransparencyLog: tl,
}
env, err := attestation.SignDSSE(ctx, payload, signer, opts)
require.NoError(t, err)
// marshal envelope to json to test for bugs when marshaling envelope data
serializedEnv, err := json.Marshal(env)
require.NoError(t, err)
deserializedEnv := new(attestation.Envelope)
err = json.Unmarshal(serializedEnv, deserializedEnv)
require.NoError(t, err)
// signer.Public() calls AWS API when using AWS signer, use attestation.GetPublicVerificationKey() to get key from TUF repo
// signer.Public() used here for test purposes
ecPub, ok := signer.Public().(*ecdsa.PublicKey)
assert.True(t, ok)
pem, err := signerverifier.ConvertToPEM(ecPub)
assert.NoError(t, err)
keyID, err := signerverifier.KeyID(ecPub)
assert.NoError(t, err)
badKeyPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
require.NoError(t, err)
badKey := &badKeyPriv.PublicKey
badPEM, err := signerverifier.ConvertToPEM(badKey)
require.NoError(t, err)
testCases := []struct {
name string
keyID string
pem []byte
distrust bool
from time.Time
to *time.Time
status string
expectedError string
}{
{
name: "all OK",
keyID: keyID,
pem: pem,
distrust: false,
from: time.Time{},
to: nil,
status: "active",
expectedError: "",
},
{
name: "key not found",
keyID: "someotherkey",
pem: pem,
distrust: false,
from: time.Time{},
to: nil,
status: "active",
expectedError: fmt.Sprintf("key not found: %s", keyID),
},
{
name: "key distrusted",
keyID: keyID,
pem: pem,
distrust: true,
from: time.Time{},
to: nil,
status: "active",
expectedError: "distrusted",
},
{
name: "key not yet valid",
keyID: keyID,
pem: pem,
distrust: false,
from: time.Now().Add(time.Hour),
to: nil,
status: "active",
expectedError: "not yet valid",
},
{
name: "key already revoked",
keyID: keyID,
pem: pem,
distrust: false,
from: time.Time{},
to: new(time.Time),
status: "revoked",
expectedError: "already revoked",
},
{
name: "bad key",
keyID: keyID,
pem: badPEM,
distrust: false,
from: time.Time{},
to: nil,
status: "active",
expectedError: "signature is not valid",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
keyMeta := &attestation.KeyMetadata{
ID: tc.keyID,
PEM: string(tc.pem),
Distrust: tc.distrust,
From: tc.from,
To: tc.to,
Status: tc.status,
}
opts := &attestation.VerifyOptions{
Keys: attestation.Keys{keyMeta},
}
getTL := func(_ context.Context, opts *attestation.VerifyOptions) (tlog.TransparencyLog, error) {
if opts.SkipTL {
return nil, nil
}
return tl, nil
}
verifier, err := attestation.NewVerfier(attestation.WithLogVerifierFactory(getTL))
require.NoError(t, err)
_, err = attestation.VerifyDSSE(ctx, verifier, deserializedEnv, opts)
if tc.expectedError != "" {
require.Error(t, err)
assert.Contains(t, err.Error(), tc.expectedError)
} else {
assert.NoError(t, err)
}
})
}
}
func TestAddSignedLayerAnnotations(t *testing.T) {
ctx, signer := test.Setup(t)
testCases := []struct {
name string
replace bool
}{
{"replaced", true},
{"not replaced", false},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
data := []byte("signed")
testLayer := static.NewLayer(data, types.MediaType(intoto.PayloadType))
mediaType := types.OCIManifestSchema1
opts := &attestation.SigningOptions{}
originalLayer := &attestation.Layer{
Layer: testLayer,
Statement: &intoto.Statement{
StatementHeader: intoto.StatementHeader{
PredicateType: attestation.VSAPredicateType,
},
},
Annotations: map[string]string{"test": "test"},
}
manifest := &attestation.Manifest{
OriginalDescriptor: &v1.Descriptor{
MediaType: mediaType,
},
OriginalLayers: []*attestation.Layer{
originalLayer,
},
SubjectDescriptor: &v1.Descriptor{},
}
err := manifest.Add(ctx, signer, originalLayer.Statement, opts)
require.NoError(t, err)
newImg, err := manifest.BuildImage(attestation.WithReplacedLayers(tc.replace))
require.NoError(t, err)
mf, _ := newImg.RawManifest()
type Annotations struct {
Annotations map[string]string `json:"annotations"`
}
type Layers struct {
Layers []Annotations `json:"layers"`
}
l := &Layers{}
err = json.Unmarshal(mf, l)
require.NoError(t, err)
_, ok := l.Layers[0].Annotations["test"]
assert.Truef(t, ok, "missing annotations")
})
}
}
func TestSimpleStatementSigning(t *testing.T) {
ctx, signer := test.Setup(t)
empty := types.MediaType("application/vnd.oci.empty.v1+json")
testCases := []struct {
name string
replace bool
}{
{"replaced", true},
{"not replaced", false},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
opts := &attestation.SigningOptions{}
statement := &intoto.Statement{
StatementHeader: intoto.StatementHeader{
PredicateType: attestation.VSAPredicateType,
},
}
statement2 := &intoto.Statement{
StatementHeader: intoto.StatementHeader{
PredicateType: attestation.VSAPredicateType,
},
}
digest, err := v1.NewHash(test.UnsignedLinuxAMD64ImageDigest)
require.NoError(t, err)
subject := &v1.Descriptor{
MediaType: "application/vnd.oci.image.manifest.v1+json",
Digest: digest,
}
manifest, err := attestation.NewManifest(subject)
require.NoError(t, err)
err = manifest.Add(ctx, signer, statement, opts)
require.NoError(t, err)
err = manifest.Add(ctx, signer, statement2, opts)
require.NoError(t, err)
// fake that the manfifest was loaded from a real image
manifest.OriginalLayers = manifest.SignedLayers
envelopes, err := attestation.ExtractEnvelopes(manifest, attestation.VSAPredicateType)
require.NoError(t, err)
assert.Len(t, envelopes, 2)
newImg, err := manifest.BuildImage(attestation.WithReplacedLayers(tc.replace))
require.NoError(t, err)
layers, err := newImg.Layers()
require.NoError(t, err)
if tc.replace {
assert.Len(t, layers, 2)
} else {
assert.Len(t, layers, 4)
}
newImgs, err := manifest.BuildReferringArtifacts()
require.NoError(t, err)
assert.Len(t, newImgs, 2)
for _, img := range newImgs {
mf, err := img.Manifest()
require.NoError(t, err)
assert.Contains(t, mf.ArtifactType, "application/vnd.in-toto")
assert.Contains(t, mf.ArtifactType, "+dsse")
assert.Equal(t, subject.MediaType, mf.MediaType)
assert.Equal(t, empty, mf.Config.MediaType)
assert.Equal(t, int64(2), mf.Config.Size)
assert.Equal(t, "{}", string(mf.Config.Data))
layers, err := img.Layers()
require.NoError(t, err)
assert.Len(t, layers, 1)
}
regServer := test.NewLocalRegistry(ctx, registry.WithReferrersSupport(true))
defer regServer.Close()
u, err := url.Parse(regServer.URL)
require.NoError(t, err)
indexName := fmt.Sprintf("%s/repo:root", u.Host)
output, err := oci.ParseImageSpecs(indexName)
require.NoError(t, err)
artifacts, err := manifest.BuildReferringArtifacts()
require.NoError(t, err)
err = oci.SaveImagesNoTag(ctx, artifacts, output)
require.NoError(t, err)
})
}
}

163
attestation/types.go Normal file
View File

@@ -0,0 +1,163 @@
/*
Copyright Docker attest 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.
*/
package attestation
import (
"crypto"
"encoding/base64"
"fmt"
"time"
"github.com/docker/attest/tlog"
v1 "github.com/google/go-containerregistry/pkg/v1"
intoto "github.com/in-toto/in-toto-golang/in_toto"
v02 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2"
slsav1 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v1"
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
)
const (
DockerReferenceType = "vnd.docker.reference.type"
AttestationManifestType = "attestation-manifest"
InTotoPredicateType = "in-toto.io/predicate-type"
DockerReferenceDigest = "vnd.docker.reference.digest"
DockerDSSEExtKind = "application/vnd.docker.attestation-verification.v1+json"
OCIDescriptorDSSEMediaType = ociv1.MediaTypeDescriptor + "+dsse"
InTotoReferenceLifecycleStage = "vnd.docker.lifecycle-stage"
LifecycleStageExperimental = "experimental"
)
var base64Encoding = base64.StdEncoding.Strict()
type Layer struct {
Statement *intoto.Statement
Layer v1.Layer
Annotations map[string]string
}
type Manifest struct {
OriginalDescriptor *v1.Descriptor
OriginalLayers []*Layer
// accumulated during signing
SignedLayers []*Layer
// details of subject image
SubjectName string
SubjectDescriptor *v1.Descriptor
}
type ManifestImageOptions struct {
// how to output the image
skipSubject bool
replaceLayers bool
laxReferrers bool
}
// the following types are needed until https://github.com/secure-systems-lab/dsse/pull/61 is merged.
type Envelope struct {
PayloadType string `json:"payloadType"`
Payload string `json:"payload"`
Signatures []*Signature `json:"signatures"`
}
type Signature struct {
KeyID string `json:"keyid"`
Sig string `json:"sig"`
Extension *Extension `json:"extension,omitempty"`
}
type Extension struct {
Kind string `json:"kind"`
Ext *DockerDSSEExtension `json:"ext"`
}
type EnvelopeReference struct {
*Envelope
ResourceDescriptor *ResourceDescriptor `json:"resourceDescriptor"`
}
type ResourceDescriptor struct {
MediaType string `json:"mediaType"`
Digest map[string]string `json:"digest"`
URI string `json:"uri,omitempty"`
}
type AnnotatedStatement struct {
OCIDescriptor *v1.Descriptor
InTotoStatement *intoto.Statement
Annotations map[string]string
}
type DockerDSSEExtension struct {
TL *tlog.DockerTLExtension `json:"tl"`
}
type TransparencyLogKind string
const (
RekorTransparencyLogKind = "rekor"
)
type VerifyOptions struct {
Keys []*KeyMetadata `json:"keys"`
SkipTL bool `json:"skip_tl"`
TransparencyLog TransparencyLogKind `json:"tl"`
}
type KeyMetadata struct {
ID string `json:"id"`
PEM string `json:"key"`
From time.Time `json:"from"`
To *time.Time `json:"to"`
Status string `json:"status"`
SigningFormat string `json:"signing-format"`
Distrust bool `json:"distrust,omitempty"`
publicKey crypto.PublicKey
}
type (
Keys []*KeyMetadata
KeysMap map[string]*KeyMetadata
)
type SigningOptions struct {
// set this in order to log to a transparency log
TransparencyLog tlog.TransparencyLog
}
type Options struct {
NoReferrers bool
Attach bool
ReferrersRepo string
}
func DSSEMediaType(predicateType string) (string, error) {
var predicateName string
switch predicateType {
case slsav1.PredicateSLSAProvenance:
predicateName = "provenance"
case v02.PredicateSLSAProvenance:
predicateName = "provenance"
case intoto.PredicateSPDX:
predicateName = "spdx"
case VSAPredicateType:
predicateName = "verification_summary"
default:
return "", fmt.Errorf("unknown predicate type %q", predicateType)
}
return fmt.Sprintf("application/vnd.in-toto.%s+dsse", predicateName), nil
}

60
attestation/types_test.go Normal file
View File

@@ -0,0 +1,60 @@
/*
Copyright Docker attest 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.
*/
package attestation
import (
"fmt"
"testing"
intoto "github.com/in-toto/in-toto-golang/in_toto"
v02 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2"
slsav1 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestDSSEMediaType(t *testing.T) {
testcases := []struct {
name string
expected string
}{
{
name: slsav1.PredicateSLSAProvenance,
expected: "provenance",
},
{
name: v02.PredicateSLSAProvenance,
expected: "provenance",
},
{
name: intoto.PredicateSPDX,
expected: "spdx",
},
{
name: VSAPredicateType,
expected: "verification_summary",
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
mt, err := DSSEMediaType(tc.name)
require.NoError(t, err)
assert.Equal(t, fmt.Sprintf("application/vnd.in-toto.%s+dsse", tc.expected), mt)
})
}
}

159
attestation/verifier.go Normal file
View File

@@ -0,0 +1,159 @@
/*
Copyright Docker attest 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.
*/
package attestation
import (
"context"
"crypto"
"crypto/x509"
"fmt"
"github.com/docker/attest/signerverifier"
"github.com/docker/attest/tlog"
"github.com/docker/attest/tuf"
"github.com/secure-systems-lab/go-securesystemslib/dsse"
)
func WithTUFDownloader(tufDownloader tuf.Downloader) func(*verifier) {
return func(r *verifier) {
r.tufDownloader = tufDownloader
}
}
type SignatureVerifierFactory func(ctx context.Context, publicKey crypto.PublicKey, opts *VerifyOptions) (dsse.Verifier, error)
func WithSignatureVerifierFactory(factory SignatureVerifierFactory) func(*verifier) {
return func(r *verifier) {
r.signatureVerifierFactory = factory
}
}
func WithLogVerifierFactory(factory LogVerifierFactory) func(*verifier) {
return func(r *verifier) {
r.logVerifierFactory = factory
}
}
type LogVerifierFactory func(ctx context.Context, opts *VerifyOptions) (tlog.TransparencyLog, error)
func NewVerfier(options ...func(*verifier)) (Verifier, error) {
verifier := &verifier{}
for _, opt := range options {
opt(verifier)
}
return verifier, nil
}
type Verifier interface {
GetSignatureVerifier(ctx context.Context, publicKey crypto.PublicKey, opts *VerifyOptions) (dsse.Verifier, error)
GetLogVerifier(ctx context.Context, opts *VerifyOptions) (tlog.TransparencyLog, error)
VerifySignature(ctx context.Context, publicKey crypto.PublicKey, data []byte, signature []byte, opts *VerifyOptions) error
VerifyLog(ctx context.Context, keyMeta *KeyMetadata, data []byte, sig *Signature, opts *VerifyOptions) error
}
// ensure it has all the necessary methods.
var _ Verifier = (*verifier)(nil)
type verifier struct {
tufDownloader tuf.Downloader
signatureVerifierFactory SignatureVerifierFactory
logVerifierFactory LogVerifierFactory
}
// GetLogVerifier implements Verifier.
func (v *verifier) GetLogVerifier(ctx context.Context, opts *VerifyOptions) (tlog.TransparencyLog, error) {
if v.logVerifierFactory != nil {
return v.logVerifierFactory(ctx, opts)
}
if opts.SkipTL {
return nil, nil
}
// TODO support other transparency logs
var transparencyLog tlog.TransparencyLog
switch opts.TransparencyLog {
case "", RekorTransparencyLogKind:
var err error
transparencyLog, err = tlog.NewRekorLog(tlog.WithTUFDownloader(v.tufDownloader))
if err != nil {
return nil, fmt.Errorf("error failed to create rekor verifier: %w", err)
}
default:
return nil, fmt.Errorf("unsupported transparency log: %s", opts.TransparencyLog)
}
return transparencyLog, nil
}
// GetSignatureVerifier implements Verifier.
func (v *verifier) GetSignatureVerifier(ctx context.Context, publicKey crypto.PublicKey, opts *VerifyOptions) (dsse.Verifier, error) {
if v.signatureVerifierFactory != nil {
return v.signatureVerifierFactory(ctx, publicKey, opts)
}
// TODO: use details from opts to decide which algorithm to use here
ecdsaVerifier, err := signerverifier.NewECDSAVerifier(publicKey)
if err != nil {
return nil, fmt.Errorf("error failed to create ecdsa verifier: %w", err)
}
return ecdsaVerifier, nil
}
func (v *verifier) VerifySignature(ctx context.Context, publicKey crypto.PublicKey, data []byte, signature []byte, opts *VerifyOptions) error {
sigVerifier, err := v.GetSignatureVerifier(ctx, publicKey, opts)
if err != nil {
return fmt.Errorf("error failed to get verifier: %w", err)
}
return sigVerifier.Verify(ctx, data, signature)
}
func (v *verifier) VerifyLog(ctx context.Context, keyMeta *KeyMetadata, encPayload []byte, sig *Signature, opts *VerifyOptions) error {
if opts.SkipTL {
return nil
}
if sig.Extension == nil || sig.Extension.Kind == "" {
return fmt.Errorf("error missing signature extension")
}
if sig.Extension.Kind != DockerDSSEExtKind {
return fmt.Errorf("error unsupported signature extension kind: %s", sig.Extension.Kind)
}
transparencyLog, err := v.GetLogVerifier(ctx, opts)
if err != nil {
return fmt.Errorf("error failed to get transparency log verifier: %w", err)
}
if transparencyLog == nil {
return fmt.Errorf("error missing transparency log verifier")
}
// verify TL entry payload
publicKey, err := keyMeta.ParsedKey()
if err != nil {
return fmt.Errorf("error failed to parse public key: %w", err)
}
encodedPub, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return fmt.Errorf("error failed to marshal public key: %w", err)
}
integratedTime, err := transparencyLog.VerifyEntry(ctx, sig.Extension.Ext.TL, encPayload, encodedPub)
if err != nil {
return fmt.Errorf("TL entry failed verification: %w", err)
}
if integratedTime.Before(keyMeta.From) {
return fmt.Errorf("key %s was not yet valid at TL log time %s (key valid from %s)", keyMeta.ID, integratedTime, keyMeta.From)
}
if keyMeta.To != nil && !integratedTime.Before(*keyMeta.To) {
return fmt.Errorf("key %s was already %s at TL log time %s (key %s at %s)", keyMeta.ID, keyMeta.Status, integratedTime, keyMeta.Status, *keyMeta.To)
}
return nil
}

View File

@@ -0,0 +1,71 @@
/*
Copyright Docker attest 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.
*/
package attestation
import (
"context"
"reflect"
"testing"
"github.com/docker/attest/tlog"
"github.com/docker/attest/tuf"
"github.com/stretchr/testify/require"
)
func Test_verifier_GetLogVerifier(t *testing.T) {
type fields struct {
tufDownloader tuf.Downloader
signatureVerifierFactory SignatureVerifierFactory
logVerifierFactory LogVerifierFactory
}
type args struct {
ctx context.Context
opts *VerifyOptions
}
rekor, err := tlog.NewRekorLog()
require.NoError(t, err)
tests := []struct {
name string
fields fields
args args
want tlog.TransparencyLog
wantErr bool
}{
{name: "skip_tl true", fields: fields{}, args: args{ctx: context.Background(), opts: &VerifyOptions{SkipTL: true}}},
{name: "skip_tl false", fields: fields{}, args: args{ctx: context.Background(), opts: &VerifyOptions{SkipTL: false}}, want: rekor},
{name: "tl: rekor", fields: fields{logVerifierFactory: func(_ context.Context, _ *VerifyOptions) (tlog.TransparencyLog, error) {
return &tlog.Rekor{}, nil
}}, args: args{ctx: context.Background(), opts: &VerifyOptions{}}, want: &tlog.Rekor{}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
v := &verifier{
tufDownloader: tt.fields.tufDownloader,
signatureVerifierFactory: tt.fields.signatureVerifierFactory,
logVerifierFactory: tt.fields.logVerifierFactory,
}
got, err := v.GetLogVerifier(tt.args.ctx, tt.args.opts)
if (err != nil) != tt.wantErr {
t.Errorf("verifier.GetLogVerifier() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("verifier.GetLogVerifier() = %v, want %v", got, tt.want)
}
})
}
}

99
attestation/verify.go Normal file
View File

@@ -0,0 +1,99 @@
/*
Copyright Docker attest 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.
*/
package attestation
import (
"context"
"crypto"
"encoding/base64"
"fmt"
"github.com/docker/attest/signerverifier"
intoto "github.com/in-toto/in-toto-golang/in_toto"
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/secure-systems-lab/go-securesystemslib/dsse"
)
func VerifyDSSE(ctx context.Context, verifier Verifier, env *Envelope, opts *VerifyOptions) ([]byte, error) {
// enforce payload type
if !ValidPayloadType(env.PayloadType) {
return nil, fmt.Errorf("unsupported payload type %s", env.PayloadType)
}
if len(env.Signatures) == 0 {
return nil, fmt.Errorf("no signatures found")
}
keys := make(map[string]*KeyMetadata, len(opts.Keys))
for _, key := range opts.Keys {
keys[key.ID] = key
}
payload, err := base64Encoding.DecodeString(env.Payload)
if err != nil {
return nil, fmt.Errorf("error failed to decode payload: %w", err)
}
encPayload := dsse.PAE(env.PayloadType, payload)
// verify signatures and transparency log entry
for _, sig := range env.Signatures {
// resolve public key used to sign
keyMeta, ok := keys[sig.KeyID]
if !ok {
return nil, fmt.Errorf("error key not found: %s", sig.KeyID)
}
if keyMeta.Distrust {
return nil, fmt.Errorf("key %s is distrusted", keyMeta.ID)
}
publicKey, err := keyMeta.ParsedKey()
if err != nil {
return nil, fmt.Errorf("failed to parse public key: %w", err)
}
// decode signature
signature, err := base64.StdEncoding.Strict().DecodeString(sig.Sig)
if err != nil {
return nil, fmt.Errorf("error failed to decode signature: %w", err)
}
err = verifier.VerifySignature(ctx, publicKey, encPayload, signature, opts)
if err != nil {
return nil, fmt.Errorf("error failed to verify signature: %w", err)
}
if err := verifier.VerifyLog(ctx, keyMeta, encPayload, sig, opts); err != nil {
return nil, fmt.Errorf("error failed to verify transparency log entry: %w", err)
}
}
return payload, nil
}
func ValidPayloadType(payloadType string) bool {
return payloadType == intoto.PayloadType || payloadType == ociv1.MediaTypeDescriptor
}
func (km *KeyMetadata) ParsedKey() (crypto.PublicKey, error) {
if km.publicKey != nil {
return km.publicKey, nil
}
publicKey, err := signerverifier.ParsePublicKey([]byte(km.PEM))
if err != nil {
return nil, fmt.Errorf("failed to parse public key: %w", err)
}
km.publicKey = publicKey
return publicKey, nil
}

View File

@@ -1,11 +1,27 @@
/*
Copyright Docker attest 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.
*/
package attestation_test
import (
"encoding/base64"
"testing"
"github.com/docker/attest/attestation"
"github.com/docker/attest/internal/test"
"github.com/docker/attest/pkg/attestation"
intoto "github.com/in-toto/in-toto-golang/in_toto"
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/stretchr/testify/assert"
@@ -35,15 +51,14 @@ func TestVerifyUnsignedAttestation(t *testing.T) {
payload := []byte("payload")
env := &attestation.Envelope{
// no signatures
Signatures: []attestation.Signature{},
Signatures: []*attestation.Signature{},
Payload: base64.StdEncoding.EncodeToString(payload),
PayloadType: intoto.PayloadType,
}
opts := &attestation.VerifyOptions{
Keys: attestation.Keys{},
}
_, err := attestation.VerifyDSSE(ctx, env, opts)
_, err := attestation.VerifyDSSE(ctx, nil, env, opts)
assert.Error(t, err)
assert.Contains(t, err.Error(), "no signatures")
}

79
attestation/vsa.go Normal file
View File

@@ -0,0 +1,79 @@
/*
Copyright Docker attest 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.
*/
package attestation
import (
"fmt"
"github.com/docker/attest/version"
intoto "github.com/in-toto/in-toto-golang/in_toto"
"github.com/package-url/packageurl-go"
)
const (
VSAPredicateType = "https://slsa.dev/verification_summary/v1"
)
type VSAPredicate struct {
Verifier VSAVerifier `json:"verifier"`
TimeVerified string `json:"timeVerified"`
ResourceURI string `json:"resourceUri"`
Policy VSAPolicy `json:"policy"`
InputAttestations []ResourceDescriptor `json:"inputAttestations,omitempty"`
VerificationResult string `json:"verificationResult"`
VerifiedLevels []string `json:"verifiedLevels"`
}
type VSAVerifier struct {
ID string `json:"id"`
Version VerifierVersion `json:"version"`
}
type VerifierVersion map[string]string
type VSAPolicy struct {
URI string `json:"uri,omitempty"`
Digest map[string]string `json:"digest"`
DownloadLocation string `json:"downloadLocation,omitempty"`
}
func ToVSAResourceURI(sub intoto.Subject) (string, error) {
// parse purl
purl, err := packageurl.FromString(sub.Name)
if err != nil {
return "", fmt.Errorf("failed to parse package url: %w", err)
}
quals := purl.Qualifiers.Map()
if quals["digest"] == "" {
quals["digest"] = "sha256:" + sub.Digest["sha256"]
}
purl.Qualifiers = packageurl.QualifiersFromMap(quals)
return purl.String(), nil
}
func GetVerifierVersion(fetcher version.Fetcher) (VerifierVersion, error) {
attestVersion, err := fetcher.Get()
if err != nil {
return nil, fmt.Errorf("failed to get attest version: %w", err)
}
if attestVersion == nil {
return nil, nil
}
return VerifierVersion{
version.ThisModulePath: attestVersion.String(),
}, nil
}

View File

@@ -1,2 +1,5 @@
ignore:
- "internal/test"
coverage:
status:
patch: false

View File

@@ -1,13 +1,29 @@
/*
Copyright Docker attest 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.
*/
package attest_test
import (
"context"
"github.com/docker/attest/pkg/attest"
"github.com/docker/attest/pkg/attestation"
"github.com/docker/attest/pkg/mirror"
"github.com/docker/attest/pkg/oci"
"github.com/docker/attest/pkg/signerverifier"
"github.com/docker/attest"
"github.com/docker/attest/attestation"
"github.com/docker/attest/oci"
"github.com/docker/attest/signerverifier"
"github.com/docker/attest/tlog"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/empty"
"github.com/google/go-containerregistry/pkg/v1/mutate"
@@ -26,13 +42,19 @@ func ExampleSignStatements_remote() {
// signer, err := signerverifier.GetAWSSigner(cmd.Context(), aws_arn, aws_region)
// configure signing options
// use rekor transparency log wit static rekor public key (see options to use dynamic rekor public key)
rekor, err := tlog.NewRekorLog()
if err != nil {
panic(err)
}
opts := &attestation.SigningOptions{
SkipTL: true, // skip trust logging to a transparency log
TransparencyLog: rekor, // unset this to disable signature transparency logging
}
// load image index with unsigned attestation-manifests
ref := "docker/image-signer-verifier:latest"
attIdx, err := oci.IndexFromRemote(ref)
attIdx, err := oci.IndexFromRemote(context.Background(), ref)
if err != nil {
panic(err)
}
@@ -55,7 +77,7 @@ func ExampleSignStatements_remote() {
}
// push image index with signed attestation-manifests
err = mirror.PushIndexToRegistry(signedIndex, ref)
err = oci.PushIndexToRegistry(context.Background(), signedIndex, ref)
if err != nil {
panic(err)
}
@@ -66,11 +88,11 @@ func ExampleSignStatements_remote() {
Add: signedIndex,
Descriptor: v1.Descriptor{
Annotations: map[string]string{
oci.OciReferenceTarget: attIdx.Name,
oci.OCIReferenceTarget: attIdx.Name,
},
},
})
err = mirror.SaveIndexAsOCILayout(idx, path)
err = oci.SaveIndexAsOCILayout(idx, path)
if err != nil {
panic(err)
}

70
example_verify_test.go Normal file
View File

@@ -0,0 +1,70 @@
/*
Copyright Docker attest 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.
*/
package attest_test
import (
"context"
"fmt"
"os"
"path/filepath"
"github.com/docker/attest"
"github.com/docker/attest/oci"
"github.com/docker/attest/policy"
"github.com/docker/attest/tuf"
)
func ExampleVerify_remote() {
// create a tuf client
home, err := os.UserHomeDir()
if err != nil {
panic(err)
}
tufOutputPath := filepath.Join(home, ".docker", "tuf")
tufClientOpts := tuf.NewDockerDefaultClientOptions(tufOutputPath)
// create a resolver for remote attestations
image := "registry-1.docker.io/library/notary:server"
platform := "linux/amd64"
// configure policy options
opts := &policy.Options{
TUFClientOptions: tufClientOpts,
LocalTargetsDir: filepath.Join(home, ".docker", "policy"), // location to store policy files downloaded from TUF
LocalPolicyDir: "", // overrides TUF policy for local policy files if set
PolicyID: "", // set to ignore policy mapping and select a policy by id
DisableTUF: false, // set to disable TUF and rely on local policy files
}
src, err := oci.ParseImageSpec(image, oci.WithPlatform(platform))
if err != nil {
panic(err)
}
// verify attestations
result, err := attest.Verify(context.Background(), src, opts)
if err != nil {
panic(err)
}
switch result.Outcome {
case attest.OutcomeSuccess:
fmt.Println("policy passed")
case attest.OutcomeNoPolicy:
fmt.Println("no policy for image")
case attest.OutcomeFailure:
fmt.Println("policy failed")
}
}

200
go.mod
View File

@@ -1,97 +1,95 @@
module github.com/docker/attest
go 1.22.1
go 1.22.8
require (
github.com/Masterminds/semver/v3 v3.2.1
github.com/aws/aws-sdk-go-v2/config v1.27.26
github.com/Masterminds/semver/v3 v3.3.0
github.com/aws/aws-sdk-go-v2/config v1.28.5
github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231024185945-8841054dbdb8
github.com/containerd/platforms v0.2.1
github.com/containerd/containerd/v2 v2.0.0
github.com/containerd/platforms v1.0.0-rc.0
github.com/distribution/reference v0.6.0
github.com/docker-library/bashbrew v0.1.12
github.com/go-git/go-git/v5 v5.12.0
github.com/go-openapi/runtime v0.28.0
github.com/go-openapi/strfmt v0.23.0
github.com/google/go-containerregistry v0.20.0
github.com/hashicorp/go-cleanhttp v0.5.2
github.com/google/go-containerregistry v0.20.2
github.com/in-toto/in-toto-golang v0.9.0
github.com/open-policy-agent/opa v0.66.0
github.com/open-policy-agent/opa v0.70.0
github.com/opencontainers/image-spec v1.1.0
github.com/package-url/packageurl-go v0.1.3
github.com/pkg/errors v0.9.1
github.com/secure-systems-lab/go-securesystemslib v0.8.0
github.com/sigstore/cosign/v2 v2.2.4
github.com/sigstore/cosign/v2 v2.4.1
github.com/sigstore/rekor v1.3.6
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.7
github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.7
github.com/sigstore/sigstore v1.8.10
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.10
github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.10
github.com/stretchr/testify v1.9.0
github.com/testcontainers/testcontainers-go/modules/registry v0.32.0
github.com/theupdateframework/go-tuf/v2 v2.0.0
google.golang.org/api v0.188.0
gopkg.in/yaml.v3 v3.0.1
github.com/theupdateframework/go-tuf/v2 v2.0.2
google.golang.org/api v0.205.0
sigs.k8s.io/yaml v1.4.0
)
// fork of a fork (in case it goes away) with changes to support ArtifactType (https://github.com/google/go-containerregistry/pull/1931)
replace github.com/google/go-containerregistry v0.20.0 => github.com/kipz/go-containerregistry v0.0.0-20240722163910-ebe90246535d
// fork with changes to support ArtifactType (https://github.com/google/go-containerregistry/pull/1931)
replace github.com/google/go-containerregistry => github.com/docker/go-containerregistry v0.0.0-20240808132857-c8bfc44af7c8
require (
cloud.google.com/go v0.115.0 // indirect
cloud.google.com/go/auth v0.7.0 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect
cloud.google.com/go/compute/metadata v0.4.0 // indirect
cloud.google.com/go/iam v1.1.10 // indirect
cloud.google.com/go/kms v1.18.2 // indirect
cloud.google.com/go/longrunning v0.5.9 // indirect
dario.cat/mergo v1.0.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
cloud.google.com/go v0.116.0 // indirect
cloud.google.com/go/auth v0.10.1 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.5 // indirect
cloud.google.com/go/compute/metadata v0.5.2 // indirect
cloud.google.com/go/iam v1.2.1 // indirect
cloud.google.com/go/kms v1.20.0 // indirect
cloud.google.com/go/longrunning v0.6.1 // indirect
dario.cat/mergo v1.0.1 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/Microsoft/hcsshim v0.12.3 // indirect
github.com/Microsoft/hcsshim v0.12.9 // indirect
github.com/OneOfOne/xxhash v1.2.8 // indirect
github.com/ProtonMail/go-crypto v1.0.0 // indirect
github.com/agnivade/levenshtein v1.1.1 // indirect
github.com/agnivade/levenshtein v1.2.0 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/aws/aws-sdk-go-v2 v1.30.3 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.26 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2 v1.32.5 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.46 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
github.com/aws/aws-sdk-go-v2/service/ecr v1.29.1 // indirect
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.24.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 // indirect
github.com/aws/aws-sdk-go-v2/service/kms v1.35.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.22.3 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect
github.com/aws/smithy-go v1.20.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 // indirect
github.com/aws/aws-sdk-go-v2/service/kms v1.37.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 // indirect
github.com/aws/smithy-go v1.22.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver v3.5.1+incompatible // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudflare/circl v1.3.8 // indirect
github.com/containerd/containerd v1.7.19 // indirect
github.com/containerd/containerd v1.7.23 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect
github.com/cpuguy83/dockercfg v0.3.1 // indirect
github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 // indirect
github.com/digitorus/timestamp v0.0.0-20231217203849-220c5c2851b7 // indirect
github.com/docker/cli v26.1.3+incompatible // indirect
github.com/docker/cli v27.1.1+incompatible // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker v27.0.3+incompatible // indirect
github.com/docker/docker-credential-helpers v0.8.1 // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-chi/chi v4.1.2+incompatible // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.5.0 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-jose/go-jose/v4 v4.0.2 // indirect
github.com/go-jose/go-jose/v4 v4.0.4 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-openapi/analysis v0.23.0 // indirect
github.com/go-openapi/errors v0.22.0 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
@@ -101,103 +99,101 @@ require (
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-openapi/validate v0.24.0 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/certificate-transparency-go v1.1.8 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/certificate-transparency-go v1.2.1 // indirect
github.com/google/s2a-go v0.1.8 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.5 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/hashicorp/go-retryablehttp v0.7.6 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 // indirect
github.com/jellydator/ttlcache/v3 v3.2.0 // indirect
github.com/jellydator/ttlcache/v3 v3.3.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/klauspost/compress v1.17.8 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec // indirect
github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/patternmatcher v0.6.0 // indirect
github.com/moby/sys/sequential v0.5.0 // indirect
github.com/moby/sys/user v0.1.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/prometheus/client_golang v1.19.1 // indirect
github.com/prometheus/client_golang v1.20.5 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.53.0 // indirect
github.com/prometheus/procfs v0.15.0 // indirect
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/rogpeppe/go-internal v1.13.1 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sassoftware/relic v7.2.1+incompatible // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/shibumi/go-pathspec v1.3.0 // indirect
github.com/shirou/gopsutil/v3 v3.24.4 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/sigstore/sigstore v1.8.6 // indirect
github.com/sigstore/protobuf-specs v0.3.2 // indirect
github.com/sigstore/timestamp-authority v1.2.2 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/skeema/knownhosts v1.2.2 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/cobra v1.8.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.18.2 // indirect
github.com/spf13/viper v1.19.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
github.com/testcontainers/testcontainers-go v0.32.0 // indirect
github.com/theupdateframework/go-tuf v0.7.0 // indirect
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect
github.com/tklauser/go-sysconf v0.3.14 // indirect
github.com/tklauser/numcpus v0.8.0 // indirect
github.com/transparency-dev/merkle v0.0.2 // indirect
github.com/vbatts/tar-split v0.11.5 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/yashtewari/glob-intersection v0.2.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.mongodb.org/mongo-driver v1.15.0 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 // indirect
go.opentelemetry.io/otel v1.27.0 // indirect
go.opentelemetry.io/otel/metric v1.27.0 // indirect
go.opentelemetry.io/otel/sdk v1.27.0 // indirect
go.opentelemetry.io/otel/trace v1.27.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect
go.opentelemetry.io/otel v1.31.0 // indirect
go.opentelemetry.io/otel/metric v1.31.0 // indirect
go.opentelemetry.io/otel/sdk v1.31.0 // indirect
go.opentelemetry.io/otel/trace v1.31.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/crypto v0.25.0 // indirect
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.27.0 // indirect
golang.org/x/oauth2 v0.21.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/term v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/genproto v0.0.0-20240708141625-4ad9e859172b // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240708141625-4ad9e859172b // indirect
google.golang.org/grpc v1.64.1 // indirect
google.golang.org/protobuf v1.34.2 // indirect
golang.org/x/crypto v0.28.0 // indirect
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/net v0.30.0 // indirect
golang.org/x/oauth2 v0.23.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/term v0.25.0 // indirect
golang.org/x/text v0.19.0 // indirect
golang.org/x/time v0.7.0 // indirect
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect
google.golang.org/grpc v1.67.1 // indirect
google.golang.org/protobuf v1.35.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.5.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
pault.ag/go/debian v0.12.0 // indirect
pault.ag/go/topsort v0.1.1 // indirect
)

573
go.sum
View File

@@ -1,46 +1,42 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14=
cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU=
cloud.google.com/go/auth v0.7.0 h1:kf/x9B3WTbBUHkC+1VS8wwwli9TzhSt0vSTVBmMR8Ts=
cloud.google.com/go/auth v0.7.0/go.mod h1:D+WqdrpcjmiCgWrXmLLxOVq1GACoE36chW6KXoEvuIw=
cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4=
cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q=
cloud.google.com/go/compute/metadata v0.4.0 h1:vHzJCWaM4g8XIcm8kopr3XmDA4Gy/lblD3EhhSux05c=
cloud.google.com/go/compute/metadata v0.4.0/go.mod h1:SIQh1Kkb4ZJ8zJ874fqVkslA29PRXuleyj6vOzlbK7M=
cloud.google.com/go/iam v1.1.10 h1:ZSAr64oEhQSClwBL670MsJAW5/RLiC6kfw3Bqmd5ZDI=
cloud.google.com/go/iam v1.1.10/go.mod h1:iEgMq62sg8zx446GCaijmA2Miwg5o3UbO+nI47WHJps=
cloud.google.com/go/kms v1.18.2 h1:EGgD0B9k9tOOkbPhYW1PHo2W0teamAUYMOUIcDRMfPk=
cloud.google.com/go/kms v1.18.2/go.mod h1:YFz1LYrnGsXARuRePL729oINmN5J/5e7nYijgvfiIeY=
cloud.google.com/go/longrunning v0.5.9 h1:haH9pAuXdPAMqHvzX0zlWQigXT7B0+CL4/2nXXdBo5k=
cloud.google.com/go/longrunning v0.5.9/go.mod h1:HD+0l9/OOW0za6UWdKJtXoFAX/BGg/3Wj8p10NeWF7c=
cuelabs.dev/go/oci/ociregistry v0.0.0-20240314152124-224736b49f2e h1:GwCVItFUPxwdsEYnlUcJ6PJxOjTeFFCKOh6QWg4oAzQ=
cuelabs.dev/go/oci/ociregistry v0.0.0-20240314152124-224736b49f2e/go.mod h1:ApHceQLLwcOkCEXM1+DyCXTHEJhNGDpJ2kmV6axsx24=
cuelang.org/go v0.8.1 h1:VFYsxIFSPY5KgSaH1jQ2GxHOrbu6Ga3kEI70yCZwnOg=
cuelang.org/go v0.8.1/go.mod h1:CoDbYolfMms4BhWUlhD+t5ORnihR7wvjcfgyO9lL5FI=
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE=
cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U=
cloud.google.com/go/auth v0.10.1 h1:TnK46qldSfHWt2a0b/hciaiVJsmDXWy9FqyUan0uYiI=
cloud.google.com/go/auth v0.10.1/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI=
cloud.google.com/go/auth/oauth2adapt v0.2.5 h1:2p29+dePqsCHPP1bqDJcKj4qxRyYCcbzKpFyKGt3MTk=
cloud.google.com/go/auth/oauth2adapt v0.2.5/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8=
cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo=
cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k=
cloud.google.com/go/iam v1.2.1 h1:QFct02HRb7H12J/3utj0qf5tobFh9V4vR6h9eX5EBRU=
cloud.google.com/go/iam v1.2.1/go.mod h1:3VUIJDPpwT6p/amXRC5GY8fCCh70lxPygguVtI0Z4/g=
cloud.google.com/go/kms v1.20.0 h1:uKUvjGqbBlI96xGE669hcVnEMw1Px/Mvfa62dhM5UrY=
cloud.google.com/go/kms v1.20.0/go.mod h1:/dMbFF1tLLFnQV44AoI2GlotbjowyUfgVwezxW291fM=
cloud.google.com/go/longrunning v0.6.1 h1:lOLTFxYpr8hcRtcwWir5ITh1PAKUD/sG2lKrTSYjyMc=
cloud.google.com/go/longrunning v0.6.1/go.mod h1:nHISoOZpBcmlwbJmiVk5oDRz0qG/ZxPynEGs1iZ79s0=
cuelabs.dev/go/oci/ociregistry v0.0.0-20240404174027-a39bec0462d2 h1:BnG6pr9TTr6CYlrJznYUDj6V7xldD1W+1iXPum0wT/w=
cuelabs.dev/go/oci/ociregistry v0.0.0-20240404174027-a39bec0462d2/go.mod h1:pK23AUVXuNzzTpfMCA06sxZGeVQ/75FdVtW249de9Uo=
cuelang.org/go v0.9.2 h1:pfNiry2PdRBr02G/aKm5k2vhzmqbAOoaB4WurmEbWvs=
cuelang.org/go v0.9.2/go.mod h1:qpAYsLOf7gTM1YdEg6cxh553uZ4q9ZDWlPbtZr9q1Wk=
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230919221257-8b5d3ce2d11d h1:zjqpY4C7H15HjRPEenkS4SAn3Jy2eRRjkjZbGR30TOg=
github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230919221257-8b5d3ce2d11d/go.mod h1:XNqJ7hv2kY++g8XEHREpi+JqZo3+0l+CH2egBVN4yqM=
github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/alibabacloudsdkgo/helper v0.2.0 h1:8+4G8JaejP8Xa6W46PzJEwisNgBXMvFcz78N6zG/ARw=
github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/alibabacloudsdkgo/helper v0.2.0/go.mod h1:GgeIE+1be8Ivm7Sh4RgwI42aTtC9qrcj+Y9Y6CjJhJs=
github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/provider v0.14.0 h1:kcnfY4vljxXliXDBrA9K9lwF8IoEZ4Up6Eg9kWTIm28=
github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/provider v0.14.0/go.mod h1:tlqp9mUGbsP+0z3Q+c0Q5MgSdq/OMwQhm5bffR3Q3ss=
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.10.0 h1:n1DH8TPV4qqPTje2RcUBYwtrTWlabVp4n46+74X2pn4=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.10.0/go.mod h1:HDcZnuGbiyppErN6lB+idp4CKhjbc8gwjto6OPpyggM=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 h1:sO0/P7g68FrryJzljemN+6GTssUXdANk6aJ7T1ZxnsQ=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1/go.mod h1:h8hyGFDsU5HMivxiS2iYFZsgDbU9OnnJ163x5UGVKYo=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2 h1:LqbJ/WzJUwBf8UiaSzgX7aMclParm9/5Vgp+TY51uBQ=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.2/go.mod h1:yInRyqWXAuaPrgI7p70+lDDgh3mlBohis29jGMISnmc=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 h1:nyQWyZvwGTvunIMxi1Y9uXkcyr+I7TeNrr/foo4Kpk8=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0/go.mod h1:l38EPgmsp71HHLq9j7De57JcKOWPyhrsW1Awm1JS6K0=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0 h1:DRiANoJTiW6obBQe3SqZizkuV1PEgfiiGivmVocDy64=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0/go.mod h1:qLIye2hwb/ZouqhpSD9Zn3SJipvpEnz1Ywl3VUk9Y0s=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0/go.mod h1:bTSOgj05NGRuHHhQwAdPnYr9TOdNmKlZTgGLL6nyAdI=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw=
@@ -60,20 +56,22 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU=
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/DataDog/zstd v1.4.8/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.12.3 h1:LS9NXqXhMoqNCplK1ApmVSfB4UnVLRDWRapB6EIlxE0=
github.com/Microsoft/hcsshim v0.12.3/go.mod h1:Iyl1WVpZzr+UkzjekHZbV8o5Z9ZkxNGx6CtY2Qg/JVQ=
github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg=
github.com/Microsoft/hcsshim v0.12.9/go.mod h1:fJ0gkFAna6ukt0bLdKB8djt4XIJhF/vEPuoIWYVvZ8Y=
github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/ThalesIgnite/crypto11 v1.2.5 h1:1IiIIEqYmBvUYFeMnHqRft4bwf/O36jryEUpY+9ef8E=
github.com/ThalesIgnite/crypto11 v1.2.5/go.mod h1:ILDKtnCKiQ7zRoNxcp36Y1ZR8LBPmR2E23+wTQe/MlE=
github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8=
github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo=
github.com/agnivade/levenshtein v1.2.0 h1:U9L4IOT0Y3i0TIlUIDJ7rVUziKi/zPbrJGaFrtYH3SY=
github.com/agnivade/levenshtein v1.2.0/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU=
github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0=
github.com/alessio/shellescape v1.4.1/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30=
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4 h1:iC9YFYKDGEy3n/FtqJnOkZsene9olVspKmkX5A2YBEo=
@@ -96,58 +94,64 @@ github.com/alibabacloud-go/tea-utils v1.4.5 h1:h0/6Xd2f3bPE4XHTvkpjwxowIwRCJAJOq
github.com/alibabacloud-go/tea-utils v1.4.5/go.mod h1:KNcT0oXlZZxOXINnZBs6YvgOd5aYp9U67G+E3R8fcQw=
github.com/alibabacloud-go/tea-xml v1.1.3 h1:7LYnm+JbOq2B+T/B0fHC4Ies4/FofC4zHzYtqw7dgt0=
github.com/alibabacloud-go/tea-xml v1.1.3/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8=
github.com/aliyun/credentials-go v1.3.1 h1:uq/0v7kWrxmoLGpqjx7vtQ/s03f0zR//0br/xWDTE28=
github.com/aliyun/credentials-go v1.3.1/go.mod h1:8jKYhQuDawt8x2+fusqa1Y6mPxemTsBEN04dgcAcYz0=
github.com/aliyun/credentials-go v1.3.2 h1:L4WppI9rctC8PdlMgyTkF8bBsy9pyKQEzBD1bHMRl+g=
github.com/aliyun/credentials-go v1.3.2/go.mod h1:tlpz4uys4Rn7Ik4/piGRrTbXy2uLKvePgQJJduE+Y5c=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/aws/aws-sdk-go v1.54.16 h1:+B9zGaVwOUU6AO9Sy99VjTMDPthWx10HjB08hjaBHIc=
github.com/aws/aws-sdk-go v1.54.16/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
github.com/aws/aws-sdk-go-v2 v1.30.3 h1:jUeBtG0Ih+ZIFH0F4UkmL9w3cSpaMv9tYYDbzILP8dY=
github.com/aws/aws-sdk-go-v2 v1.30.3/go.mod h1:nIQjQVp5sfpQcTc9mPSr1B0PaWK5ByX9MOoDadSN4lc=
github.com/aws/aws-sdk-go-v2/config v1.27.26 h1:T1kAefbKuNum/AbShMsZEro6eRkeOT8YILfE9wyjAYQ=
github.com/aws/aws-sdk-go-v2/config v1.27.26/go.mod h1:ivWHkAWFrw/nxty5Fku7soTIVdqZaZ7dw+tc5iGW3GA=
github.com/aws/aws-sdk-go-v2/credentials v1.17.26 h1:tsm8g/nJxi8+/7XyJJcP2dLrnK/5rkFp6+i2nhmz5fk=
github.com/aws/aws-sdk-go-v2/credentials v1.17.26/go.mod h1:3vAM49zkIa3q8WT6o9Ve5Z0vdByDMwmdScO0zvThTgI=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 h1:KreluoV8FZDEtI6Co2xuNk/UqI9iwMrOx/87PBNIKqw=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11/go.mod h1:SeSUYBLsMYFoRvHE0Tjvn7kbxaUhl75CJi1sbfhMxkU=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 h1:SoNJ4RlFEQEbtDcCEt+QG56MY4fm4W8rYirAmq+/DdU=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15/go.mod h1:U9ke74k1n2bf+RIgoX1SXFed1HLs51OgUSs+Ph0KJP8=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 h1:C6WHdGnTDIYETAm5iErQUiVNsclNx9qbJVPIt03B6bI=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15/go.mod h1:ZQLZqhcu+JhSrA9/NXRm8SkDvsycE+JkV3WGY41e+IM=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU=
github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
github.com/aws/aws-sdk-go-v2 v1.32.5 h1:U8vdWJuY7ruAkzaOdD7guwJjD06YSKmnKCJs7s3IkIo=
github.com/aws/aws-sdk-go-v2 v1.32.5/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U=
github.com/aws/aws-sdk-go-v2/config v1.28.5 h1:Za41twdCXbuyyWv9LndXxZZv3QhTG1DinqlFsSuvtI0=
github.com/aws/aws-sdk-go-v2/config v1.28.5/go.mod h1:4VsPbHP8JdcdUDmbTVgNL/8w9SqOkM5jyY8ljIxLO3o=
github.com/aws/aws-sdk-go-v2/credentials v1.17.46 h1:AU7RcriIo2lXjUfHFnFKYsLCwgbz1E7Mm95ieIRDNUg=
github.com/aws/aws-sdk-go-v2/credentials v1.17.46/go.mod h1:1FmYyLGL08KQXQ6mcTlifyFXfJVCNJTVGuQP4m0d/UA=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 h1:sDSXIrlsFSFJtWKLQS4PUWRvrT580rrnuLydJrCQ/yA=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20/go.mod h1:WZ/c+w0ofps+/OUqMwWgnfrgzZH1DZO1RIkktICsqnY=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 h1:4usbeaes3yJnCFC7kfeyhkdkPtoRYPa/hTmCqMpKpLI=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24/go.mod h1:5CI1JemjVwde8m2WG3cz23qHKPOxbpkq0HaoreEgLIY=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 h1:N1zsICrQglfzaBnrfM0Ys00860C+QFwu6u/5+LomP+o=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24/go.mod h1:dCn9HbJ8+K31i8IQ8EWmWj0EiIk0+vKiHNMxTTYveAg=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc=
github.com/aws/aws-sdk-go-v2/service/ecr v1.29.1 h1:ywNLJrn/Qn4enDsz/XnKlvpnLqvJxFGQV2BltWltbis=
github.com/aws/aws-sdk-go-v2/service/ecr v1.29.1/go.mod h1:WadVIk+UrTvWuAsCp6BKGX4i2snurpz8mPWhJQnS7Dg=
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.24.1 h1:Eq9i/mvOlGghiKe9NtsmeD9Wlwg8p4fbsqrMb3nWirM=
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.24.1/go.mod h1:VtOgEoLEPV1YADuq+Z2XOK6/wKkGW2YK6DjChZ/GvDs=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 h1:dT3MqvGhSoaIhRseqw2I0yH81l7wiR2vjs57O51EAm8=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3/go.mod h1:GlAeCkHwugxdHaueRr4nhPuY+WW+gR8UjlcqzPr1SPI=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 h1:HGErhhrxZlQ044RiM+WdoZxp0p+EGM62y3L6pwA4olE=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17/go.mod h1:RkZEx4l0EHYDJpWppMJ3nD9wZJAa8/0lq9aVC+r2UII=
github.com/aws/aws-sdk-go-v2/service/kms v1.35.1 h1:0gP2OJJT6HM2BYltZ9x+A87OE8LJL96DXeAAdLv3t1M=
github.com/aws/aws-sdk-go-v2/service/kms v1.35.1/go.mod h1:hGONorZkQCfR5DW6l2xdy7zC8vfO0r9pJlwyg6gmGeo=
github.com/aws/aws-sdk-go-v2/service/sso v1.22.3 h1:Fv1vD2L65Jnp5QRsdiM64JvUM4Xe+E0JyVsRQKv6IeA=
github.com/aws/aws-sdk-go-v2/service/sso v1.22.3/go.mod h1:ooyCOXjvJEsUw7x+ZDHeISPMhtwI3ZCB7ggFMcFfWLU=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 h1:yiwVzJW2ZxZTurVbYWA7QOrAaCYQR72t0wrSBfoesUE=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4/go.mod h1:0oxfLkpz3rQ/CHlx5hB7H69YUpFiI1tql6Q6Ne+1bCw=
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 h1:ZsDKRLXGWHk8WdtyYMoGNO7bTudrvuKpDKgMVRlepGE=
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3/go.mod h1:zwySh8fpFyXp9yOr/KVzxOl8SRqgf/IDw5aUt9UKFcQ=
github.com/aws/smithy-go v1.20.3 h1:ryHwveWzPV5BIof6fyDvor6V3iUL7nTfiTKXHiW05nE=
github.com/aws/smithy-go v1.20.3/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 h1:wtpJ4zcwrSbwhECWQoI/g6WM9zqCcSpHDJIWSbMLOu4=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5/go.mod h1:qu/W9HXQbbQ4+1+JcZp0ZNPV31ym537ZJN+fiS7Ti8E=
github.com/aws/aws-sdk-go-v2/service/kms v1.37.2 h1:tfBABi5R6aSZlhgTWHxL+opYUDOnIGoNcJLwVYv0jLM=
github.com/aws/aws-sdk-go-v2/service/kms v1.37.2/go.mod h1:dZYFcQwuoh+cLOlFnZItijZptmyDhRIkOKWFO1CfzV8=
github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 h1:3zu537oLmsPfDMyjnUS2g+F2vITgy5pB74tHI+JBNoM=
github.com/aws/aws-sdk-go-v2/service/sso v1.24.6/go.mod h1:WJSZH2ZvepM6t6jwu4w/Z45Eoi75lPN7DcydSRtJg6Y=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 h1:K0OQAsDywb0ltlFrZm0JHPY3yZp/S9OaoLU33S7vPS8=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5/go.mod h1:ORITg+fyuMoeiQFiVGoqB3OydVTLkClw/ljbblMq6Cc=
github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 h1:6SZUVRQNvExYlMLbHdlKB48x0fLbc2iVROyaNEwBHbU=
github.com/aws/aws-sdk-go-v2/service/sts v1.33.1/go.mod h1:GqWyYCwLXnlUB1lOAXQyNSPqPLQJvmo8J0DWBzp9mtg=
github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro=
github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231024185945-8841054dbdb8 h1:SoFYaT9UyGkR0+nogNyD/Lj+bsixB+SNuAS4ABlEs6M=
github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231024185945-8841054dbdb8/go.mod h1:2JF49jcDOrLStIXN/j/K1EKRq8a8R2qRnlZA6/o/c7c=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/buildkite/agent/v3 v3.62.0 h1:yvzSjI8Lgifw883I8m9u8/L/Thxt4cLFd5aWPn3gg70=
github.com/buildkite/agent/v3 v3.62.0/go.mod h1:jN6SokGXrVNNIpI0BGQ+j5aWeI3gin8F+3zwA5Q6gqM=
github.com/buildkite/go-pipeline v0.3.2 h1:SW4EaXNwfjow7xDRPGgX0Rcx+dPj5C1kV9LKCLjWGtM=
github.com/buildkite/go-pipeline v0.3.2/go.mod h1:iY5jzs3Afc8yHg6KDUcu3EJVkfaUkd9x/v/OH98qyUA=
github.com/buildkite/interpolate v0.0.0-20200526001904-07f35b4ae251 h1:k6UDF1uPYOs0iy1HPeotNa155qXRWrzKnqAaGXHLZCE=
github.com/buildkite/interpolate v0.0.0-20200526001904-07f35b4ae251/go.mod h1:gbPR1gPu9dB96mucYIR7T3B7p/78hRVSOuzIWLHK2Y4=
github.com/buildkite/agent/v3 v3.81.0 h1:JVfkng2XnsXesFXwiFwLJFkuzVu4zvoJCvedfoIXD6E=
github.com/buildkite/agent/v3 v3.81.0/go.mod h1:edJeyycODRxaFvpT22rDGwaQ5oa4eB8GjtbjgX5VpFw=
github.com/buildkite/go-pipeline v0.13.1 h1:Y9p8pQIwPtauVwNrcmTDH6+XK7jE1nLuvWVaK8oymA8=
github.com/buildkite/go-pipeline v0.13.1/go.mod h1:2HHqlSFTYgHFhzedJu0LhLs9n5c9XkYnHiQFVN5HE4U=
github.com/buildkite/interpolate v0.1.3 h1:OFEhqji1rNTRg0u9DsSodg63sjJQEb1uWbENq9fUOBM=
github.com/buildkite/interpolate v0.1.3/go.mod h1:UNVe6A+UfiBNKbhAySrBbZFZFxQ+DXr9nWen6WVt/A8=
github.com/buildkite/roko v1.2.0 h1:hbNURz//dQqNl6Eo9awjQOVOZwSDJ8VEbBDxSfT9rGQ=
github.com/buildkite/roko v1.2.0/go.mod h1:23R9e6nHxgedznkwwfmqZ6+0VJZJZ2Sg/uVcp2cP46I=
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 h1:3uZCA/BLTIu+DqCfguByNMJa2HVHpXvjfy0Dy7g6fuA=
github.com/bytecodealliance/wasmtime-go/v3 v3.0.2/go.mod h1:RnUjnIXxEJcL6BgCvNyzCCRzZcxCgsZCi+RNlvYor5Q=
@@ -178,23 +182,25 @@ github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUo
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL2kskAlV9ckgEsNQXscjIaLiOYiZ75d4e94E6dcQ=
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w=
github.com/containerd/containerd v1.7.19 h1:/xQ4XRJ0tamDkdzrrBAUy/LE5nCcxFKdBm4EcPrSMEE=
github.com/containerd/containerd v1.7.19/go.mod h1:h4FtNYUUMB4Phr6v+xG89RYKj9XccvbNSCKjdufCrkc=
github.com/containerd/containerd v1.7.23 h1:H2CClyUkmpKAGlhQp95g2WXHfLYc7whAuvZGBNYOOwQ=
github.com/containerd/containerd v1.7.23/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw=
github.com/containerd/containerd/v2 v2.0.0 h1:qLDdFaAykQrIyLiqwQrNLLz95wiC36bAZVwioUwqShM=
github.com/containerd/containerd/v2 v2.0.0/go.mod h1:j25kDy9P48/ngb1sxWIFfK6GsnqOHoSqo1EpAod20VQ=
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
github.com/containerd/platforms v1.0.0-rc.0 h1:GuHWSKgVVO3POn6nRBB4sH63uPOLa87yuuhsGLWaXAA=
github.com/containerd/platforms v1.0.0-rc.0/go.mod h1:T1XAzzOdYs3it7l073MNXyxRwQofJfqwi/8cRjufIk4=
github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G/ZW/0kEe2oEKCdS/ZxIyoCU=
github.com/containerd/stargz-snapshotter/estargz v0.15.1/go.mod h1:gr2RNwukQ/S9Nv33Lt6UC7xEx58C+LHRdoqbEKjz1Kk=
github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoEaJU=
github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlSQupk0KK3ac=
github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E=
github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI=
github.com/coreos/go-oidc/v3 v3.11.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f h1:eHnXnuK47UlSTOQexbzxAZfekVz6i+LKRdj1CU5DPaM=
github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f/go.mod h1:uzvlm1mxhHkdfqitSA92i7Se+S9ksOn3a3qmv/kyOCw=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/danieljoos/wincred v1.2.1 h1:dl9cBrupW8+r5250DYkYxocLeZ1Y4vB1kxgtjxw8GQs=
github.com/danieljoos/wincred v1.2.1/go.mod h1:uGaFL9fDn3OLTvzCGulzE+SzjEe5NGlh5FdCcyfPwps=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -205,8 +211,8 @@ github.com/dgraph-io/badger/v3 v3.2103.5 h1:ylPa6qzbjYRQMU6jokoj4wzcaweHylt//CH0
github.com/dgraph-io/badger/v3 v3.2103.5/go.mod h1:4MPiseMeDQ3FNCYwRbbcBOGJLf5jsE0PPFzRiKjtcdw=
github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8=
github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA=
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g=
github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54 h1:SG7nF6SRlWhcT7cNTs5R6Hk4V2lcmLz2NsG2VnInyNo=
github.com/dgryski/trifles v0.0.0-20230903005119-f50d829f2e54/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA=
github.com/digitorus/pkcs7 v0.0.0-20230713084857-e76b763bdc49/go.mod h1:SKVExuS+vpu2l9IoOc0RwqE7NYnb0JlcFHFnEJkVDzc=
github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 h1:ge14PCmCvPjpMQMIAH7uKg0lrtNSOdpYsRXlwk3QbaE=
github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352/go.mod h1:SKVExuS+vpu2l9IoOc0RwqE7NYnb0JlcFHFnEJkVDzc=
@@ -216,24 +222,26 @@ github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/cli v26.1.3+incompatible h1:bUpXT/N0kDE3VUHI2r5VMsYQgi38kYuoC0oL9yt3lqc=
github.com/docker/cli v26.1.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker-library/bashbrew v0.1.12 h1:qykd2fxTMiudN/70XItEQqgk/7LeVoDiBTEnKTpkst8=
github.com/docker-library/bashbrew v0.1.12/go.mod h1:6fyRRSm4vgBAgTw87EsfOT7wXKsc4JA9I5cdQJmwOm8=
github.com/docker/cli v27.1.1+incompatible h1:goaZxOqs4QKxznZjjBWKONQci/MywhtRv2oNn0GkeZE=
github.com/docker/cli v27.1.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v27.0.3+incompatible h1:aBGI9TeQ4MPlhquTQKq9XbK79rKFVwXNUAYz9aXyEBE=
github.com/docker/docker v27.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo=
github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-containerregistry v0.0.0-20240808132857-c8bfc44af7c8 h1:T/wutVfQ1Oj4H5tbP5IZL5l6PZqzvapVJ5cB4Wy4Ucc=
github.com/docker/go-containerregistry v0.0.0-20240808132857-c8bfc44af7c8/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/emicklei/proto v1.12.1 h1:6n/Z2pZAnBwuhU66Gs8160B8rrrYKo7h2F2sCOnNceE=
github.com/emicklei/proto v1.12.1/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
@@ -253,22 +261,31 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec=
github.com/go-chi/chi v4.1.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY=
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k=
github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk=
github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E=
github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w=
@@ -305,8 +322,8 @@ github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68=
github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY=
github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -327,8 +344,8 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/certificate-transparency-go v1.1.8 h1:LGYKkgZF7satzgTak9R4yzfJXEeYVAjV6/EAEJOf1to=
github.com/google/certificate-transparency-go v1.1.8/go.mod h1:bV/o8r0TBKRf1X//iiiSgWrvII4d7/8OiA+3vG26gI8=
github.com/google/certificate-transparency-go v1.2.1 h1:4iW/NwzqOqYEEoCBEFP+jPbBXbLqMpq3CifMyOnDUME=
github.com/google/certificate-transparency-go v1.2.1/go.mod h1:bvn/ytAccv+I6+DGkqpvSsEdiVGramgaSC6RD3tEmeE=
github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM=
github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU=
@@ -340,7 +357,6 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
@@ -351,8 +367,8 @@ github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM=
github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA=
github.com/google/tink/go v1.7.0 h1:6Eox8zONGebBFcCBqkVmt60LaWZa6xg1cl/DwAh/J1w=
github.com/google/tink/go v1.7.0/go.mod h1:GAUOd+QE3pgj9q8VKIGTCP33c/B7eb4NhxLcgTJZStM=
github.com/google/trillian v1.6.0 h1:jMBeDBIkINFvS2n6oV5maDqfRlxREAc6CW9QYWQ0qT4=
@@ -360,15 +376,15 @@ github.com/google/trillian v1.6.0/go.mod h1:Yu3nIMITzNhhMJEHjAtp6xKiu+H/iHu2Oq5F
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
github.com/googleapis/gax-go/v2 v2.12.5 h1:8gw9KZK8TiVKB6q3zHY3SBzLnrGp6HQjyfYBYGmXdxA=
github.com/googleapis/gax-go/v2 v2.12.5/go.mod h1:BUDKcWo+RaKq5SC9vVYL0wLADa3VcfswbOMMRmB9H3E=
github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw=
github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA=
github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s=
github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
@@ -377,8 +393,8 @@ github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB1
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-retryablehttp v0.7.6 h1:TwRYfx2z2C4cLbXmT8I5PgP/xmuqASDyiVuGYfs9GZM=
github.com/hashicorp/go-retryablehttp v0.7.6/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 h1:UpiO20jno/eV1eVZcxqWnUohyKRe1g8FPV/xH1s/2qs=
@@ -389,22 +405,26 @@ github.com/hashicorp/go-sockaddr v1.0.5 h1:dvk7TIXCZpmfOlM+9mlcrWmWjw/wlKT+VDq2w
github.com/hashicorp/go-sockaddr v1.0.5/go.mod h1:uoUUmtwU7n9Dv3O4SNLeFvg0SxQ3lyjsj6+CCykpaxI=
github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM=
github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM=
github.com/hashicorp/vault/api v1.12.2 h1:7YkCTE5Ni90TcmYHDBExdt4WGJxhpzaHqR6uGbQb/rE=
github.com/hashicorp/vault/api v1.12.2/go.mod h1:LSGf1NGT1BnvFFnKVtnvcaLBM2Lz+gJdpL6HUYed8KE=
github.com/hashicorp/vault/api v1.14.0 h1:Ah3CFLixD5jmjusOgm8grfN9M0d+Y8fVR2SW0K6pJLU=
github.com/hashicorp/vault/api v1.14.0/go.mod h1:pV9YLxBGSz+cItFDd8Ii4G17waWOQ32zVjMWHe/cOqk=
github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef h1:A9HsByNhogrvm9cWb28sjiS3i7tcKCkflWFEkHfuAgM=
github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/in-toto/attestation v1.1.0 h1:oRWzfmZPDSctChD0VaQV7MJrywKOzyNrtpENQFq//2Q=
github.com/in-toto/attestation v1.1.0/go.mod h1:DB59ytd3z7cIHgXxwpSX2SABrU6WJUKg/grpdgHVgVs=
github.com/in-toto/in-toto-golang v0.9.0 h1:tHny7ac4KgtsfrG6ybU8gVOZux2H8jN05AXJ9EBM1XU=
github.com/in-toto/in-toto-golang v0.9.0/go.mod h1:xsBVrVsHNsB61++S6Dy2vWosKhuA3lUTQd+eF9HdeMo=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267 h1:TMtDYDHKYY15rFihtRfck/bfFqNfvcabqvXAFQfAUpY=
github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267/go.mod h1:h1nSAbGFqGVzn6Jyl1R/iCcBUHN4g+gW1u9CoBTrb9E=
github.com/jellydator/ttlcache/v3 v3.2.0 h1:6lqVJ8X3ZaUwvzENqPAobDsXNExfUJd61u++uW8a3LE=
github.com/jellydator/ttlcache/v3 v3.2.0/go.mod h1:hi7MGFdMAwZna5n2tuvh63DvFLzVKySzCVW6+0gA2n4=
github.com/jellydator/ttlcache/v3 v3.3.0 h1:BdoC9cE81qXfrxeb9eoJi9dWrdhSuwXMAnHTbnBm4Wc=
github.com/jellydator/ttlcache/v3 v3.3.0/go.mod h1:bj2/e0l4jRnQdrnSTaGTsh4GSXvMjQcy41i7th0GVGw=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
@@ -415,23 +435,22 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kipz/go-containerregistry v0.0.0-20240722163910-ebe90246535d h1:5QaWAwKhslfqxEyMZY0ofvsbMJkMLcx5E30JFufMVj8=
github.com/kipz/go-containerregistry v0.0.0-20240722163910-ebe90246535d/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kjk/lzma v0.0.0-20161016003348-3fd93898850d/go.mod h1:phT/jsRPBAEqjAibu1BurrabCBNTYiVI+zbmyCZJY6Q=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec h1:2tTW6cDth2TSgRbAhD7yjZzTQmcN25sDRPEeinR51yQ=
github.com/letsencrypt/boulder v0.0.0-20240620165639-de9c06129bec/go.mod h1:TmwEoGCwIti7BCeJ9hescZgRtatxRE+A72pCoPfmcfk=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae h1:dIZY4ULFcto4tAFlj1FYZl8ztUZ13bdq+PLY+NOfbyI=
github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
@@ -450,24 +469,12 @@ github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQ
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg=
github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mozillazg/docker-credential-acr-helper v0.3.0 h1:DVWFZ3/O8BP6Ue3iS/Olw+G07u1hCq1EOVCDZZjCIBI=
github.com/mozillazg/docker-credential-acr-helper v0.3.0/go.mod h1:cZlu3tof523ujmLuiNUb6JsjtHcNA70u1jitrrdnuyA=
github.com/mozillazg/docker-credential-acr-helper v0.4.0 h1:Uoh3Z9CcpEDnLiozDx+D7oDgRq7X+R296vAqAumnOcw=
github.com/mozillazg/docker-credential-acr-helper v0.4.0/go.mod h1:2kiicb3OlPytmlNC9XGkLvVC+f0qTiJw3f/mhmeeQBg=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 h1:Up6+btDp321ZG5/zdSLo48H9Iaq0UQGthrhWC6pCxzE=
@@ -478,8 +485,8 @@ github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/oleiade/reflections v1.0.1 h1:D1XO3LVEYroYskEsoSiGItp9RUxG6jWnCVvrqH0HHQM=
github.com/oleiade/reflections v1.0.1/go.mod h1:rdFxbxq4QXVZWj0F+e9jqjDkc7dbp97vkRixKo2JR60=
github.com/oleiade/reflections v1.1.0 h1:D+I/UsXQB4esMathlt0kkZRJZdUDmhv5zGi/HOwYTWo=
github.com/oleiade/reflections v1.1.0/go.mod h1:mCxx0QseeVCHs5Um5HhJeCKVC7AwS8kO67tky4rdisA=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
@@ -489,10 +496,11 @@ github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw=
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
github.com/open-policy-agent/opa v0.66.0 h1:DbrvfJQja0FBRcPOB3Z/BOckocN+M4ApNWyNhSRJt0w=
github.com/open-policy-agent/opa v0.66.0/go.mod h1:EIgNnJcol7AvQR/IcWLwL13k64gHVbNAVG46b2G+/EY=
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
github.com/open-policy-agent/opa v0.70.0 h1:B3cqCN2iQAyKxK6+GI+N40uqkin+wzIrM7YA60t9x1U=
github.com/open-policy-agent/opa v0.70.0/go.mod h1:Y/nm5NY0BX0BqjBriKUiV81sCl8XOjjvqQG7dXrggtI=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
@@ -503,8 +511,10 @@ github.com/package-url/packageurl-go v0.1.3 h1:4juMED3hHiz0set3Vq3KeQ75KD1avthoX
github.com/package-url/packageurl-go v0.1.3/go.mod h1:nKAWB8E6uk1MHqiS/lQb9pYBGH2+mdJ2PJc2s50dQY0=
github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw=
github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -512,24 +522,21 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE=
github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U=
github.com/prometheus/procfs v0.15.0 h1:A82kmvXJq2jTu5YUhSGNlYoxh85zLnKgPz4bMZgI5Ek=
github.com/prometheus/procfs v0.15.0/go.mod h1:Y0RJ/Y5g5wJpkTisOtqwDSo4HwhGmLB4VQSw2sQJLHk=
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/protocolbuffers/txtpbfmt v0.0.0-20231025115547-084445ff1adf h1:014O62zIzQwvoD7Ekj3ePDF5bv9Xxy0w6AZk0qYbjUk=
github.com/protocolbuffers/txtpbfmt v0.0.0-20231025115547-084445ff1adf/go.mod h1:jgxiZysxFPM+iWKwQwPR+y+Jvo54ARd4EisXxKYpB5c=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
@@ -545,34 +552,37 @@ github.com/secure-systems-lab/go-securesystemslib v0.8.0 h1:mr5An6X45Kb2nddcFlbm
github.com/secure-systems-lab/go-securesystemslib v0.8.0/go.mod h1:UH2VZVuJfCYR8WgMlCU1uFsOUU+KeyrTWcSS73NBOzU=
github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c=
github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI=
github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE=
github.com/shirou/gopsutil/v3 v3.24.4 h1:dEHgzZXt4LMNm+oYELpzl9YCqV65Yr/6SfrvgRBtXeU=
github.com/shirou/gopsutil/v3 v3.24.4/go.mod h1:lTd2mdiOspcqLgAnr9/nGi71NkeMpWKdmhuxm9GusH8=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/sigstore/cosign/v2 v2.2.4 h1:iY4vtEacmu2hkNj1Fh+8EBqBwKs2DHM27/lbNWDFJro=
github.com/sigstore/cosign/v2 v2.2.4/go.mod h1:JZlRD2uaEjVAvZ1XJ3QkkZJhTqSDVtLaet+C/TMR81Y=
github.com/sigstore/fulcio v1.4.5 h1:WWNnrOknD0DbruuZWCbN+86WRROpEl3Xts+WT2Ek1yc=
github.com/sigstore/fulcio v1.4.5/go.mod h1:oz3Qwlma8dWcSS/IENR/6SjbW4ipN0cxpRVfgdsjMU8=
github.com/sigstore/cosign/v2 v2.4.1 h1:b8UXEfJFks3hmTwyxrRNrn6racpmccUycBHxDMkEPvU=
github.com/sigstore/cosign/v2 v2.4.1/go.mod h1:GvzjBeUKigI+XYnsoVQDmMAsMMc6engxztRSuxE+x9I=
github.com/sigstore/fulcio v1.6.3 h1:Mvm/bP6ELHgazqZehL8TANS1maAkRoM23CRAdkM4xQI=
github.com/sigstore/fulcio v1.6.3/go.mod h1:5SDgLn7BOUVLKe1DwOEX3wkWFu5qEmhUlWm+SFf0GH8=
github.com/sigstore/protobuf-specs v0.3.2 h1:nCVARCN+fHjlNCk3ThNXwrZRqIommIeNKWwQvORuRQo=
github.com/sigstore/protobuf-specs v0.3.2/go.mod h1:RZ0uOdJR4OB3tLQeAyWoJFbNCBFrPQdcokntde4zRBA=
github.com/sigstore/rekor v1.3.6 h1:QvpMMJVWAp69a3CHzdrLelqEqpTM3ByQRt5B5Kspbi8=
github.com/sigstore/rekor v1.3.6/go.mod h1:JDTSNNMdQ/PxdsS49DJkJ+pRJCO/83nbR5p3aZQteXc=
github.com/sigstore/sigstore v1.8.6 h1:g066b/Nw5r5oxhNv4XqJUUzVcyf1b07itUueiQe7rZM=
github.com/sigstore/sigstore v1.8.6/go.mod h1:UOBrJd9JBQ81DrkpGljzsIFXEtfC30raHvLWFWG857U=
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.7 h1:SoahswHQm2JhO8h3KTAeX8IZeE7mSR2Lc53ay5choes=
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.7/go.mod h1:TOVOPOqldrrz4dP7x4/0DFQTs9QSXZUoHu21+JHmixA=
github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.3 h1:xgbPRCr2npmmsuVVteJqi/ERw9+I13Wou7kq0Yk4D8g=
github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.3/go.mod h1:G4+I83FILPX6MtnoaUdmv/bRGEVtR3JdLeJa/kXdk/0=
github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.7 h1:zYg1XlbKpQkmE7FpWTkLuUn7RttLAq4FcZ1G9JcqhoY=
github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.7/go.mod h1:VmUsO1R4OHuyHBEgI4bbSUn0z2nojszrDMvlDxyX/dE=
github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.3 h1:h9G8j+Ds21zqqulDbA/R/ft64oQQIyp8S7wJYABYSlg=
github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.3/go.mod h1:zgCeHOuqF6k7A7TTEvftcA9V3FRzB7mrPtHOhXAQBnc=
github.com/sigstore/sigstore v1.8.10 h1:r4t+TYzJlG9JdFxMy+um9GZhZ2N1hBTyTex0AHEZxFs=
github.com/sigstore/sigstore v1.8.10/go.mod h1:BekjqxS5ZtHNJC4u3Q3Stvfx2eyisbW/lUZzmPU2u4A=
github.com/sigstore/sigstore-go v0.6.1 h1:tGkkv1oDIER+QYU5MrjqlttQOVDWfSkmYwMqkJhB/cg=
github.com/sigstore/sigstore-go v0.6.1/go.mod h1:Xe5GHmUeACRFbomUWzVkf/xYCn8xVifb9DgqJrV2dIw=
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.10 h1:e5GfVngPjGap/N3ODefayt7vKIPS1/v3hWLZ9+4MrN4=
github.com/sigstore/sigstore/pkg/signature/kms/aws v1.8.10/go.mod h1:HOr3AdFPKdND2FNl/sUD5ZifPl1OMJvrbf9xIaaWcus=
github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.8 h1:RKk4Z+qMaLORUdT7zntwMqKiYAej1VQlCswg0S7xNSY=
github.com/sigstore/sigstore/pkg/signature/kms/azure v1.8.8/go.mod h1:dMJdlBWKHMu2xf0wIKpbo7+QfG+RzVkBB3nHP8EMM5o=
github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.10 h1:Xre51HdjIIaVo5ox5zyL+6h0tkrx7Ke9Neh7fLmmZK0=
github.com/sigstore/sigstore/pkg/signature/kms/gcp v1.8.10/go.mod h1:VNfdklQDbyGJog8S7apdxiEfmYmCkKyxrsCL9xprkTY=
github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.8 h1:Zte3Oogkd8m+nu2oK3yHtGmN++TZWh2Lm6q2iSprT1M=
github.com/sigstore/sigstore/pkg/signature/kms/hashivault v1.8.8/go.mod h1:j00crVw6ki4/WViXflw0zWgNALrAzZT+GbIK8v7Xlz4=
github.com/sigstore/timestamp-authority v1.2.2 h1:X4qyutnCQqJ0apMewFyx+3t7Tws00JQ/JonBiu3QvLE=
github.com/sigstore/timestamp-authority v1.2.2/go.mod h1:nEah4Eq4wpliDjlY342rXclGSO7Kb9hoRrl9tqLW13A=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A=
github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
@@ -585,22 +595,22 @@ github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
github.com/spiffe/go-spiffe/v2 v2.2.0 h1:9Vf06UsvsDbLYK/zJ4sYsIsHmMFknUD+feA7IYoWMQY=
github.com/spiffe/go-spiffe/v2 v2.2.0/go.mod h1:Urzb779b3+IwDJD2ZbN8fVl3Aa8G4N/PiUe6iXC0XxU=
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
github.com/spiffe/go-spiffe/v2 v2.3.0 h1:g2jYNb/PDMB8I7mBGL2Zuq/Ur6hUhoroxGQFyD6tTj8=
github.com/spiffe/go-spiffe/v2 v2.3.0/go.mod h1:Oxsaio7DBgSNqhAO9i/9tLClaVlfRok7zvJnTV8ZyIY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
@@ -609,43 +619,35 @@ github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDd
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48=
github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes=
github.com/tchap/go-patricia/v2 v2.3.1/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k=
github.com/testcontainers/testcontainers-go v0.32.0 h1:ug1aK08L3gCHdhknlTTwWjPHPS+/alvLJU/DRxTD/ME=
github.com/testcontainers/testcontainers-go v0.32.0/go.mod h1:CRHrzHLQhlXUsa5gXjTOfqIEJcrK5+xMDmBr/WMI88E=
github.com/testcontainers/testcontainers-go/modules/registry v0.32.0 h1:b4JSSEhbGXGtQA1WXJ3BlbkVjjdXoFTtBPvLRe+9Y9Y=
github.com/testcontainers/testcontainers-go/modules/registry v0.32.0/go.mod h1:bX3JF8vQkv3D2frmrDyQd0GCQIQGl5nPG91xUvl7UhA=
github.com/thales-e-security/pool v0.0.2 h1:RAPs4q2EbWsTit6tpzuvTFlgFRJ3S8Evf5gtvVDbmPg=
github.com/thales-e-security/pool v0.0.2/go.mod h1:qtpMm2+thHtqhLzTwgDBj/OuNnMpupY8mv0Phz0gjhU=
github.com/theupdateframework/go-tuf v0.7.0 h1:CqbQFrWo1ae3/I0UCblSbczevCCbS31Qvs5LdxRWqRI=
github.com/theupdateframework/go-tuf v0.7.0/go.mod h1:uEB7WSY+7ZIugK6R1hiBMBjQftaFzn7ZCDJcp1tCUug=
github.com/theupdateframework/go-tuf/v2 v2.0.0 h1:rD8d9RotYBprZVgC+9oyTZ5MmawepnTSTqoDuxjWgbs=
github.com/theupdateframework/go-tuf/v2 v2.0.0/go.mod h1:baB22nBHeHBCeuGZcIlctNq4P61PcOdyARlplg5xmLA=
github.com/theupdateframework/go-tuf/v2 v2.0.2 h1:PyNnjV9BJNzN1ZE6BcWK+5JbF+if370jjzO84SS+Ebo=
github.com/theupdateframework/go-tuf/v2 v2.0.2/go.mod h1:baB22nBHeHBCeuGZcIlctNq4P61PcOdyARlplg5xmLA=
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 h1:e/5i7d4oYZ+C1wj2THlRK+oAhjeS/TRQwMfkIuet3w0=
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399/go.mod h1:LdwHTNJT99C5fTAzDz0ud328OgXz+gierycbcIx2fRs=
github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY=
github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE=
github.com/transparency-dev/merkle v0.0.2 h1:Q9nBoQcZcgPamMkGn7ghV8XiTZ/kRxn1yCG81+twTK4=
github.com/transparency-dev/merkle v0.0.2/go.mod h1:pqSy+OXefQ1EDUVmAJ8MUhHB9TXGuzVAT58PqBoHz1A=
github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts=
github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk=
github.com/xanzy/go-gitlab v0.102.0 h1:ExHuJ1OTQ2yt25zBMMj0G96ChBirGYv8U7HyUiYkZ+4=
github.com/xanzy/go-gitlab v0.102.0/go.mod h1:ETg8tcj4OhrB84UEgeE8dSuV/0h4BBL1uOV/qK0vlyI=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xanzy/go-gitlab v0.109.0 h1:RcRme5w8VpLXTSTTMZdVoQWY37qTJWg+gwdQl4aAttE=
github.com/xanzy/go-gitlab v0.109.0/go.mod h1:wKNKh3GkYDMOsGmnfuX+ITCmDuSDWFO0G+C4AygL9RY=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
github.com/yashtewari/glob-intersection v0.2.0 h1:8iuHdN88yYuCzCdjt0gDe+6bAhUwBeEWqThExu54RFg=
github.com/yashtewari/glob-intersection v0.2.0/go.mod h1:LK7pIC3piUjovexikBbJ26Yml7g8xa5bsjfx2v1fwok=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/zalando/go-keyring v0.2.3 h1:v9CUu9phlABObO4LPWycf+zwMG7nlbb3t/B5wa97yms=
github.com/zalando/go-keyring v0.2.3/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk=
github.com/zeebo/errs v1.3.0 h1:hmiaKqgYZzcVgRL1Vkc1Mn2914BbzB0IBxs+ebeutGs=
@@ -654,28 +656,26 @@ go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUS
go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 h1:vS1Ao/R55RNV4O7TA2Qopok8yN+X0LIP6RVWLFkprck=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0/go.mod h1:BMsdeOxN04K0L5FNUBfjFdvwWGNe/rkmSwH4Aelu/X0=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 h1:9l89oX4ba9kHbBol3Xin3leYJ+252h0zszDtBwyKe2A=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0/go.mod h1:XLZfZboOJWHNKUv7eH0inh0E9VV6eWDFB/9yJyTLPp0=
go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg=
go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik=
go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak=
go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI=
go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A=
go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw=
go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4=
go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94=
go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A=
go.step.sm/crypto v0.44.2 h1:t3p3uQ7raP2jp2ha9P6xkQF85TJZh+87xmjSLaib+jk=
go.step.sm/crypto v0.44.2/go.mod h1:x1439EnFhadzhkuaGX7sz03LEMQ+jV4gRamf5LCZJQQ=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 h1:yMkBS9yViCc7U7yeLzJPM2XizlfdVvBRSmsQDWu6qc0=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0/go.mod h1:n8MR6/liuGB5EmTETUBeU5ZgqMOlqKRxUaqPQBOANZ8=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM=
go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY=
go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 h1:K0XaT3DwHAcV4nKLzcQvwAgSyisUghWoY20I7huthMk=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0/go.mod h1:B5Ki776z/MBnVha1Nzwp5arlzBbE3+1jk+pGmaP5HME=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 h1:FFeLy03iVTXP6ffeN2iXrxfGsZGCjVx0/4KlizjyBwU=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0/go.mod h1:TMu73/k1CP8nBUpDLc71Wj/Kf7ZS9FK5b53VapRsP9o=
go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE=
go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY=
go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk=
go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0=
go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys=
go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A=
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
go.step.sm/crypto v0.51.2 h1:5EiCGIMg7IvQTGmJrwRosbXeprtT80OhoS/PJarg60o=
go.step.sm/crypto v0.51.2/go.mod h1:QK7czLjN2k+uqVp5CHXxJbhc70kVRSP+0CQF3zsR5M0=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
@@ -685,23 +685,24 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -709,71 +710,65 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -781,48 +776,46 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
google.golang.org/api v0.188.0 h1:51y8fJ/b1AaaBRJr4yWm96fPcuxSo0JcegXE3DaHQHw=
google.golang.org/api v0.188.0/go.mod h1:VR0d+2SIiWOYG3r/jdm7adPW9hI2aRv9ETOSCQ9Beag=
google.golang.org/api v0.205.0 h1:LFaxkAIpDb/GsrWV20dMMo5MR0h8UARTbn24LmD+0Pg=
google.golang.org/api v0.205.0/go.mod h1:NrK1EMqO8Xk6l6QwRAmrXXg2v6dzukhlOyvkYtnvUuc=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20240708141625-4ad9e859172b h1:dSTjko30weBaMj3eERKc0ZVXW4GudCswM3m+P++ukU0=
google.golang.org/genproto v0.0.0-20240708141625-4ad9e859172b/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY=
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0=
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240708141625-4ad9e859172b h1:04+jVzTs2XBnOZcPsLnmrTGqltqJbZQ1Ey26hjYdQQ0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240708141625-4ad9e859172b/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU=
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38/go.mod h1:xBI+tzfqGGN2JBeSebfKXFSdBpWVQ7sLW40PTupVRm4=
google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 h1:fVoAXEKA4+yufmbdVYv+SE73+cPZbbbe8paLsHfkK+U=
google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53/go.mod h1:riSXTwQ4+nqmPGtobMFyW5FqVAmIs0St6VPp4Ug7CE4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA=
google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0=
google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -834,9 +827,10 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
@@ -846,6 +840,8 @@ gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -859,24 +855,29 @@ gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/api v0.28.3 h1:Gj1HtbSdB4P08C8rs9AR94MfSGpRhJgsS+GF9V26xMM=
k8s.io/api v0.28.3/go.mod h1:MRCV/jr1dW87/qJnZ57U5Pak65LGmQVkKTzf3AtKFHc=
k8s.io/apimachinery v0.28.3 h1:B1wYx8txOaCQG0HmYF6nbpU8dg6HvA06x5tEffvOe7A=
k8s.io/apimachinery v0.28.3/go.mod h1:uQTKmIqs+rAYaq+DFaoD2X7pcjLOqbQX2AOiO0nIpb8=
k8s.io/client-go v0.28.3 h1:2OqNb72ZuTZPKCl+4gTKvqao0AMOl9f3o2ijbAj3LI4=
k8s.io/client-go v0.28.3/go.mod h1:LTykbBp9gsA7SwqirlCXBWtK0guzfhpoW4qSm7i9dxo=
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/api v0.31.2 h1:3wLBbL5Uom/8Zy98GRPXpJ254nEFpl+hwndmk9RwmL0=
k8s.io/api v0.31.2/go.mod h1:bWmGvrGPssSK1ljmLzd3pwCQ9MgoTsRCuK35u6SygUk=
k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw=
k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
k8s.io/client-go v0.31.2 h1:Y2F4dxU5d3AQj+ybwSMqQnpZH9F30//1ObxOKlTI9yc=
k8s.io/client-go v0.31.2/go.mod h1:NPa74jSVR/+eez2dFsEIHNa+3o09vtNaWwWwb1qSxSs=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
pault.ag/go/debian v0.12.0 h1:b8ctSdBSGJ98NE1VLn06aSx70EUpczlP2qqSHEiYYJA=
pault.ag/go/debian v0.12.0/go.mod h1:UbnMr3z/KZepjq7VzbYgBEfz8j4+Pyrm2L5X1fzhy/k=
pault.ag/go/topsort v0.0.0-20160530003732-f98d2ad46e1a/go.mod h1:INqx0ClF7kmPAMk2zVTX8DRnhZ/yaA/Mg52g8KFKE7k=
pault.ag/go/topsort v0.1.1 h1:L0QnhUly6LmTv0e3DEzbN2q6/FGgAcQvaEw65S53Bg4=
pault.ag/go/topsort v0.1.1/go.mod h1:r1kc/L0/FZ3HhjezBIPaNVhkqv8L0UJ9bxRuHRVZ0q4=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/release-utils v0.7.7 h1:JKDOvhCk6zW8ipEOkpTGDH/mW3TI+XqtPp16aaQ79FU=
sigs.k8s.io/release-utils v0.7.7/go.mod h1:iU7DGVNi3umZJ8q6aHyUFzsDUIaYwNnNKGHo3YE5E3s=
sigs.k8s.io/structured-merge-diff/v4 v4.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk=
sigs.k8s.io/structured-merge-diff/v4 v4.3.0/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/release-utils v0.8.4 h1:4QVr3UgbyY/d9p74LBhg0njSVQofUsAZqYOzVZBhdBw=
sigs.k8s.io/release-utils v0.8.4/go.mod h1:m1bHfscTemQp+z+pLCZnkXih9n0+WukIUU70n6nFnU0=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
software.sslmate.com/src/go-pkcs12 v0.4.0 h1:H2g08FrTvSFKUj+D309j1DPfk5APnIdAQAB8aEykJ5k=

View File

@@ -1,3 +1,19 @@
/*
Copyright Docker attest 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.
*/
package embed
import (
@@ -16,11 +32,13 @@ var prodRoot []byte
var defaultRoot = prodRoot
type RootName string
type EmbeddedRoot struct {
Data []byte
Name RootName
}
type (
RootName string
EmbeddedRoot struct {
Data []byte
Name RootName
}
)
var (
RootDev = EmbeddedRoot{Data: devRoot, Name: "dev"}

176
internal/git/git.go Normal file
View File

@@ -0,0 +1,176 @@
/*
Copyright Docker attest 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.
*/
package git
import (
"archive/tar"
"bytes"
"context"
"fmt"
"io"
"os/exec"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
)
// GitCommand is the path to the git binary, overridden in tests to check behavior when git is not installed.
var GitCommand = "git"
func Clone(ctx context.Context, gitRepo string, gitCommit string, targetDir string) error {
const localBranch = "FETCH_HEAD"
repo, err := git.PlainInit(targetDir, false)
if err != nil {
return fmt.Errorf("failed to init: %w", err)
}
remote, err := repo.CreateRemote(&config.RemoteConfig{
Name: "origin",
URLs: []string{gitRepo},
Fetch: []config.RefSpec{
config.RefSpec(fmt.Sprintf("%s:%s", gitCommit, localBranch)),
},
})
if err != nil {
return fmt.Errorf("failed to add remote: %w", err)
}
err = remote.FetchContext(ctx, &git.FetchOptions{
Depth: 1,
})
if err != nil {
return fmt.Errorf("failed to fetch: %w", err)
}
wt, err := repo.Worktree()
if err != nil {
return fmt.Errorf("failed to get worktree: %w", err)
}
err = wt.Checkout(&git.CheckoutOptions{
Hash: plumbing.NewHash(gitCommit),
})
if err != nil {
return fmt.Errorf("failed to checkout: %w", err)
}
return nil
}
type execError struct {
*exec.ExitError
stderr []byte
}
func (e *execError) Error() string {
trimmed := bytes.TrimSpace(e.stderr)
if len(trimmed) == 0 {
return e.ExitError.Error()
}
return fmt.Sprintf("%s, %q", e.ExitError.Error(), string(bytes.TrimSpace(e.stderr)))
}
func (e *execError) Unwrap() error {
return e.ExitError
}
// Archive creates a tar archive of the files in the subdirectory given by subdir of the git repository at gitRepoDir.
// This is accomplished by running `git archive --format=tar HEAD:subdir` in the git repository directory.
//
// The archive is written to the returned io.Reader. It is not necessary to close the returned reader.
// Any error encountered while starting the command will be returned immediately.
// Any error encountered after the command is running will be returned on the next read from the returned io.Reader.
func Archive(ctx context.Context, gitRepoDir string, subdir string) (io.Reader, error) {
readPipe, writePipe := io.Pipe()
treeish := fmt.Sprintf("HEAD:%s", subdir)
cmd := exec.CommandContext(ctx, GitCommand, "archive", "--format=tar", treeish)
// run the command inside the git repo directory
cmd.Dir = gitRepoDir
// set the standard output to the write end of the pipe
cmd.Stdout = writePipe
// capture standard error so we can include it in the error message if the command fails
stderr := new(bytes.Buffer)
cmd.Stderr = stderr
err := cmd.Start()
if err != nil {
return nil, fmt.Errorf("failed to start command: %w", err)
}
// spawn a goroutine to wait for the command to finish and close the write pipe
go func() {
var err error // variable to hold any error
defer func() {
if p := recover(); p != nil {
// if we panic, set err to a new error wrapping the panic value
err = fmt.Errorf("panic: %v", p)
}
// send any error from the command (or the panic above) to the write pipe
// or nil if there was no error
// this will cause the error to be returned on the next read from the read pipe
writePipe.CloseWithError(err)
}()
// wait for the command to finish and capture any error
err = cmd.Wait()
if err != nil {
if ee, ok := err.(*exec.ExitError); ok {
err = &execError{ExitError: ee, stderr: stderr.Bytes()}
}
}
}()
return readPipe, nil
}
func TarScrub(in io.Reader, out io.Writer) error {
tr := tar.NewReader(in)
tw := tar.NewWriter(out)
defer tw.Flush() // note: flush instead of close to avoid the empty block at EOF
for {
hdr, err := tr.Next()
if err == io.EOF {
return nil
}
if err != nil {
return err
}
newHdr := &tar.Header{
Typeflag: hdr.Typeflag,
Name: hdr.Name,
Linkname: hdr.Linkname,
Size: hdr.Size,
Mode: hdr.Mode,
Devmajor: hdr.Devmajor,
Devminor: hdr.Devminor,
}
if err := tw.WriteHeader(newHdr); err != nil {
return err
}
_, err = io.CopyN(tw, tr, hdr.Size)
if err != nil {
return err
}
}
}

42
internal/git/git_test.go Normal file
View File

@@ -0,0 +1,42 @@
/*
Copyright Docker attest 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.
*/
package git
import (
"context"
"os"
"os/exec"
"testing"
"github.com/stretchr/testify/require"
)
func TestArchiveWithInvalidGitCommand(t *testing.T) {
originalGitCommand := GitCommand
GitCommand = "invalid-git-command"
defer func() { GitCommand = originalGitCommand }()
tempDir, err := os.MkdirTemp("", "gitrepo")
if err != nil {
t.Fatalf("failed to create temp dir: %v", err)
}
defer os.RemoveAll(tempDir)
ctx := context.Background()
_, err = Archive(ctx, tempDir, "")
require.ErrorIs(t, err, exec.ErrNotFound)
}

View File

@@ -1,64 +0,0 @@
package test
import (
"context"
"os"
"path/filepath"
"github.com/docker/attest/pkg/attestation"
"github.com/docker/attest/pkg/oci"
"github.com/docker/attest/pkg/signerverifier"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/secure-systems-lab/go-securesystemslib/dsse"
)
type MockResolver struct {
Envs []*attestation.Envelope
}
func (r MockResolver) Attestations(ctx context.Context, mediaType string) ([]*attestation.Envelope, error) {
return r.Envs, nil
}
func (r MockResolver) ImageName(ctx context.Context) (string, error) {
return "library/alpine:latest", nil
}
func (r MockResolver) ImageDescriptor(ctx context.Context) (*v1.Descriptor, error) {
digest, err := v1.NewHash("sha256:da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620")
if err != nil {
return nil, err
}
return &v1.Descriptor{
Digest: digest,
Size: 1234,
MediaType: "application/vnd.oci.image.manifest.v1+json",
}, nil
}
func (r MockResolver) ImagePlatform(ctx context.Context) (*v1.Platform, error) {
return oci.ParsePlatform("linux/amd64")
}
type MockRegistryResolver struct {
Subject *v1.Descriptor
ImageNameStr string
*MockResolver
}
func (r *MockRegistryResolver) ImageDescriptor(ctx context.Context) (*v1.Descriptor, error) {
return r.Subject, nil
}
func (r *MockRegistryResolver) ImageName(ctx context.Context) (string, error) {
return r.ImageNameStr, nil
}
func GetMockSigner(ctx context.Context) (dsse.SignerVerifier, error) {
priv, err := os.ReadFile(filepath.Join("..", "..", "test", "testdata", "test-signing-key.pem"))
if err != nil {
return nil, err
}
return signerverifier.LoadKeyPair(priv)
}

View File

@@ -1,34 +1,61 @@
/*
Copyright Docker attest 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.
*/
package test
import (
"context"
"encoding/base64"
"encoding/json"
"crypto"
"crypto/x509"
_ "embed"
"encoding/pem"
"fmt"
"io"
"log"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
"github.com/docker/attest/pkg/attestation"
"github.com/docker/attest/pkg/policy"
"github.com/docker/attest/pkg/signerverifier"
"github.com/docker/attest/pkg/tlog"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/layout"
"github.com/google/go-containerregistry/pkg/v1/partial"
intoto "github.com/in-toto/in-toto-golang/in_toto"
"github.com/docker/attest/signerverifier"
"github.com/docker/attest/useragent"
"github.com/google/go-containerregistry/pkg/registry"
"github.com/secure-systems-lab/go-securesystemslib/dsse"
)
const (
USE_MOCK_TL = true
USE_MOCK_KMS = true
USE_MOCK_POLICY = true
AwsRegion = "us-east-1"
AwsKmsKeyArn = "arn:aws:kms:us-east-1:175142243308:alias/doi-signing" // sandbox
UseMockKMS = true
AWSRegion = "us-east-1"
AWSKMSKeyARN = "arn:aws:kms:us-east-1:175142243308:alias/doi-signing" // sandbox
UnsignedLinuxAMD64ImageDigest = "sha256:da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620"
UnsignedLinuxArm64ImageDigest = "sha256:7a76cec943853f9f7105b1976afa1bf7cd5bb6afc4e9d5852dd8da7cf81ae86e"
)
func UnsignedTestIndex(rel ...string) string {
rel = append(rel, "test", "testdata", "unsigned-index")
return filepath.Join(rel...)
}
func UnsignedTestImage(rel ...string) string {
rel = append(rel, "test", "testdata", "unsigned-image")
return filepath.Join(rel...)
}
func CreateTempDir(t *testing.T, dir, pattern string) string {
// Create a temporary directory for output oci layout
tempDir, err := os.MkdirTemp(dir, pattern)
@@ -45,34 +72,24 @@ func CreateTempDir(t *testing.T, dir, pattern string) string {
return tempDir
}
//go:embed test-signing-key.pem
var signingKey []byte
func GetMockSigner(_ context.Context) (dsse.SignerVerifier, error) {
return signerverifier.LoadKeyPair(signingKey)
}
func Setup(t *testing.T) (context.Context, dsse.SignerVerifier) {
var tl tlog.TL
if USE_MOCK_TL {
tl = tlog.GetMockTL()
} else {
tl = &tlog.RekorTL{}
}
ctx := tlog.WithTL(context.Background(), tl)
var policyEvaluator policy.PolicyEvaluator
if USE_MOCK_POLICY {
policyEvaluator = policy.GetMockPolicy()
} else {
policyEvaluator = policy.NewRegoEvaluator(true)
}
ctx = policy.WithPolicyEvaluator(ctx, policyEvaluator)
ctx := context.Background()
var signer dsse.SignerVerifier
var err error
if USE_MOCK_KMS {
if UseMockKMS {
signer, err = GetMockSigner(ctx)
if err != nil {
t.Fatal(err)
}
} else {
signer, err = signerverifier.GetAWSSigner(ctx, AwsKmsKeyArn, AwsRegion)
signer, err = signerverifier.GetAWSSigner(ctx, AWSKMSKeyARN, AWSRegion)
if err != nil {
t.Fatal(err)
}
@@ -81,106 +98,30 @@ func Setup(t *testing.T) (context.Context, dsse.SignerVerifier) {
return ctx, signer
}
type AnnotatedStatement struct {
OCIDescriptor *v1.Descriptor
InTotoStatement *intoto.Statement
Annotations map[string]string
func NewLocalRegistry(ctx context.Context, options ...registry.Option) *httptest.Server {
options = append(options, registry.Logger(log.New(io.Discard, "", log.LstdFlags)))
regHandler := registry.New(options...)
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Check the user agent
ua := r.Header.Get("User-Agent")
userAgent := useragent.Get(ctx)
if !strings.HasPrefix(ua, userAgent) {
http.Error(w, fmt.Sprintf("expected user agent to contain %q, got %q", userAgent, ua), http.StatusForbidden)
}
regHandler.ServeHTTP(w, r)
}))
}
func ExtractStatementsFromIndex(idx v1.ImageIndex, mediaType string) ([]*AnnotatedStatement, error) {
mfs2, err := idx.IndexManifest()
func PublicKeyToPEM(pubKey crypto.PublicKey) (string, error) {
derBytes, err := x509.MarshalPKIXPublicKey(pubKey)
if err != nil {
return nil, fmt.Errorf("failed to extract IndexManifest from ImageIndex: %w", err)
return "", err
}
var statements []*AnnotatedStatement
for _, mf := range mfs2.Manifests {
if mf.Annotations[attestation.DockerReferenceType] != "attestation-manifest" {
continue
}
attestationImage, err := idx.Image(mf.Digest)
if err != nil {
return nil, fmt.Errorf("failed to extract attestation image with digest %s: %w", mf.Digest.String(), err)
}
layers, err := attestationImage.Layers()
if err != nil {
return nil, fmt.Errorf("failed to extract layers from attestation image: %w", err)
}
for _, layer := range layers {
// parse layer blob as json
mt, err := layer.MediaType()
if err != nil {
return nil, fmt.Errorf("failed to get layer media type: %w", err)
}
if string(mt) != mediaType {
continue
}
r, err := layer.Uncompressed()
if err != nil {
return nil, fmt.Errorf("failed to get layer contents: %w", err)
}
defer r.Close()
var intotoStatement = new(intoto.Statement)
var desc *v1.Descriptor
if strings.HasSuffix(string(mt), "+dsse") {
var env = new(attestation.Envelope)
err = json.NewDecoder(r).Decode(env)
if err != nil {
return nil, fmt.Errorf("failed to decode env: %w", err)
}
payload, err := base64.StdEncoding.Strict().DecodeString(env.Payload)
if err != nil {
return nil, fmt.Errorf("failed to decode payload: %w", err)
}
err = json.Unmarshal([]byte(payload), intotoStatement)
if err != nil {
return nil, fmt.Errorf("failed to decode %s statement: %w", mediaType, err)
}
} else {
desc := new(v1.Descriptor)
err = json.NewDecoder(r).Decode(desc)
if err != nil {
return nil, fmt.Errorf("failed to decode statement: %w", err)
}
}
layerDesc, err := partial.Descriptor(layer)
if err != nil {
return nil, fmt.Errorf("failed to get descriptor for layer: %w", err)
}
annotations := make(map[string]string)
for k, v := range layerDesc.Annotations {
annotations[k] = v
}
statements = append(statements, &AnnotatedStatement{
OCIDescriptor: desc,
InTotoStatement: intotoStatement,
Annotations: annotations,
})
}
pemBlock := &pem.Block{
Type: "PUBLIC KEY",
Bytes: derBytes,
}
return statements, nil
}
func ExtractAnnotatedStatements(path string, mediaType string) ([]*AnnotatedStatement, error) {
idx, err := layout.ImageIndexFromPath(path)
if err != nil {
return nil, fmt.Errorf("failed to load image index: %w", err)
}
idxm, err := idx.IndexManifest()
if err != nil {
return nil, fmt.Errorf("failed to get digest: %w", err)
}
idxDigest := idxm.Manifests[0].Digest
mfs, err := idx.ImageIndex(idxDigest)
if err != nil {
return nil, fmt.Errorf("failed to extract ImageIndex for digest %s: %w", idxDigest.String(), err)
}
return ExtractStatementsFromIndex(mfs, mediaType)
return string(pem.EncodeToMemory(pemBlock)), nil
}

View File

@@ -1,23 +0,0 @@
package test
import (
"path/filepath"
"testing"
intoto "github.com/in-toto/in-toto-golang/in_toto"
"github.com/stretchr/testify/assert"
)
var (
UnsignedTestImage = filepath.Join("..", "..", "test", "testdata", "unsigned-test-image")
)
const (
ExpectedStatements = 4
)
func TestExtractAnnotatedStatements(t *testing.T) {
statements, err := ExtractAnnotatedStatements(UnsignedTestImage, intoto.PayloadType)
assert.NoError(t, err)
assert.Equalf(t, len(statements), ExpectedStatements, "expected %d statement, got %d", ExpectedStatements, len(statements))
}

View File

@@ -1,3 +1,19 @@
/*
Copyright Docker attest 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.
*/
package util
import (

154
mapping/mapping.go Normal file
View File

@@ -0,0 +1,154 @@
/*
Copyright Docker attest 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.
*/
package mapping
import (
"errors"
"fmt"
"os"
"path/filepath"
"regexp"
"github.com/docker/attest/tuf"
v1 "github.com/google/go-containerregistry/pkg/v1"
"sigs.k8s.io/yaml"
)
const (
MappingFilename = "mapping.yaml"
)
func validateMappingsFile(mappings *policyMappingsFile) error {
var validationErrors []error
if mappings.Kind != "policy-mapping" {
validationErrors = append(validationErrors, fmt.Errorf("file is not of kind policy-mapping: %s", mappings.Kind))
}
if mappings.Version != "v1" {
validationErrors = append(validationErrors, fmt.Errorf("unsupported policy mapping file version: %s", mappings.Version))
}
for _, rule := range mappings.Rules {
if rule.Pattern == "" {
validationErrors = append(validationErrors, fmt.Errorf("rule missing pattern: %s", rule))
}
if rule.PolicyID == "" && rule.Replacement == "" {
validationErrors = append(validationErrors, fmt.Errorf("rule must have policy-id or replacement: %s", rule))
}
if rule.PolicyID != "" && rule.Replacement != "" {
validationErrors = append(validationErrors, fmt.Errorf("rule cannot have both policy-id and replacement: %s", rule))
}
if rule.Platforms != nil {
for _, platform := range rule.Platforms {
if platform == "" {
validationErrors = append(validationErrors, fmt.Errorf("rule has empty platform: %s", rule))
}
}
}
}
for _, policy := range mappings.Policies {
if policy.ID == "" {
validationErrors = append(validationErrors, fmt.Errorf("policy missing id: %s", policy.ID))
}
if len(policy.Files) == 0 {
validationErrors = append(validationErrors, fmt.Errorf("policy missing files: %v", policy))
}
for _, file := range policy.Files {
if file.Path == "" {
validationErrors = append(validationErrors, fmt.Errorf("file missing path: %s", file))
}
}
}
if len(validationErrors) > 0 {
return errors.Join(validationErrors...)
}
return nil
}
func parsePolicyMappingsFile(data []byte) (*PolicyMappings, error) {
mappings := &policyMappingsFile{}
err := yaml.Unmarshal(data, mappings)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal policy mapping file: %w", err)
}
err = validateMappingsFile(mappings)
if err != nil {
return nil, fmt.Errorf("invalid policy mapping file: %w", err)
}
return expandMappingFile(mappings)
}
func LoadLocalMappings(configDir string) (*PolicyMappings, error) {
if configDir == "" {
return nil, nil
}
path := filepath.Join(configDir, MappingFilename)
mappingFile, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("failed to read local policy mapping file %s: %w", path, err)
}
return parsePolicyMappingsFile(mappingFile)
}
func LoadTUFMappings(tufClient tuf.Downloader, localTargetsDir string) (*PolicyMappings, error) {
if tufClient == nil {
return nil, fmt.Errorf("tuf client not set")
}
filename := MappingFilename
file, err := tufClient.DownloadTarget(filename, filepath.Join(localTargetsDir, filename))
if err != nil {
return nil, fmt.Errorf("failed to download policy mapping file %s: %w", filename, err)
}
return parsePolicyMappingsFile(file.Data)
}
func expandMappingFile(mappingFile *policyMappingsFile) (*PolicyMappings, error) {
policies := make(map[string]*PolicyMapping)
for _, policy := range mappingFile.Policies {
policies[policy.ID] = policy
}
var rules []*PolicyRule
for _, rule := range mappingFile.Rules {
patternRegex, err := regexp.Compile(rule.Pattern)
if err != nil {
return nil, err
}
platforms := make([]*v1.Platform, 0, len(rule.Platforms))
for _, platform := range rule.Platforms {
parsedPlatform, err := v1.ParsePlatform(platform)
if err != nil {
return nil, fmt.Errorf("failed to parse platform %s: %w", platform, err)
}
platforms = append(platforms, parsedPlatform)
}
rules = append(rules, &PolicyRule{
Pattern: patternRegex,
PolicyID: rule.PolicyID,
Replacement: rule.Replacement,
Platforms: platforms,
})
}
return &PolicyMappings{
Version: mappingFile.Version,
Kind: mappingFile.Kind,
Policies: policies,
Rules: rules,
}, nil
}

98
mapping/mapping_test.go Normal file
View File

@@ -0,0 +1,98 @@
/*
Copyright Docker attest 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.
*/
package mapping
import (
"testing"
"github.com/stretchr/testify/require"
)
func newMapping() *policyMappingsFile {
return &policyMappingsFile{
Version: "v1",
Kind: "policy-mapping",
Policies: []*PolicyMapping{
{
ID: "docker-official-images",
Files: []PolicyMappingFile{
{
Path: "docker.io/library/alpine",
},
},
},
},
Rules: []*policyRuleFile{
{
Pattern: "docker.io/library/alpine",
PolicyID: "docker-official-images",
},
},
}
}
func TestMappingsFileValidation(t *testing.T) {
mappings := newMapping()
err := validateMappingsFile(mappings)
require.NoError(t, err)
mappings = newMapping()
mappings.Kind = "not-policy-mapping"
err = validateMappingsFile(mappings)
require.ErrorContains(t, err, "file is not of kind policy-mapping: not-policy-mapping")
mappings = newMapping()
mappings.Version = "v2"
err = validateMappingsFile(mappings)
require.ErrorContains(t, err, "unsupported policy mapping file version: v2")
mappings = newMapping()
mappings.Rules[0].Pattern = ""
err = validateMappingsFile(mappings)
require.ErrorContains(t, err, "rule missing pattern")
mappings = newMapping()
mappings.Rules[0].PolicyID = ""
err = validateMappingsFile(mappings)
require.ErrorContains(t, err, "rule must have policy-id or replacement")
mappings = newMapping()
mappings.Rules[0].PolicyID = "docker-official-images"
mappings.Rules[0].Replacement = "docker.io/library/alpine"
err = validateMappingsFile(mappings)
require.ErrorContains(t, err, "rule cannot have both policy-id and replacement")
mappings = newMapping()
mappings.Policies[0].ID = ""
err = validateMappingsFile(mappings)
require.ErrorContains(t, err, "policy missing id")
mappings = newMapping()
mappings.Policies[0].Files = nil
err = validateMappingsFile(mappings)
require.ErrorContains(t, err, "policy missing files")
mappings = newMapping()
mappings.Policies[0].Files[0].Path = ""
err = validateMappingsFile(mappings)
require.ErrorContains(t, err, "file missing path")
// multiple errors
mappings.Policies[0].ID = ""
err = validateMappingsFile(mappings)
require.ErrorContains(t, err, "policy missing id: \nfile missing path: {}")
}

96
mapping/match.go Normal file
View File

@@ -0,0 +1,96 @@
/*
Copyright Docker attest 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.
*/
package mapping
import (
"fmt"
v1 "github.com/google/go-containerregistry/pkg/v1"
)
type matchType string
const (
MatchTypePolicy matchType = "policy"
MatchTypeMatchNoPolicy matchType = "match_no_policy"
MatchTypeNoMatch matchType = "no_match"
)
type PolicyMatch struct {
MatchType matchType
Policy *PolicyMapping
Rule *PolicyRule
MatchedName string
}
func (mappings *PolicyMappings) FindPolicyMatch(imageName string, platform *v1.Platform) (*PolicyMatch, error) {
if mappings == nil {
return &PolicyMatch{MatchType: MatchTypeNoMatch, MatchedName: imageName}, nil
}
return mappings.findPolicyMatchImpl(imageName, platform, make(map[*PolicyRule]bool))
}
func (mappings *PolicyMappings) findPolicyMatchImpl(imageName string, platform *v1.Platform, matched map[*PolicyRule]bool) (*PolicyMatch, error) {
for _, rule := range mappings.Rules {
if !rule.matchesPlatform(platform) {
continue
}
if rule.Pattern.MatchString(imageName) {
switch {
case rule.PolicyID == "" && rule.Replacement == "":
return nil, fmt.Errorf("rule %s has neither policy-id nor rewrite", rule.Pattern)
case rule.PolicyID != "" && rule.Replacement != "":
return nil, fmt.Errorf("rule %s has both policy-id and rewrite", rule.Pattern)
case rule.PolicyID != "":
policy := mappings.Policies[rule.PolicyID]
if policy != nil {
return &PolicyMatch{
MatchType: MatchTypePolicy,
Policy: policy,
Rule: rule,
MatchedName: imageName,
}, nil
}
return &PolicyMatch{
MatchType: MatchTypeMatchNoPolicy,
Rule: rule,
MatchedName: imageName,
}, nil
case rule.Replacement != "":
if matched[rule] {
return nil, fmt.Errorf("rewrite loop detected")
}
matched[rule] = true
imageName = rule.Pattern.ReplaceAllString(imageName, rule.Replacement)
return mappings.findPolicyMatchImpl(imageName, platform, matched)
}
}
}
return &PolicyMatch{MatchType: MatchTypeNoMatch}, nil
}
func (rule *PolicyRule) matchesPlatform(platform *v1.Platform) bool {
if len(rule.Platforms) == 0 {
return true
}
for i := range rule.Platforms {
if rule.Platforms[i].Equals(*platform) {
return true
}
}
return false
}

216
mapping/match_test.go Normal file
View File

@@ -0,0 +1,216 @@
/*
Copyright Docker attest 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.
*/
package mapping
import (
"path/filepath"
"testing"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestFindPolicyMatch(t *testing.T) {
defaultPlatform, err := v1.ParsePlatform("linux/amd64")
require.NoError(t, err)
testCases := []struct {
name string
imageName string
mappingDir string
expectError bool
expectLoadingError bool
expectedMatchType matchType
expectedPolicyID string
expectedImageName string
platform string
}{
{
name: "alpine",
mappingDir: "doi",
imageName: "docker.io/library/alpine",
expectedMatchType: MatchTypePolicy,
expectedPolicyID: "docker-official-images",
expectedImageName: "docker.io/library/alpine",
},
{
name: "no match",
mappingDir: "doi",
imageName: "docker.io/something/else",
expectedMatchType: MatchTypeNoMatch,
},
{
name: "match, no policy",
mappingDir: "local",
imageName: "docker.io/library/alpine",
expectedMatchType: MatchTypeMatchNoPolicy,
expectedImageName: "docker.io/library/alpine",
},
{
name: "simple rewrite",
mappingDir: "simple-rewrite",
imageName: "mycoolmirror.org/library/alpine",
expectedMatchType: MatchTypePolicy,
expectedPolicyID: "docker-official-images",
expectedImageName: "docker.io/library/alpine",
},
{
name: "rewrite no match",
mappingDir: "rewrite-to-no-match",
imageName: "mycoolmirror.org/library/alpine",
expectedMatchType: MatchTypeNoMatch,
},
{
name: "rewrite to match, no policy",
mappingDir: "rewrite-to-local",
imageName: "mycoolmirror.org/library/alpine",
expectedMatchType: MatchTypeMatchNoPolicy,
expectedImageName: "docker.io/library/alpine",
},
{
name: "multiple rewrites",
mappingDir: "rewrite-multiple",
imageName: "myevencoolermirror.org/library/alpine",
expectedMatchType: MatchTypePolicy,
expectedPolicyID: "docker-official-images",
expectedImageName: "docker.io/library/alpine",
},
{
name: "rewrite loop",
mappingDir: "rewrite-loop",
imageName: "yin/alpine",
expectError: true,
},
{
name: "alpine with platform",
mappingDir: "doi",
imageName: "docker.io/library/alpine",
platform: "linux/amd64",
expectedMatchType: MatchTypePolicy,
expectedPolicyID: "docker-official-images",
expectedImageName: "docker.io/library/alpine",
},
{
name: "alpine with platform",
mappingDir: "doi-platform",
imageName: "docker.io/library/alpine",
platform: "linux/amd64",
expectedMatchType: MatchTypePolicy,
expectedPolicyID: "docker-official-images",
expectedImageName: "docker.io/library/alpine",
},
{
name: "alpine with no matching platform",
mappingDir: "doi-platform",
imageName: "docker.io/library/alpine",
platform: "linux/arm64",
expectedMatchType: MatchTypeNoMatch,
expectedPolicyID: "docker-official-images",
},
{
name: "alpine with platform",
mappingDir: "doi-platform",
imageName: "docker.io/library/alpine",
platform: "linux/amd64",
expectedMatchType: MatchTypePolicy,
expectedPolicyID: "docker-official-images",
expectedImageName: "docker.io/library/alpine",
},
{
name: "alpine with invalid platform in mapping",
mappingDir: "doi-platform-broken",
imageName: "docker.io/library/alpine",
platform: "linux/amd64",
expectLoadingError: true,
},
{
name: "firefox with > 1 platforms in policy",
mappingDir: "doi-platform",
imageName: "docker.io/mozilla/firefox",
platform: "linux/arm64",
expectedMatchType: MatchTypePolicy,
expectedPolicyID: "docker-official-images",
expectedImageName: "docker.io/mozilla/firefox",
},
{
name: "firefox with > 1 platforms in policy (no match)",
mappingDir: "doi-platform",
imageName: "docker.io/mozilla/firefox",
platform: "macOs/arm64",
expectedMatchType: MatchTypeNoMatch,
expectedPolicyID: "docker-official-images",
},
{
name: "rewrite and platform",
mappingDir: "doi-platform",
imageName: "mycoolmirror.org/library/alpine",
platform: "linux/amd64",
expectedMatchType: MatchTypePolicy,
expectedPolicyID: "docker-official-images",
expectedImageName: "docker.io/library/alpine",
},
{
name: "rewrite and platform mismatch",
mappingDir: "doi-platform",
imageName: "mycoolmirror.org/library/alpine",
platform: "macOs/amd64",
expectedMatchType: MatchTypeNoMatch,
expectedPolicyID: "docker-official-images",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
mappings, err := LoadLocalMappings(filepath.Join("testdata", "mappings", tc.mappingDir))
if tc.expectLoadingError {
require.Error(t, err)
return
}
require.NoError(t, err)
platform := defaultPlatform
if tc.platform != "" {
platform, err = v1.ParsePlatform(tc.platform)
require.NoError(t, err)
}
match, err := mappings.FindPolicyMatch(tc.imageName, platform)
if tc.expectError {
require.Error(t, err)
// TODO: check error matches expected error message
return
}
require.NoError(t, err)
assert.Equal(t, tc.expectedMatchType, match.MatchType)
if match.MatchType == MatchTypePolicy {
if assert.NotNil(t, match.Policy) {
assert.Equal(t, tc.expectedPolicyID, match.Policy.ID)
}
}
if match.MatchType == MatchTypeMatchNoPolicy || match.MatchType == MatchTypePolicy {
assert.Equal(t, tc.expectedImageName, match.MatchedName)
}
})
}
}

View File

@@ -0,0 +1,11 @@
version: v1
kind: policy-mapping
policies:
- id: docker-official-images
description: Docker Official Images
files:
- path: doi/policy.rego
rules:
- pattern: "^docker[.]io/library/(.*)$"
platforms: ["linux/amd64/broken/platform/spec/1.0:foobar"]
policy-id: docker-official-images

View File

@@ -0,0 +1,17 @@
version: v1
kind: policy-mapping
policies:
- id: docker-official-images
description: Docker Official Images
files:
- path: doi/policy.rego
rules:
- pattern: "^docker[.]io/library/(.*)$"
platforms: ["linux/amd64"]
policy-id: docker-official-images
- pattern: "^docker.io/mozilla/(.*)$"
platforms: ["linux/amd64", "linux/arm64"]
policy-id: docker-official-images
- pattern: "^mycoolmirror[.]org/library/(.*)$"
platforms: ["linux/amd64"]
rewrite: "docker.io/library/$1"

74
mapping/types.go Normal file
View File

@@ -0,0 +1,74 @@
/*
Copyright Docker attest 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.
*/
package mapping
import (
"regexp"
v1 "github.com/google/go-containerregistry/pkg/v1"
)
type policyMappingsFile struct {
Version string `json:"version"`
Kind string `json:"kind"`
Policies []*PolicyMapping `json:"policies"`
Rules []*policyRuleFile `json:"rules"`
}
type policyRuleFile struct {
Pattern string `json:"pattern"`
Platforms []string `json:"platforms"`
PolicyID string `json:"policy-id"`
Replacement string `json:"rewrite"`
}
type PolicyMappings struct {
Version string
Kind string
Policies map[string]*PolicyMapping
Rules []*PolicyRule
}
type AttestationStyle string
const (
AttestationStyleAttached AttestationStyle = "attached"
AttestationStyleReferrers AttestationStyle = "referrers"
)
type PolicyMapping struct {
ID string `json:"id"`
Description string `json:"description"`
Files []PolicyMappingFile `json:"files"`
Attestations *AttestationConfig `json:"attestations"`
}
type AttestationConfig struct {
Style AttestationStyle `json:"style"`
Repo string `json:"repo"`
}
type PolicyMappingFile struct {
Path string `json:"path"`
}
type PolicyRule struct {
Pattern *regexp.Regexp
PolicyID string
Replacement string
Platforms []*v1.Platform
}

2
mirror/README.md Normal file
View File

@@ -0,0 +1,2 @@
## mirror
This package contains components to mirror TUF metadata and targets to OCI.

View File

@@ -1,25 +1,42 @@
/*
Copyright Docker attest 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.
*/
package mirror_test
import (
"context"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/docker/attest/internal/embed"
"github.com/docker/attest/pkg/mirror"
"github.com/docker/attest/pkg/tuf"
"github.com/docker/attest/mirror"
"github.com/docker/attest/oci"
"github.com/docker/attest/tuf"
v1 "github.com/google/go-containerregistry/pkg/v1"
)
type TufMirrorOutput struct {
metadata v1.Image
delegatedMetadata []*mirror.MirrorImage
targets []*mirror.MirrorImage
delegatedTargets []*mirror.MirrorIndex
delegatedMetadata []*mirror.Image
targets []*mirror.Image
delegatedTargets []*mirror.Index
}
func ExampleNewTufMirror() {
func ExampleNewTUFMirror() {
home, err := os.UserHomeDir()
if err != nil {
panic(err)
@@ -29,7 +46,8 @@ func ExampleNewTufMirror() {
// configure TUF mirror
metadataURI := "https://docker.github.io/tuf-staging/metadata"
targetsURI := "https://docker.github.io/tuf-staging/targets"
m, err := mirror.NewTufMirror(embed.RootStaging.Data, tufOutputPath, metadataURI, targetsURI, tuf.NewMockVersionChecker())
ctx := context.Background()
m, err := mirror.NewTUFMirror(ctx, tuf.DockerTUFRootStaging.Data, tufOutputPath, metadataURI, targetsURI, tuf.NewMockVersionChecker())
if err != nil {
panic(err)
}
@@ -46,7 +64,7 @@ func ExampleNewTufMirror() {
}
// create targets manifest
targets, err := m.GetTufTargetMirrors()
targets, err := m.GetTUFTargetMirrors()
if err != nil {
panic(err)
}
@@ -64,7 +82,7 @@ func ExampleNewTufMirror() {
}
// push metadata and targets to registry (optional)
err = mirrorToRegistry(mirrorOutput)
err = mirrorToRegistry(ctx, mirrorOutput)
if err != nil {
panic(err)
}
@@ -77,10 +95,10 @@ func ExampleNewTufMirror() {
}
}
func mirrorToRegistry(o *TufMirrorOutput) error {
func mirrorToRegistry(ctx context.Context, o *TufMirrorOutput) error {
// push metadata to registry
metadataRepo := "registry-1.docker.io/docker/tuf-metadata:latest"
err := mirror.PushImageToRegistry(o.metadata, metadataRepo)
err := oci.PushImageToRegistry(ctx, o.metadata, metadataRepo)
if err != nil {
return err
}
@@ -91,7 +109,7 @@ func mirrorToRegistry(o *TufMirrorOutput) error {
return fmt.Errorf("failed to get repo without tag: %s", metadataRepo)
}
imageName := fmt.Sprintf("%s:%s", repo, metadata.Tag)
err = mirror.PushImageToRegistry(metadata.Image, imageName)
err = oci.PushImageToRegistry(ctx, metadata.Image, imageName)
if err != nil {
return err
}
@@ -101,7 +119,7 @@ func mirrorToRegistry(o *TufMirrorOutput) error {
targetsRepo := "registry-1.docker.io/docker/tuf-targets"
for _, target := range o.targets {
imageName := fmt.Sprintf("%s:%s", targetsRepo, target.Tag)
err = mirror.PushImageToRegistry(target.Image, imageName)
err = oci.PushImageToRegistry(ctx, target.Image, imageName)
if err != nil {
return err
}
@@ -109,7 +127,7 @@ func mirrorToRegistry(o *TufMirrorOutput) error {
// push delegated targets to registry
for _, target := range o.delegatedTargets {
imageName := fmt.Sprintf("%s:%s", targetsRepo, target.Tag)
err = mirror.PushIndexToRegistry(target.Index, imageName)
err = oci.PushIndexToRegistry(ctx, target.Index, imageName)
if err != nil {
return err
}
@@ -119,14 +137,14 @@ func mirrorToRegistry(o *TufMirrorOutput) error {
func mirrorToLocal(o *TufMirrorOutput, outputPath string) error {
// output metadata to local directory
err := mirror.SaveImageAsOCILayout(o.metadata, outputPath)
err := oci.SaveImageAsOCILayout(o.metadata, outputPath)
if err != nil {
return err
}
// output delegated metadata to local directory
for _, metadata := range o.delegatedMetadata {
path := filepath.Join(outputPath, metadata.Tag)
err = mirror.SaveImageAsOCILayout(metadata.Image, path)
err = oci.SaveImageAsOCILayout(metadata.Image, path)
if err != nil {
return err
}
@@ -135,7 +153,7 @@ func mirrorToLocal(o *TufMirrorOutput, outputPath string) error {
// output top-level targets to local directory
for _, target := range o.targets {
path := filepath.Join(outputPath, target.Tag)
err = mirror.SaveImageAsOCILayout(target.Image, path)
err = oci.SaveImageAsOCILayout(target.Image, path)
if err != nil {
return err
}
@@ -143,7 +161,7 @@ func mirrorToLocal(o *TufMirrorOutput, outputPath string) error {
// output delegated targets to local directory
for _, target := range o.delegatedTargets {
path := filepath.Join(outputPath, target.Tag)
err = mirror.SaveIndexAsOCILayout(target.Index, path)
err = oci.SaveIndexAsOCILayout(target.Index, path)
if err != nil {
return err
}

View File

@@ -1,9 +1,26 @@
/*
Copyright Docker attest 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.
*/
package mirror
import (
"fmt"
"strconv"
"github.com/docker/attest/oci"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/empty"
"github.com/google/go-containerregistry/pkg/v1/mutate"
@@ -16,9 +33,9 @@ import (
// TUF root metadata
// -----------------
// GetMetadataManifest returns an image with TUF root metadata as layers
func (m *TufMirror) GetMetadataManifest(metadataURL string) (v1.Image, error) {
metadata, err := m.getTufMetadataMirror(metadataURL)
// GetMetadataManifest returns an image with TUF root metadata as layers.
func (m *TUFMirror) GetMetadataManifest(metadataURL string) (*oci.EmptyConfigImage, error) {
metadata, err := m.getMetadataMirror(metadataURL)
if err != nil {
return nil, fmt.Errorf("failed to get metadata: %w", err)
}
@@ -26,19 +43,19 @@ func (m *TufMirror) GetMetadataManifest(metadataURL string) (v1.Image, error) {
if err != nil {
return nil, fmt.Errorf("failed to build metadata manifest: %w", err)
}
return manifest, nil
return &oci.EmptyConfigImage{Image: manifest}, nil
}
// getTufMetadataMirror returns a TufMetadata struct with TUF metadata as map of file names to bytes
func (m *TufMirror) getTufMetadataMirror(metadataURL string) (*TufMetadata, error) {
trustedMetadata := m.TufClient.GetMetadata()
// getMetadataMirror returns a TufMetadata struct with TUF metadata as map of file names to bytes.
func (m *TUFMirror) getMetadataMirror(metadataURL string) (*TUFMetadata, error) {
trustedMetadata := m.TUFClient.GetMetadata()
rootMetadata := map[string][]byte{}
rootVersion := trustedMetadata.Root.Signed.Version
// get the previous versions of root metadata if any
if rootVersion != 1 {
var err error
rootMetadata, err = m.TufClient.GetPriorRoots(metadataURL)
rootMetadata, err = m.TUFClient.GetPriorRoots(metadataURL)
if err != nil {
return nil, fmt.Errorf("failed to get prior root metadata: %w", err)
}
@@ -69,7 +86,7 @@ func (m *TufMirror) getTufMetadataMirror(metadataURL string) (*TufMetadata, erro
snapshotVersion = strconv.FormatInt(trustedMetadata.Snapshot.Signed.Version, 10)
targetsVersion = strconv.FormatInt(trustedMetadata.Targets[metadata.TARGETS].Signed.Version, 10)
}
return &TufMetadata{
return &TUFMetadata{
Root: rootMetadata,
Snapshot: map[string][]byte{nameFromRole(metadata.SNAPSHOT, snapshotVersion): snapshotBytes},
Targets: map[string][]byte{nameFromRole(metadata.TARGETS, targetsVersion): targetsBytes},
@@ -77,12 +94,12 @@ func (m *TufMirror) getTufMetadataMirror(metadataURL string) (*TufMetadata, erro
}, nil
}
// buildMetadataManifest returns an OCI image with TUF metadata as layers with annotations
func (m *TufMirror) buildMetadataManifest(metadata *TufMetadata) (v1.Image, error) {
// buildMetadataManifest returns an OCI image with TUF metadata as layers with annotations.
func (m *TUFMirror) buildMetadataManifest(metadata *TUFMetadata) (v1.Image, error) {
img := empty.Image
img = mutate.MediaType(img, types.OCIManifestSchema1)
img = mutate.ConfigMediaType(img, types.OCIConfigJSON)
for _, role := range TufRoles {
for _, role := range TUFRoles {
layers, err := m.makeRoleLayers(role, metadata)
if err != nil {
return nil, fmt.Errorf("failed to make role layer: %w", err)
@@ -95,8 +112,8 @@ func (m *TufMirror) buildMetadataManifest(metadata *TufMetadata) (v1.Image, erro
return img, nil
}
// makeRoleLayers returns a list of layers for a given TUF role
func (m *TufMirror) makeRoleLayers(role TufRole, tufMetadata *TufMetadata) ([]mutate.Addendum, error) {
// makeRoleLayers returns a list of layers for a given TUF role.
func (m *TUFMirror) makeRoleLayers(role TUFRole, tufMetadata *TUFMetadata) ([]mutate.Addendum, error) {
var layers []mutate.Addendum
ann := map[string]string{tufFileAnnotation: ""}
switch role {
@@ -115,8 +132,8 @@ func (m *TufMirror) makeRoleLayers(role TufRole, tufMetadata *TufMetadata) ([]mu
return layers, nil
}
// annotatedMetaLayers returns a list of layers with annotations for each TUF metadata file
func (m *TufMirror) annotatedMetaLayers(meta map[string][]byte) []mutate.Addendum {
// annotatedMetaLayers returns a list of layers with annotations for each TUF metadata file.
func (m *TUFMirror) annotatedMetaLayers(meta map[string][]byte) []mutate.Addendum {
var layers []mutate.Addendum
for name, data := range meta {
ann := map[string]string{tufFileAnnotation: name}
@@ -129,8 +146,8 @@ func (m *TufMirror) annotatedMetaLayers(meta map[string][]byte) []mutate.Addendu
// TUF delegated targets metadata
// ------------------------------
// GetDelegatedMetadataMirrors returns a list of mirrors (image/tag pairs) for each delegated targets role metadata
func (m *TufMirror) GetDelegatedMetadataMirrors() ([]*MirrorImage, error) {
// GetDelegatedMetadataMirrors returns a list of mirrors (image/tag pairs) for each delegated targets role metadata.
func (m *TUFMirror) GetDelegatedMetadataMirrors() ([]*Image, error) {
// get current delegated targets metadata
delegatedTargets, err := m.getDelegatedTargetsMetadata()
if err != nil {
@@ -143,12 +160,12 @@ func (m *TufMirror) GetDelegatedMetadataMirrors() ([]*MirrorImage, error) {
return mirror, nil
}
// getDelegatedTargetsMetadata returns delegated targets metadata as a list of DelegatedTargetMetadata (role name and data)
func (m *TufMirror) getDelegatedTargetsMetadata() ([]DelegatedTargetMetadata, error) {
// getDelegatedTargetsMetadata returns delegated targets metadata as a list of DelegatedTargetMetadata (role name and data).
func (m *TUFMirror) getDelegatedTargetsMetadata() ([]DelegatedTargetMetadata, error) {
var delegatedTargets []DelegatedTargetMetadata
md := m.TufClient.GetMetadata()
md := m.TUFClient.GetMetadata()
for _, role := range md.Targets[metadata.TARGETS].Signed.Delegations.Roles {
roleMetadata, err := m.TufClient.LoadDelegatedTargets(role.Name, metadata.TARGETS)
roleMetadata, err := m.TUFClient.LoadDelegatedTargets(role.Name, metadata.TARGETS)
if err != nil {
return nil, fmt.Errorf("failed to get delegated role metadata: %w", err)
}
@@ -170,9 +187,9 @@ func (m *TufMirror) getDelegatedTargetsMetadata() ([]DelegatedTargetMetadata, er
return delegatedTargets, nil
}
// buildDelegatedMetadataManifests returns a list of mirrors (image/tag pairs) for each delegated target role metadata
func (m *TufMirror) buildDelegatedMetadataManifests(delegated []DelegatedTargetMetadata) ([]*MirrorImage, error) {
manifests := []*MirrorImage{}
// buildDelegatedMetadataManifests returns a list of mirrors (image/tag pairs) for each delegated target role metadata.
func (m *TUFMirror) buildDelegatedMetadataManifests(delegated []DelegatedTargetMetadata) ([]*Image, error) {
manifests := []*Image{}
for _, role := range delegated {
img := empty.Image
img = mutate.MediaType(img, types.OCIManifestSchema1)
@@ -183,7 +200,7 @@ func (m *TufMirror) buildDelegatedMetadataManifests(delegated []DelegatedTargetM
if err != nil {
return nil, fmt.Errorf("failed to append delegated targets layer to image: %w", err)
}
manifests = append(manifests, &MirrorImage{Image: img, Tag: role.Name})
manifests = append(manifests, &Image{Image: &oci.EmptyConfigImage{Image: img}, Tag: role.Name})
}
return manifests, nil
}

View File

@@ -1,6 +1,23 @@
/*
Copyright Docker attest 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.
*/
package mirror
import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
@@ -9,22 +26,26 @@ import (
"strings"
"testing"
"github.com/docker/attest/internal/embed"
"github.com/docker/attest/internal/test"
"github.com/docker/attest/pkg/tuf"
"github.com/docker/attest/tuf"
"github.com/stretchr/testify/assert"
"github.com/theupdateframework/go-tuf/v2/metadata"
)
const (
metadataPath = "/metadata"
targetsPath = "/targets"
)
func TestGetTufMetadataMirror(t *testing.T) {
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "..", "test", "testdata", "tuf", "test-repo"))))
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "test", "testdata", "tuf", "test-repo"))))
defer server.Close()
path := test.CreateTempDir(t, "", "tuf_temp")
m, err := NewTufMirror(embed.RootDev.Data, path, server.URL+"/metadata", server.URL+"/targets", tuf.NewMockVersionChecker())
m, err := NewTUFMirror(context.Background(), tuf.DockerTUFRootDev.Data, path, server.URL+metadataPath, server.URL+targetsPath, tuf.NewMockVersionChecker())
assert.NoError(t, err)
tufMetadata, err := m.getTufMetadataMirror(server.URL + "/metadata")
tufMetadata, err := m.getMetadataMirror(server.URL + metadataPath)
assert.NoError(t, err)
// check that all roles are not empty
@@ -35,14 +56,14 @@ func TestGetTufMetadataMirror(t *testing.T) {
}
func TestGetMetadataManifest(t *testing.T) {
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "..", "test", "testdata", "tuf", "test-repo"))))
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "test", "testdata", "tuf", "test-repo"))))
defer server.Close()
path := test.CreateTempDir(t, "", "tuf_temp")
m, err := NewTufMirror(embed.RootDev.Data, path, server.URL+"/metadata", server.URL+"/targets", tuf.NewMockVersionChecker())
m, err := NewTUFMirror(context.Background(), tuf.DockerTUFRootDev.Data, path, server.URL+metadataPath, server.URL+targetsPath, tuf.NewMockVersionChecker())
assert.NoError(t, err)
img, err := m.GetMetadataManifest(server.URL + "/metadata")
img, err := m.GetMetadataManifest(server.URL + metadataPath)
assert.NoError(t, err)
assert.NotNil(t, img)
@@ -74,11 +95,11 @@ func TestGetMetadataManifest(t *testing.T) {
}
func TestGetDelegatedMetadataMirrors(t *testing.T) {
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "..", "test", "testdata", "tuf", "test-repo"))))
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "test", "testdata", "tuf", "test-repo"))))
defer server.Close()
path := test.CreateTempDir(t, "", "tuf_temp")
m, err := NewTufMirror(embed.RootDev.Data, path, server.URL+"/metadata", server.URL+"/targets", tuf.NewMockVersionChecker())
m, err := NewTUFMirror(context.Background(), tuf.DockerTUFRootDev.Data, path, server.URL+metadataPath, server.URL+targetsPath, tuf.NewMockVersionChecker())
assert.NoError(t, err)
delegations, err := m.GetDelegatedMetadataMirrors()

35
mirror/mirror.go Normal file
View File

@@ -0,0 +1,35 @@
/*
Copyright Docker attest 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.
*/
package mirror
import (
"context"
"fmt"
"github.com/docker/attest/tuf"
)
func NewTUFMirror(ctx context.Context, root []byte, tufPath, metadataURL, targetsURL string, versionChecker tuf.VersionChecker) (*TUFMirror, error) {
if root == nil {
root = tuf.DockerTUFRootDefault.Data
}
tufClient, err := tuf.NewClient(ctx, &tuf.ClientOptions{InitialRoot: root, LocalStorageDir: tufPath, MetadataSource: metadataURL, TargetsSource: targetsURL, VersionChecker: versionChecker})
if err != nil {
return nil, fmt.Errorf("failed to create TUF client: %w", err)
}
return &TUFMirror{TUFClient: tufClient, tufPath: tufPath, metadataURL: metadataURL, targetsURL: targetsURL}, nil
}

View File

@@ -1,3 +1,19 @@
/*
Copyright Docker attest 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.
*/
package mirror
import (
@@ -5,6 +21,7 @@ import (
"path/filepath"
"strings"
"github.com/docker/attest/oci"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/empty"
"github.com/google/go-containerregistry/pkg/v1/mutate"
@@ -13,16 +30,16 @@ import (
"github.com/theupdateframework/go-tuf/v2/metadata"
)
// GetTufTargetMirrors returns a list of top-level target files as MirrorImages (image with tag)
func (m *TufMirror) GetTufTargetMirrors() ([]*MirrorImage, error) {
targetMirrors := []*MirrorImage{}
md := m.TufClient.GetMetadata()
// GetTUFTargetMirrors returns a list of top-level target files as MirrorImages (image with tag).
func (m *TUFMirror) GetTUFTargetMirrors() ([]*Image, error) {
targetMirrors := []*Image{}
md := m.TUFClient.GetMetadata()
// for each top-level target file, create an image with the target file as a layer
targets := md.Targets[metadata.TARGETS].Signed.Targets
for _, t := range targets {
// download target file
_, data, err := m.TufClient.DownloadTarget(t.Path, filepath.Join(m.tufPath, "download"))
file, err := m.TUFClient.DownloadTarget(t.Path, filepath.Join(m.tufPath, "download"))
if err != nil {
return nil, fmt.Errorf("failed to download target %s: %w", t.Path, err)
}
@@ -37,21 +54,21 @@ func (m *TufMirror) GetTufTargetMirrors() ([]*MirrorImage, error) {
}
name := hash.String() + "." + t.Path
ann := map[string]string{tufFileAnnotation: name}
layer := mutate.Addendum{Layer: static.NewLayer(data, tufTargetMediaType), Annotations: ann}
layer := mutate.Addendum{Layer: static.NewLayer(file.Data, tufTargetMediaType), Annotations: ann}
img, err = mutate.Append(img, layer)
if err != nil {
return nil, fmt.Errorf("failed to append role layer to image: %w", err)
}
targetMirrors = append(targetMirrors, &MirrorImage{Image: img, Tag: name})
targetMirrors = append(targetMirrors, &Image{Image: &oci.EmptyConfigImage{Image: img}, Tag: name})
}
return targetMirrors, nil
}
// GetDelegatedTargetMirrors returns a list of delegated target files as MirrorIndexes (image index with tag)
// each image in the index contains a delegated target file
func (m *TufMirror) GetDelegatedTargetMirrors() ([]*MirrorIndex, error) {
mirror := []*MirrorIndex{}
md := m.TufClient.GetMetadata()
// each image in the index contains a delegated target file.
func (m *TUFMirror) GetDelegatedTargetMirrors() ([]*Index, error) {
mirror := []*Index{}
md := m.TUFClient.GetMetadata()
// for each delegated role, create an image index with target files as images
roles := md.Targets[metadata.TARGETS].Signed.Delegations.Roles
@@ -60,7 +77,7 @@ func (m *TufMirror) GetDelegatedTargetMirrors() ([]*MirrorIndex, error) {
index := v1.ImageIndex(empty.Index)
// get delegated targets metadata for role
roleMeta, err := m.TufClient.LoadDelegatedTargets(role.Name, metadata.TARGETS)
roleMeta, err := m.TUFClient.LoadDelegatedTargets(role.Name, metadata.TARGETS)
if err != nil {
return nil, fmt.Errorf("failed to load delegated targets metadata: %w", err)
}
@@ -68,7 +85,7 @@ func (m *TufMirror) GetDelegatedTargetMirrors() ([]*MirrorIndex, error) {
// for each target file, create an image with the target file as a layer
for _, target := range roleMeta.Signed.Targets {
// download target file
_, data, err := m.TufClient.DownloadTarget(target.Path, filepath.Join(m.tufPath, "download"))
file, err := m.TUFClient.DownloadTarget(target.Path, filepath.Join(m.tufPath, "download"))
if err != nil {
return nil, fmt.Errorf("failed to download target %s: %w", target.Path, err)
}
@@ -88,14 +105,15 @@ func (m *TufMirror) GetDelegatedTargetMirrors() ([]*MirrorIndex, error) {
}
name := hash.String() + "." + filename
ann := map[string]string{tufFileAnnotation: name}
layer := mutate.Addendum{Layer: static.NewLayer(data, tufTargetMediaType), Annotations: ann}
layer := mutate.Addendum{Layer: static.NewLayer(file.Data, tufTargetMediaType), Annotations: ann}
img, err = mutate.Append(img, layer)
if err != nil {
return nil, fmt.Errorf("failed to append role layer to image: %w", err)
}
emptyConfigImage := &oci.EmptyConfigImage{Image: img}
// append image to index with annotation
index = mutate.AppendManifests(index, mutate.IndexAddendum{
Add: img,
Add: emptyConfigImage,
Descriptor: v1.Descriptor{
Annotations: map[string]string{
tufFileAnnotation: fmt.Sprintf("%s/%s", subdir, name),
@@ -103,7 +121,7 @@ func (m *TufMirror) GetDelegatedTargetMirrors() ([]*MirrorIndex, error) {
},
})
}
mirror = append(mirror, &MirrorIndex{Index: index, Tag: role.Name})
mirror = append(mirror, &Index{Index: index, Tag: role.Name})
}
return mirror, nil
}

View File

@@ -1,6 +1,23 @@
/*
Copyright Docker attest 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.
*/
package mirror
import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
@@ -8,9 +25,8 @@ import (
"strings"
"testing"
"github.com/docker/attest/internal/embed"
"github.com/docker/attest/internal/test"
"github.com/docker/attest/pkg/tuf"
"github.com/docker/attest/tuf"
"github.com/stretchr/testify/assert"
)
@@ -23,14 +39,14 @@ type Layers struct {
}
func TestGetTufTargetsMirror(t *testing.T) {
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "..", "test", "testdata", "tuf", "test-repo"))))
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "test", "testdata", "tuf", "test-repo"))))
defer server.Close()
path := test.CreateTempDir(t, "", "tuf_temp")
m, err := NewTufMirror(embed.RootDev.Data, path, server.URL+"/metadata", server.URL+"/targets", tuf.NewMockVersionChecker())
m, err := NewTUFMirror(context.Background(), tuf.DockerTUFRootDev.Data, path, server.URL+metadataPath, server.URL+targetsPath, tuf.NewMockVersionChecker())
assert.NoError(t, err)
targets, err := m.GetTufTargetMirrors()
targets, err := m.GetTUFTargetMirrors()
assert.NoError(t, err)
assert.Greater(t, len(targets), 0)
@@ -57,24 +73,24 @@ func TestGetTufTargetsMirror(t *testing.T) {
}
func TestTargetDelegationMetadata(t *testing.T) {
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "..", "test", "testdata", "tuf", "test-repo"))))
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "test", "testdata", "tuf", "test-repo"))))
defer server.Close()
path := test.CreateTempDir(t, "", "tuf_temp")
tm, err := NewTufMirror(embed.RootDev.Data, path, server.URL+"/metadata", server.URL+"/targets", tuf.NewMockVersionChecker())
tm, err := NewTUFMirror(context.Background(), tuf.DockerTUFRootDev.Data, path, server.URL+metadataPath, server.URL+targetsPath, tuf.NewMockVersionChecker())
assert.NoError(t, err)
targets, err := tm.TufClient.LoadDelegatedTargets("test-role", "targets")
targets, err := tm.TUFClient.LoadDelegatedTargets("test-role", "targets")
assert.NoError(t, err)
assert.Greater(t, len(targets.Signed.Targets), 0)
}
func TestGetDelegatedTargetMirrors(t *testing.T) {
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "..", "test", "testdata", "tuf", "test-repo"))))
server := httptest.NewServer(http.FileServer(http.Dir(filepath.Join("..", "test", "testdata", "tuf", "test-repo"))))
defer server.Close()
path := test.CreateTempDir(t, "", "tuf_temp")
m, err := NewTufMirror(embed.RootDev.Data, path, server.URL+"/metadata", server.URL+"/targets", tuf.NewMockVersionChecker())
m, err := NewTUFMirror(context.Background(), tuf.DockerTUFRootDev.Data, path, server.URL+metadataPath, server.URL+targetsPath, tuf.NewMockVersionChecker())
assert.NoError(t, err)
mirrors, err := m.GetDelegatedTargetMirrors()

66
mirror/types.go Normal file
View File

@@ -0,0 +1,66 @@
/*
Copyright Docker attest 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.
*/
package mirror
import (
"github.com/docker/attest/oci"
"github.com/docker/attest/tuf"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/theupdateframework/go-tuf/v2/metadata"
)
const (
DefaultMetadataURL = "https://docker.github.io/tuf/metadata"
DefaultTargetsURL = "https://docker.github.io/tuf/targets"
tufMetadataMediaType = "application/vnd.tuf.metadata+json"
tufTargetMediaType = "application/vnd.tuf.target"
tufFileAnnotation = "tuf.io/filename"
)
type TUFRole string
var TUFRoles = []TUFRole{metadata.ROOT, metadata.SNAPSHOT, metadata.TARGETS, metadata.TIMESTAMP}
type TUFMetadata struct {
Root map[string][]byte
Snapshot map[string][]byte
Targets map[string][]byte
Timestamp []byte
}
type DelegatedTargetMetadata struct {
Name string
Version string
Data []byte
}
type Image struct {
Image *oci.EmptyConfigImage
Tag string
}
type Index struct {
Index v1.ImageIndex
Tag string
}
type TUFMirror struct {
TUFClient *tuf.Client
tufPath string
metadataURL string
targetsURL string
}

2
oci/README.md Normal file
View File

@@ -0,0 +1,2 @@
## oci
This package is for generic OCI components. For attestation specific components see the `attestation` package.

39
oci/authn.go Normal file
View File

@@ -0,0 +1,39 @@
/*
Copyright Docker attest 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.
*/
package oci
import (
"io"
ecr "github.com/awslabs/amazon-ecr-credential-helper/ecr-login"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/v1/google"
"github.com/google/go-containerregistry/pkg/v1/remote"
)
func MultiKeychainOption() remote.Option {
return remote.WithAuthFromKeychain(MultiKeychainAll())
}
func MultiKeychainAll() authn.Keychain {
// Create a multi-keychain that will use the default Docker, Google, or ECR keychain
return authn.NewMultiKeychain(
authn.DefaultKeychain,
google.Keychain,
authn.NewKeychainFromHelper(ecr.NewECRHelper(ecr.WithLogger(io.Discard))),
)
}

49
oci/authn_test.go Normal file
View File

@@ -0,0 +1,49 @@
//go:build e2e
/*
Copyright Docker attest 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.
*/
package oci_test
import (
"context"
"testing"
"github.com/docker/attest/internal/test"
"github.com/docker/attest/oci"
"github.com/stretchr/testify/require"
)
func TestRegistryAuth(t *testing.T) {
attIdx, err := oci.IndexFromPath(test.UnsignedTestIndex(".."))
require.NoError(t, err)
// test cases for ecr, gcr and dockerhub
testCases := []struct {
Image string
}{
{Image: "175142243308.dkr.ecr.us-east-1.amazonaws.com/e2e-test-image:latest"},
{Image: "docker/image-signer-verifier-test:latest"},
}
ctx := context.Background()
for _, tc := range testCases {
t.Run(tc.Image, func(t *testing.T) {
err := oci.PushIndexToRegistry(ctx, attIdx.Index, tc.Image)
require.NoError(t, err)
_, err = oci.IndexFromRemote(ctx, tc.Image)
require.NoError(t, err)
})
}
}

View File

@@ -1,25 +1,38 @@
/*
Copyright Docker attest 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.
*/
package oci
import (
"context"
"encoding/json"
"fmt"
"strings"
"github.com/containerd/platforms"
"github.com/distribution/reference"
"github.com/docker/attest/pkg/attestation"
att "github.com/docker/attest/pkg/attestation"
"github.com/docker/attest/useragent"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/package-url/packageurl-go"
"github.com/pkg/errors"
)
// ParsePlatform parses the provided platform string or attempts to obtain
// the platform of the current host system
// the platform of the current host system.
func ParsePlatform(platformStr string) (*v1.Platform, error) {
if platformStr == "" {
cdp := platforms.Normalize(platforms.DefaultSpec())
@@ -31,14 +44,17 @@ func ParsePlatform(platformStr string) (*v1.Platform, error) {
Architecture: cdp.Architecture,
Variant: cdp.Variant,
}, nil
} else {
return v1.ParsePlatform(platformStr)
}
return v1.ParsePlatform(platformStr)
}
func WithOptions(ctx context.Context, platform *v1.Platform) []remote.Option {
// prepare options
options := []remote.Option{MultiKeychainOption(), remote.WithTransport(HttpTransport()), remote.WithContext(ctx)}
options := []remote.Option{
MultiKeychainOption(),
remote.WithContext(ctx),
remote.WithUserAgent(useragent.Get(ctx)),
}
// add in platform into remote Get operation; this might conflict with an explicit digest, but we are trying anyway
if platform != nil {
@@ -47,61 +63,18 @@ func WithOptions(ctx context.Context, platform *v1.Platform) []remote.Option {
return options
}
func ExtractEnvelopes(manifest *attestation.AttestationManifest, predicateType string) ([]*att.Envelope, error) {
var envs []*att.Envelope
dsseMediaType, err := attestation.DSSEMediaType(predicateType)
if err != nil {
return nil, fmt.Errorf("failed to get DSSE media type for predicate '%s': %w", predicateType, err)
}
for _, attestationLayer := range manifest.OriginalLayers {
mt, err := attestationLayer.Layer.MediaType()
if err != nil {
return nil, fmt.Errorf("failed to get layer media type: %w", err)
}
if string(mt) == dsseMediaType {
reader, err := attestationLayer.Layer.Uncompressed()
if err != nil {
return nil, fmt.Errorf("failed to get layer contents: %w", err)
}
defer reader.Close()
var env = new(att.Envelope)
err = json.NewDecoder(reader).Decode(&env)
if err != nil {
return nil, fmt.Errorf("failed to decode envelope: %w", err)
}
envs = append(envs, env)
}
}
return envs, nil
}
func imageDescriptor(ix *v1.IndexManifest, platform *v1.Platform) (*v1.Descriptor, error) {
for _, m := range ix.Manifests {
func ImageDescriptor(ix *v1.IndexManifest, platform *v1.Platform) (*v1.Descriptor, error) {
for i := range ix.Manifests {
m := &ix.Manifests[i]
if (m.MediaType == ocispec.MediaTypeImageManifest || m.MediaType == "application/vnd.docker.distribution.manifest.v2+json") && m.Platform.Equals(*platform) {
return &m, nil
return m, nil
}
}
return nil, errors.New(fmt.Sprintf("no image found for platform %v", platform))
return nil, fmt.Errorf("no image found for platform %v", platform)
}
func attestationDigestForDigest(ix *v1.IndexManifest, imageDigest string, attestType string) (string, error) {
for _, m := range ix.Manifests {
if v, ok := m.Annotations[att.DockerReferenceType]; ok && v == attestType {
if d, ok := m.Annotations[att.DockerReferenceDigest]; ok && d == imageDigest {
return m.Digest.String(), nil
}
}
}
return "", errors.New(fmt.Sprintf("no attestation found for image %s", imageDigest))
}
func RefToPURL(ref string, platform *v1.Platform) (string, bool, error) {
func RefToPURL(named reference.Named, platform *v1.Platform) (string, bool, error) {
var isCanonical bool
named, err := reference.ParseNormalizedNamed(ref)
if err != nil {
return "", false, fmt.Errorf("failed to parse ref %q: %w", ref, err)
}
var qualifiers []packageurl.Qualifier
if canonical, ok := named.(reference.Canonical); ok {
@@ -135,7 +108,7 @@ func RefToPURL(ref string, platform *v1.Platform) (string, bool, error) {
})
}
p := packageurl.NewPackageURL("docker", ns, name, version, qualifiers, "")
p := packageurl.NewPackageURL(packageurl.TypeDocker, ns, name, version, qualifiers, "")
return p.ToString(), isCanonical, nil
}
@@ -150,7 +123,7 @@ func SplitDigest(digest string) (common.DigestSet, error) {
}
func ReplaceTagInSpec(src *ImageSpec, digest v1.Hash) (*ImageSpec, error) {
newName, err := replaceTag(src.Identifier, digest)
newName, err := ReplaceTag(src.Identifier, digest)
if err != nil {
return nil, fmt.Errorf("failed to parse repo name: %w", err)
}
@@ -161,8 +134,8 @@ func ReplaceTagInSpec(src *ImageSpec, digest v1.Hash) (*ImageSpec, error) {
}, nil
}
// so that the index tag is replaced with a tag unique to the image digest and doesn't overwrite it
func replaceTag(image string, digest v1.Hash) (string, error) {
// so that the index tag is replaced with a tag unique to the image digest and doesn't overwrite it.
func ReplaceTag(image string, digest v1.Hash) (string, error) {
if strings.HasPrefix(image, LocalPrefix) {
return image, nil
}
@@ -172,3 +145,26 @@ func replaceTag(image string, digest v1.Hash) (string, error) {
}
return fmt.Sprintf("%s:%s-%s.att", notag, digest.Algorithm, digest.Hex), nil
}
func ReplaceDigestInSpec(src *ImageSpec, digest v1.Hash) (*ImageSpec, error) {
newName, err := replaceDigest(src.Identifier, digest)
if err != nil {
return nil, fmt.Errorf("failed to parse repo name: %w", err)
}
return &ImageSpec{
Identifier: newName,
Type: src.Type,
Platform: src.Platform,
}, nil
}
func replaceDigest(image string, digest v1.Hash) (string, error) {
if strings.HasPrefix(image, LocalPrefix) {
return image, nil
}
notag, err := WithoutTag(image)
if err != nil {
return "", nil
}
return fmt.Sprintf("%s@%s:%s", notag, digest.Algorithm, digest.Hex), nil
}

162
oci/oci_test.go Normal file
View File

@@ -0,0 +1,162 @@
/*
Copyright Docker attest 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.
*/
package oci_test
import (
"testing"
"github.com/distribution/reference"
"github.com/docker/attest/internal/test"
"github.com/docker/attest/oci"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/layout"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestRefToPurl(t *testing.T) {
arm, err := oci.ParsePlatform("arm64/linux")
require.NoError(t, err)
ref, err := reference.ParseNormalizedNamed("alpine")
require.NoError(t, err)
purl, canonical, err := oci.RefToPURL(ref, arm)
assert.NoError(t, err)
assert.Equal(t, "pkg:docker/alpine@latest?platform=arm64%2Flinux", purl)
assert.False(t, canonical)
ref, err = reference.ParseNormalizedNamed("alpine:123")
require.NoError(t, err)
purl, canonical, err = oci.RefToPURL(ref, arm)
assert.NoError(t, err)
assert.Equal(t, "pkg:docker/alpine@123?platform=arm64%2Flinux", purl)
assert.False(t, canonical)
ref, err = reference.ParseNormalizedNamed("google/alpine:123")
require.NoError(t, err)
purl, canonical, err = oci.RefToPURL(ref, arm)
assert.NoError(t, err)
assert.Equal(t, "pkg:docker/google/alpine@123?platform=arm64%2Flinux", purl)
assert.False(t, canonical)
ref, err = reference.ParseNormalizedNamed("library/alpine:123")
require.NoError(t, err)
purl, canonical, err = oci.RefToPURL(ref, arm)
assert.NoError(t, err)
assert.Equal(t, "pkg:docker/alpine@123?platform=arm64%2Flinux", purl)
assert.False(t, canonical)
ref, err = reference.ParseNormalizedNamed("docker.io/library/alpine:123")
require.NoError(t, err)
purl, canonical, err = oci.RefToPURL(ref, arm)
assert.NoError(t, err)
assert.Equal(t, "pkg:docker/alpine@123?platform=arm64%2Flinux", purl)
assert.False(t, canonical)
ref, err = reference.ParseNormalizedNamed("localhost:5001/library/alpine:123")
require.NoError(t, err)
purl, canonical, err = oci.RefToPURL(ref, arm)
assert.NoError(t, err)
assert.Equal(t, "pkg:docker/localhost%3A5001/library/alpine@123?platform=arm64%2Flinux", purl)
assert.False(t, canonical)
ref, err = reference.ParseNormalizedNamed("localhost:5001/alpine:123")
require.NoError(t, err)
purl, canonical, err = oci.RefToPURL(ref, arm)
assert.NoError(t, err)
assert.Equal(t, "pkg:docker/localhost%3A5001/alpine@123?platform=arm64%2Flinux", purl)
assert.False(t, canonical)
ref, err = reference.ParseNormalizedNamed("localhost:5001/alpine@sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b")
require.NoError(t, err)
purl, canonical, err = oci.RefToPURL(ref, arm)
assert.NoError(t, err)
assert.Equal(t, "pkg:docker/localhost%3A5001/alpine?digest=sha256%3Ac5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b&platform=arm64%2Flinux", purl)
assert.True(t, canonical)
}
// Test fix for https://github.com/docker/secure-artifacts-team-issues/issues/202
func TestImageDigestForPlatform(t *testing.T) {
idx, err := layout.ImageIndexFromPath(test.UnsignedTestIndex(".."))
assert.NoError(t, err)
idxm, err := idx.IndexManifest()
assert.NoError(t, err)
idxDescriptor := idxm.Manifests[0]
idxDigest := idxDescriptor.Digest
mfs, err := idx.ImageIndex(idxDigest)
assert.NoError(t, err)
mfs2, err := mfs.IndexManifest()
assert.NoError(t, err)
p, err := oci.ParsePlatform("linux/amd64")
assert.NoError(t, err)
desc, err := oci.ImageDescriptor(mfs2, p)
assert.NoError(t, err)
digest := desc.Digest.String()
assert.Equal(t, test.UnsignedLinuxAMD64ImageDigest, digest)
p, err = oci.ParsePlatform("linux/arm64")
assert.NoError(t, err)
desc, err = oci.ImageDescriptor(mfs2, p)
assert.NoError(t, err)
digest = desc.Digest.String()
assert.Equal(t, test.UnsignedLinuxArm64ImageDigest, digest)
}
func TestWithoutTag(t *testing.T) {
tc := []struct {
name string
expected string
}{
{name: "image:tag", expected: "index.docker.io/library/image"},
{name: "image", expected: "index.docker.io/library/image"},
{name: "image:sha256-digest.att", expected: "index.docker.io/library/image"},
{name: oci.RegistryPrefix + "image:tag", expected: oci.RegistryPrefix + "index.docker.io/library/image"},
{name: "image@sha256:166710df254975d4a6c4c407c315951c22753dcaa829e020a3fd5d18fff70dd2", expected: "index.docker.io/library/image"},
{name: oci.RegistryPrefix + "image@sha256:166710df254975d4a6c4c407c315951c22753dcaa829e020a3fd5d18fff70dd2", expected: oci.RegistryPrefix + "index.docker.io/library/image"},
{name: oci.RegistryPrefix + "127.0.0.1:36555/repo:latest", expected: oci.RegistryPrefix + "127.0.0.1:36555/repo"},
}
for _, c := range tc {
t.Run(c.name, func(t *testing.T) {
notag, _ := oci.WithoutTag(c.name)
assert.Equal(t, c.expected, notag)
})
}
}
func TestReplaceTag(t *testing.T) {
tc := []struct {
name string
expected string
}{
{name: "image:tag", expected: "index.docker.io/library/image:sha256-digest.att"},
{name: "image", expected: "index.docker.io/library/image:sha256-digest.att"},
{name: "image:sha256-digest.att", expected: "index.docker.io/library/image:sha256-digest.att"},
{name: oci.RegistryPrefix + "image:tag", expected: oci.RegistryPrefix + "index.docker.io/library/image:sha256-digest.att"},
{name: "image@sha256:166710df254975d4a6c4c407c315951c22753dcaa829e020a3fd5d18fff70dd2", expected: "index.docker.io/library/image:sha256-digest.att"},
{name: oci.LocalPrefix + "foobar", expected: oci.LocalPrefix + "foobar"},
{name: oci.RegistryPrefix + "image@sha256:166710df254975d4a6c4c407c315951c22753dcaa829e020a3fd5d18fff70dd2", expected: oci.RegistryPrefix + "index.docker.io/library/image:sha256-digest.att"},
{name: oci.RegistryPrefix + "127.0.0.1:36555/repo:latest", expected: oci.RegistryPrefix + "127.0.0.1:36555/repo:sha256-digest.att"},
}
digest := v1.Hash{
Algorithm: "sha256",
Hex: "digest",
}
for _, c := range tc {
t.Run(c.name, func(t *testing.T) {
replaced, err := oci.ReplaceTag(c.name, digest)
require.NoError(t, err)
assert.Equal(t, c.expected, replaced)
})
}
}

View File

@@ -1,13 +1,26 @@
package mirror
/*
Copyright Docker attest 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.
*/
package oci
import (
"context"
"fmt"
"os"
"github.com/docker/attest/internal/embed"
"github.com/docker/attest/pkg/attestation"
"github.com/docker/attest/pkg/oci"
"github.com/docker/attest/pkg/tuf"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/empty"
@@ -16,28 +29,19 @@ import (
"github.com/google/go-containerregistry/pkg/v1/remote"
)
func NewTufMirror(root []byte, tufPath, metadataURL, targetsURL string, versionChecker tuf.VersionChecker) (*TufMirror, error) {
if root == nil {
root = embed.RootDefault.Data
}
tufClient, err := tuf.NewTufClient(root, tufPath, metadataURL, targetsURL, versionChecker)
if err != nil {
return nil, fmt.Errorf("failed to create TUF client: %w", err)
}
return &TufMirror{TufClient: tufClient, tufPath: tufPath, metadataURL: metadataURL, targetsURL: targetsURL}, nil
}
func PushImageToRegistry(image v1.Image, imageName string) error {
// PushImageToRegistry pushes an image to the registry with the specified name.
func PushImageToRegistry(ctx context.Context, image v1.Image, imageName string) error {
ref, err := name.ParseReference(imageName)
if err != nil {
return fmt.Errorf("Failed to parse image name '%s': %w", imageName, err)
}
// Push the image to the registry
return remote.Write(ref, image, oci.MultiKeychainOption())
return remote.Write(ref, image, WithOptions(ctx, nil)...)
}
func PushIndexToRegistry(index v1.ImageIndex, imageName string) error {
// PushIndexToRegistry pushes an index to the registry with the specified name.
func PushIndexToRegistry(ctx context.Context, index v1.ImageIndex, imageName string) error {
// Parse the index name
ref, err := name.ParseReference(imageName)
if err != nil {
@@ -45,9 +49,10 @@ func PushIndexToRegistry(index v1.ImageIndex, imageName string) error {
}
// Push the index to the registry
return remote.WriteIndex(ref, index, oci.MultiKeychainOption())
return remote.WriteIndex(ref, index, WithOptions(ctx, nil)...)
}
// SaveIndexAsOCILayout saves an image as an OCI layout to the specified path.
func SaveImageAsOCILayout(image v1.Image, path string) error {
// Save the image to the local filesystem
err := os.MkdirAll(path, os.ModePerm)
@@ -62,6 +67,7 @@ func SaveImageAsOCILayout(image v1.Image, path string) error {
return l.AppendImage(image)
}
// SaveIndexAsOCILayout saves an index as an OCI layout to the specified path.
func SaveIndexAsOCILayout(image v1.ImageIndex, path string) error {
// Save the index to the local filesystem
err := os.MkdirAll(path, os.ModePerm)
@@ -76,16 +82,17 @@ func SaveIndexAsOCILayout(image v1.ImageIndex, path string) error {
return nil
}
func SaveIndex(outputs []*oci.ImageSpec, index v1.ImageIndex, indexName string) error {
// SaveIndex saves an index to the specified outputs.
func SaveIndex(ctx context.Context, outputs []*ImageSpec, index v1.ImageIndex, indexName string) error {
// split output by comma and write or push each one
for _, output := range outputs {
if output.Type == oci.OCI {
if output.Type == OCI {
idx := v1.ImageIndex(empty.Index)
idx = mutate.AppendManifests(idx, mutate.IndexAddendum{
Add: index,
Descriptor: v1.Descriptor{
Annotations: map[string]string{
oci.OciReferenceTarget: indexName,
OCIReferenceTarget: indexName,
},
},
})
@@ -94,7 +101,7 @@ func SaveIndex(outputs []*oci.ImageSpec, index v1.ImageIndex, indexName string)
return fmt.Errorf("failed to write signed image: %w", err)
}
} else {
err := PushIndexToRegistry(index, output.Identifier)
err := PushIndexToRegistry(ctx, index, output.Identifier)
if err != nil {
return fmt.Errorf("failed to push signed image: %w", err)
}
@@ -103,14 +110,15 @@ func SaveIndex(outputs []*oci.ImageSpec, index v1.ImageIndex, indexName string)
return nil
}
func SaveImage(output *oci.ImageSpec, image v1.Image, imageName string) error {
if output.Type == oci.OCI {
// SaveImage saves an image to the specified output.
func SaveImage(ctx context.Context, output *ImageSpec, image v1.Image, imageName string) error {
if output.Type == OCI {
idx := v1.ImageIndex(empty.Index)
idx = mutate.AppendManifests(idx, mutate.IndexAddendum{
Add: image,
Descriptor: v1.Descriptor{
Annotations: map[string]string{
oci.OciReferenceTarget: imageName,
OCIReferenceTarget: imageName,
},
},
})
@@ -119,7 +127,7 @@ func SaveImage(output *oci.ImageSpec, image v1.Image, imageName string) error {
return fmt.Errorf("failed to write signed image: %w", err)
}
} else {
err := PushImageToRegistry(image, output.Identifier)
err := PushImageToRegistry(ctx, image, output.Identifier)
if err != nil {
return fmt.Errorf("failed to push signed image: %w", err)
}
@@ -127,30 +135,26 @@ func SaveImage(output *oci.ImageSpec, image v1.Image, imageName string) error {
return nil
}
func SaveReferrers(manifest *attestation.AttestationManifest, outputs []*oci.ImageSpec) error {
// SaveImagesNoTag saves a list of images by digest to the specified outputs.
func SaveImagesNoTag(ctx context.Context, images []v1.Image, outputs []*ImageSpec) error {
for _, output := range outputs {
if output.Type == oci.OCI {
// OCI layout output not supported
if output.Type == OCI {
continue
}
// so that we use the same tag each time to reduce number of tags (tags aren't needed for referrers but we must push one)
attOut, err := oci.ReplaceTagInSpec(output, manifest.SubjectDescriptor.Digest)
if err != nil {
return err
}
//otherwise we end up with the detected platform, though I'm not sure it matters
attOut.Platform = &v1.Platform{
OS: "unknown",
Architecture: "unknown",
}
images, err := manifest.BuildReferringArtifacts()
if err != nil {
return fmt.Errorf("failed to build image: %w", err)
}
for _, image := range images {
err = SaveImage(attOut, image, "")
}
if err != nil {
return fmt.Errorf("failed to push image: %w", err)
digest, err := image.Digest()
if err != nil {
return fmt.Errorf("failed to get image digest: %w", err)
}
spec, err := ReplaceDigestInSpec(output, digest)
if err != nil {
return fmt.Errorf("failed to create image spec: %w", err)
}
err = PushImageToRegistry(ctx, image, spec.Identifier)
if err != nil {
return fmt.Errorf("failed to push image: %w", err)
}
}
}
return nil

127
oci/output_test.go Normal file
View File

@@ -0,0 +1,127 @@
/*
Copyright Docker attest 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.
*/
package oci_test
import (
"context"
"fmt"
"net/url"
"testing"
"github.com/docker/attest/attestation"
"github.com/docker/attest/internal/test"
"github.com/docker/attest/oci"
"github.com/google/go-containerregistry/pkg/registry"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/empty"
intoto "github.com/in-toto/in-toto-golang/in_toto"
"github.com/stretchr/testify/require"
)
func TestSavingIndex(t *testing.T) {
outputLayout := test.CreateTempDir(t, "", "mirror-test")
attIdx, err := oci.IndexFromPath(test.UnsignedTestIndex(".."))
require.NoError(t, err)
ctx := context.Background()
regServer := test.NewLocalRegistry(ctx)
defer regServer.Close()
u, err := url.Parse(regServer.URL)
require.NoError(t, err)
indexName := fmt.Sprintf("%s/repo:root", u.Host)
output, err := oci.ParseImageSpecs(indexName)
require.NoError(t, err)
err = oci.SaveIndex(ctx, output, attIdx.Index, indexName)
require.NoError(t, err)
ociOutput, err := oci.ParseImageSpecs(oci.LocalPrefix + outputLayout)
require.NoError(t, err)
err = oci.SaveIndex(ctx, ociOutput, attIdx.Index, indexName)
require.NoError(t, err)
}
func TestSavingImage(t *testing.T) {
outputLayout := test.CreateTempDir(t, "", "mirror-test")
img := empty.Image
ctx := context.Background()
regServer := test.NewLocalRegistry(ctx)
defer regServer.Close()
u, err := url.Parse(regServer.URL)
require.NoError(t, err)
indexName := fmt.Sprintf("%s/repo:root", u.Host)
output, err := oci.ParseImageSpec(indexName)
require.NoError(t, err)
err = oci.SaveImage(ctx, output, img, indexName)
require.NoError(t, err)
ociOutput, err := oci.ParseImageSpec(oci.LocalPrefix + outputLayout)
require.NoError(t, err)
err = oci.SaveImage(ctx, ociOutput, img, indexName)
require.NoError(t, err)
}
func TestSavingReferrers(t *testing.T) {
ctx, signer := test.Setup(t)
opts := &attestation.SigningOptions{}
statement := &intoto.Statement{
StatementHeader: intoto.StatementHeader{
PredicateType: attestation.VSAPredicateType,
},
}
digest, err := v1.NewHash(test.UnsignedLinuxAMD64ImageDigest)
require.NoError(t, err)
subject := &v1.Descriptor{
MediaType: "application/vnd.oci.image.manifest.v1+json",
Digest: digest,
}
manifest, err := attestation.NewManifest(subject)
require.NoError(t, err)
err = manifest.Add(ctx, signer, statement, opts)
require.NoError(t, err)
regServer := test.NewLocalRegistry(ctx, registry.WithReferrersSupport(true))
defer regServer.Close()
u, err := url.Parse(regServer.URL)
require.NoError(t, err)
indexName := fmt.Sprintf("%s/repo:root", u.Host)
output, err := oci.ParseImageSpecs(indexName)
require.NoError(t, err)
artifacts, err := manifest.BuildReferringArtifacts()
require.NoError(t, err)
err = oci.SaveImagesNoTag(ctx, artifacts, output)
require.NoError(t, err)
reg := &attestation.MockRegistryResolver{
Subject: subject,
MockResolver: &attestation.MockResolver{},
ImageNameStr: indexName,
}
require.NoError(t, err)
refResolver, err := attestation.NewReferrersResolver(reg)
require.NoError(t, err)
attestations, err := refResolver.Attestations(ctx, attestation.VSAPredicateType)
require.NoError(t, err)
require.Len(t, attestations, 1)
}

80
oci/registry.go Normal file
View File

@@ -0,0 +1,80 @@
/*
Copyright Docker attest 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.
*/
package oci
import (
"context"
"fmt"
"github.com/google/go-containerregistry/pkg/name"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/remote"
)
// ensure RegistryImageDetailsResolver implements ImageDetailsResolver.
var _ ImageDetailsResolver = &RegistryImageDetailsResolver{}
type RegistryImageDetailsResolver struct {
*ImageSpec
descriptor *v1.Descriptor
}
func NewRegistryImageDetailsResolver(src *ImageSpec) (*RegistryImageDetailsResolver, error) {
return &RegistryImageDetailsResolver{
ImageSpec: src,
}, nil
}
func (r *RegistryImageDetailsResolver) ImageName(_ context.Context) (string, error) {
return r.Identifier, nil
}
func (r *RegistryImageDetailsResolver) ImagePlatform(_ context.Context) (*v1.Platform, error) {
return r.Platform, nil
}
func (r *RegistryImageDetailsResolver) ImageDescriptor(ctx context.Context) (*v1.Descriptor, error) {
if r.descriptor == nil {
subjectRef, err := name.ParseReference(r.Identifier)
if err != nil {
return nil, fmt.Errorf("failed to parse reference: %w", err)
}
options := WithOptions(ctx, r.Platform)
image, err := remote.Image(subjectRef, options...)
if err != nil {
return nil, fmt.Errorf("failed to get image manifest: %w", err)
}
digest, err := image.Digest()
if err != nil {
return nil, fmt.Errorf("failed to get image digest: %w", err)
}
size, err := image.Size()
if err != nil {
return nil, fmt.Errorf("failed to get image size: %w", err)
}
mediaType, err := image.MediaType()
if err != nil {
return nil, fmt.Errorf("failed to get image media type: %w", err)
}
r.descriptor = &v1.Descriptor{
Digest: digest,
Size: size,
MediaType: mediaType,
}
}
return r.descriptor, nil
}

29
oci/resolver.go Normal file
View File

@@ -0,0 +1,29 @@
/*
Copyright Docker attest 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.
*/
package oci
import (
"context"
v1 "github.com/google/go-containerregistry/pkg/v1"
)
type ImageDetailsResolver interface {
ImageName(ctx context.Context) (string, error)
ImagePlatform(ctx context.Context) (*v1.Platform, error)
ImageDescriptor(ctx context.Context) (*v1.Descriptor, error)
}

View File

@@ -1,6 +1,25 @@
/*
Copyright Docker attest 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.
*/
package oci
import (
"bytes"
"context"
"encoding/json"
"fmt"
"strings"
@@ -11,24 +30,20 @@ import (
)
const (
OciReferenceTarget = "org.opencontainers.image.ref.name"
OCIReferenceTarget = "org.opencontainers.image.ref.name"
LocalPrefix = "oci://"
RegistryPrefix = "docker://"
OCI SourceType = "OCI"
Docker SourceType = "Docker"
)
type SourceType string
type NamedIndex struct {
Index v1.ImageIndex
Name string
}
type AttestationOptions struct {
NoReferrers bool
Attach bool
ReferrersRepo string
}
type (
SourceType string
NamedIndex struct {
Index v1.ImageIndex
Name string
}
)
type ImageSpecOption func(*ImageSpec) error
@@ -50,7 +65,7 @@ func IndexFromPath(path string) (*NamedIndex, error) {
if err != nil {
return nil, fmt.Errorf("failed to get digest: %w", err)
}
imageName := idxm.Manifests[0].Annotations[OciReferenceTarget]
imageName := idxm.Manifests[0].Annotations[OCIReferenceTarget]
idxDigest := idxm.Manifests[0].Digest
idx, err := wrapperIdx.ImageIndex(idxDigest)
@@ -63,14 +78,14 @@ func IndexFromPath(path string) (*NamedIndex, error) {
}, nil
}
func IndexFromRemote(image string) (*NamedIndex, error) {
func IndexFromRemote(ctx context.Context, image string) (*NamedIndex, error) {
ref, err := name.ParseReference(image)
if err != nil {
return nil, fmt.Errorf("failed to parse image reference %s: %w", image, err)
}
// Pull the image from the registry
idx, err := remote.Index(ref, MultiKeychainOption())
idx, err := remote.Index(ref, WithOptions(ctx, nil)...)
if err != nil {
return nil, fmt.Errorf("failed to pull image %s: %w", image, err)
}
@@ -80,12 +95,11 @@ func IndexFromRemote(image string) (*NamedIndex, error) {
}, nil
}
func LoadIndex(input *ImageSpec) (*NamedIndex, error) {
func LoadIndex(ctx context.Context, input *ImageSpec) (*NamedIndex, error) {
if input.Type == OCI {
return IndexFromPath(input.Identifier)
} else {
return IndexFromRemote(input.Identifier)
}
return IndexFromRemote(ctx, input.Identifier)
}
func (i *ImageSpec) ForPlatforms(platform string) ([]*ImageSpec, error) {
@@ -179,3 +193,42 @@ func WithoutTag(image string) (string, error) {
repo := ref.Context().Name()
return prefix + repo, nil
}
type EmptyConfigImage struct {
v1.Image
}
func (i *EmptyConfigImage) RawConfigFile() ([]byte, error) {
return []byte("{}"), nil
}
func (i *EmptyConfigImage) Manifest() (*v1.Manifest, error) {
mf, err := i.Image.Manifest()
if err != nil {
return nil, fmt.Errorf("failed to get manifest: %w", err)
}
mf.Config = v1.Descriptor{
MediaType: "application/vnd.oci.empty.v1+json",
Size: 2,
Digest: v1.Hash{Algorithm: "sha256", Hex: "44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a"},
Data: []byte("{}"),
}
return mf, nil
}
func (i *EmptyConfigImage) RawManifest() ([]byte, error) {
mf, err := i.Manifest()
if err != nil {
return nil, fmt.Errorf("failed to get manifest: %w", err)
}
return json.Marshal(mf)
}
func (i *EmptyConfigImage) Digest() (v1.Hash, error) {
mb, err := i.RawManifest()
if err != nil {
return v1.Hash{}, err
}
digest, _, err := v1.SHA256(bytes.NewReader(mb))
return digest, err
}

37
oci/types_test.go Normal file
View File

@@ -0,0 +1,37 @@
/*
Copyright Docker attest 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.
*/
package oci
import (
"testing"
"github.com/docker/attest/internal/util"
"github.com/google/go-containerregistry/pkg/v1/empty"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestEmptyConfigImageDigest(t *testing.T) {
empty := empty.Image
img := EmptyConfigImage{Image: empty}
mf, err := img.RawManifest()
require.NoError(t, err)
hash := util.SHA256Hex(mf)
digest, err := img.Digest()
require.NoError(t, err)
assert.Equal(t, digest.Hex, hash)
}

View File

@@ -1,68 +0,0 @@
package attest_test
import (
"context"
"fmt"
"os"
"path/filepath"
"github.com/docker/attest/internal/embed"
"github.com/docker/attest/pkg/attest"
"github.com/docker/attest/pkg/oci"
"github.com/docker/attest/pkg/policy"
"github.com/docker/attest/pkg/tuf"
)
func createTufClient(outputPath string) (*tuf.TufClient, error) {
// using oci tuf metadata and targets
metadataURI := "registry-1.docker.io/docker/tuf-metadata:latest"
targetsURI := "registry-1.docker.io/docker/tuf-targets"
// example using http tuf metadata and targets
// metadataURI := "https://docker.github.io/tuf-staging/metadata"
// targetsURI := "https://docker.github.io/tuf-staging/targets"
return tuf.NewTufClient(embed.RootStaging.Data, outputPath, metadataURI, targetsURI, tuf.NewMockVersionChecker())
}
func ExampleVerify_remote() {
// create a tuf client
home, err := os.UserHomeDir()
if err != nil {
panic(err)
}
tufOutputPath := filepath.Join(home, ".docker", "tuf")
tufClient, err := createTufClient(tufOutputPath)
if err != nil {
panic(err)
}
// create a resolver for remote attestations
image := "registry-1.docker.io/library/notary:server"
platform := "linux/amd64"
// configure policy options
opts := &policy.PolicyOptions{
TufClient: tufClient,
LocalTargetsDir: filepath.Join(home, ".docker", "policy"), // location to store policy files downloaded from TUF
LocalPolicyDir: "", // overrides TUF policy for local policy files if set
PolicyId: "", // set to ignore policy mapping and select a policy by id
}
// verify attestations
src, err := oci.ParseImageSpec(image, oci.WithPlatform(platform))
if err != nil {
panic(err)
}
result, err := attest.Verify(context.Background(), src, opts)
if err != nil {
panic(err)
}
switch result.Outcome {
case attest.OutcomeSuccess:
fmt.Println("policy passed")
case attest.OutcomeNoPolicy:
fmt.Println("no policy for image")
case attest.OutcomeFailure:
fmt.Println("policy failed")
}
}

View File

@@ -1,29 +0,0 @@
package attest
import (
"context"
"fmt"
"github.com/docker/attest/pkg/attestation"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/secure-systems-lab/go-securesystemslib/dsse"
)
// this is only relevant if there are (unsigned) in-toto statements
func SignStatements(ctx context.Context, idx v1.ImageIndex, signer dsse.SignerVerifier, opts *attestation.SigningOptions) ([]*attestation.AttestationManifest, error) {
// extract attestation manifests from index
attestationManifests, err := attestation.GetAttestationManifestsFromIndex(idx)
if err != nil {
return nil, fmt.Errorf("failed to load attestation manifests from index: %w", err)
}
// sign every attestation layer in each manifest
for _, manifest := range attestationManifests {
for _, layer := range manifest.OriginalLayers {
err = manifest.AddAttestation(ctx, signer, layer.Statement, opts)
if err != nil {
return nil, fmt.Errorf("failed to sign attestation layer %w", err)
}
}
}
return attestationManifests, nil
}

View File

@@ -1,246 +0,0 @@
package attest
import (
"encoding/json"
"fmt"
"net/http/httptest"
"net/url"
"path/filepath"
"testing"
"github.com/docker/attest/internal/test"
"github.com/docker/attest/pkg/attestation"
"github.com/docker/attest/pkg/mirror"
"github.com/docker/attest/pkg/oci"
"github.com/docker/attest/pkg/policy"
"github.com/google/go-containerregistry/pkg/registry"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/empty"
"github.com/google/go-containerregistry/pkg/v1/layout"
"github.com/google/go-containerregistry/pkg/v1/mutate"
"github.com/google/go-containerregistry/pkg/v1/static"
"github.com/google/go-containerregistry/pkg/v1/types"
intoto "github.com/in-toto/in-toto-golang/in_toto"
v02 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var (
UnsignedTestImage = filepath.Join("..", "..", "test", "testdata", "unsigned-test-image")
NoProvenanceImage = filepath.Join("..", "..", "test", "testdata", "no-provenance-image")
PassPolicyDir = filepath.Join("..", "..", "test", "testdata", "local-policy-pass")
PassMirrorPolicyDir = filepath.Join("..", "..", "test", "testdata", "local-policy-mirror")
PassNoTLPolicyDir = filepath.Join("..", "..", "test", "testdata", "local-policy-no-tl")
FailPolicyDir = filepath.Join("..", "..", "test", "testdata", "local-policy-fail")
TestTempDir = "attest-sign-test"
)
func TestSignVerifyOCILayout(t *testing.T) {
ctx, signer := test.Setup(t)
testCases := []struct {
name string
TestImage string
expectedStatements int
expectedAttestations int
replace bool
}{
{"signed replaced", UnsignedTestImage, 0, 4, true},
{"without replace", UnsignedTestImage, 4, 4, false},
// image without provenance doesn't fail
{"no provenance (replace)", NoProvenanceImage, 0, 2, true},
{"no provenance (no replace)", NoProvenanceImage, 2, 2, false},
}
policyOpts := &policy.PolicyOptions{
LocalPolicyDir: PassPolicyDir,
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
outputLayout := test.CreateTempDir(t, "", TestTempDir)
opts := &attestation.SigningOptions{}
attIdx, err := oci.IndexFromPath(tc.TestImage)
require.NoError(t, err)
signedManifests, err := SignStatements(ctx, attIdx.Index, signer, opts)
require.NoError(t, err)
signedIndex := attIdx.Index
signedIndex, err = attestation.UpdateIndexImages(signedIndex, signedManifests, attestation.WithReplacedLayers(tc.replace))
require.NoError(t, err)
// output signed attestations
idx := v1.ImageIndex(empty.Index)
idx = mutate.AppendManifests(idx, mutate.IndexAddendum{
Add: signedIndex,
Descriptor: v1.Descriptor{
Annotations: map[string]string{
oci.OciReferenceTarget: attIdx.Name,
},
},
})
_, err = layout.Write(outputLayout, idx)
require.NoError(t, err)
src, err := oci.ParseImageSpec("oci://" + outputLayout)
require.NoError(t, err)
policy, err := Verify(ctx, src, policyOpts)
require.NoError(t, err)
assert.Equalf(t, OutcomeSuccess, policy.Outcome, "Policy should have been found")
var allEnvelopes []*test.AnnotatedStatement
for _, predicate := range []string{intoto.PredicateSPDX, v02.PredicateSLSAProvenance, attestation.VSAPredicateType} {
mt, _ := attestation.DSSEMediaType(predicate)
statements, err := test.ExtractAnnotatedStatements(outputLayout, mt)
require.NoError(t, err)
allEnvelopes = append(allEnvelopes, statements...)
for _, stmt := range statements {
assert.Equalf(t, predicate, stmt.Annotations[attestation.InTotoPredicateType], "expected predicate-type annotation to be set to %s, got %s", predicate, stmt.Annotations[attestation.InTotoPredicateType])
assert.Equalf(t, attestation.LifecycleStageExperimental, stmt.Annotations[attestation.InTotoReferenceLifecycleStage], "expected reference lifecycle stage annotation to be set to %s, got %s", attestation.LifecycleStageExperimental, stmt.Annotations[attestation.InTotoReferenceLifecycleStage])
}
}
assert.Equalf(t, tc.expectedAttestations, len(allEnvelopes), "expected %d attestations, got %d", tc.expectedAttestations, len(allEnvelopes))
statements, err := test.ExtractAnnotatedStatements(outputLayout, intoto.PayloadType)
require.NoError(t, err)
assert.Equalf(t, tc.expectedStatements, len(statements), "expected %d statement, got %d", tc.expectedStatements, len(statements))
})
}
}
func TestAddSignedLayerAnnotations(t *testing.T) {
ctx, signer := test.Setup(t)
testCases := []struct {
name string
replace bool
}{
{"replaced", true},
{"not replaced", false},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
data := []byte("signed")
testLayer := static.NewLayer(data, types.MediaType(intoto.PayloadType))
mediaType := types.OCIManifestSchema1
opts := &attestation.SigningOptions{}
originalLayer := &attestation.AttestationLayer{
Layer: testLayer,
Statement: &intoto.Statement{
StatementHeader: intoto.StatementHeader{
PredicateType: attestation.VSAPredicateType,
},
},
Annotations: map[string]string{"test": "test"},
}
manifest := &attestation.AttestationManifest{
OriginalDescriptor: &v1.Descriptor{
MediaType: mediaType,
},
OriginalLayers: []*attestation.AttestationLayer{
originalLayer,
},
SubjectDescriptor: &v1.Descriptor{},
}
err := manifest.AddAttestation(ctx, signer, originalLayer.Statement, opts)
require.NoError(t, err)
newImg, err := manifest.BuildAttestationImage(attestation.WithReplacedLayers(tc.replace))
require.NoError(t, err)
mf, _ := newImg.RawManifest()
type Annotations struct {
Annotations map[string]string `json:"annotations"`
}
type Layers struct {
Layers []Annotations `json:"layers"`
}
l := &Layers{}
err = json.Unmarshal(mf, l)
require.NoError(t, err)
_, ok := l.Layers[0].Annotations["test"]
assert.Truef(t, ok, "missing annotations")
})
}
}
func TestSimpleStatementSigning(t *testing.T) {
ctx, signer := test.Setup(t)
empty := types.MediaType("application/vnd.oci.empty.v1+json")
testCases := []struct {
name string
replace bool
}{
{"replaced", true},
{"not replaced", false},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
opts := &attestation.SigningOptions{}
statement := &intoto.Statement{
StatementHeader: intoto.StatementHeader{
PredicateType: attestation.VSAPredicateType,
},
}
statement2 := &intoto.Statement{
StatementHeader: intoto.StatementHeader{
PredicateType: attestation.VSAPredicateType,
},
}
digest, err := v1.NewHash("sha256:da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620")
require.NoError(t, err)
subject := &v1.Descriptor{
MediaType: "application/vnd.oci.image.manifest.v1+json",
Digest: digest,
}
manifest, err := NewAttestationManifest(subject)
require.NoError(t, err)
err = manifest.AddAttestation(ctx, signer, statement, opts)
require.NoError(t, err)
err = manifest.AddAttestation(ctx, signer, statement2, opts)
require.NoError(t, err)
// fake that the manfifest was loaded from a real image
manifest.OriginalLayers = manifest.SignedLayers
envelopes, err := oci.ExtractEnvelopes(manifest, attestation.VSAPredicateType)
require.NoError(t, err)
assert.Len(t, envelopes, 2)
newImg, err := manifest.BuildAttestationImage(attestation.WithReplacedLayers(tc.replace))
require.NoError(t, err)
layers, err := newImg.Layers()
require.NoError(t, err)
if tc.replace {
assert.Len(t, layers, 2)
} else {
assert.Len(t, layers, 4)
}
newImgs, err := manifest.BuildReferringArtifacts()
require.NoError(t, err)
assert.Len(t, newImgs, 2)
for _, img := range newImgs {
mf, err := img.Manifest()
require.NoError(t, err)
assert.Contains(t, mf.ArtifactType, "application/vnd.in-toto")
assert.Contains(t, mf.ArtifactType, "+dsse")
assert.Equal(t, subject.MediaType, mf.MediaType)
assert.Equal(t, empty, mf.Config.MediaType)
assert.Equal(t, int64(2), mf.Config.Size)
assert.Equal(t, "{}", string(mf.Config.Data))
layers, err := img.Layers()
require.NoError(t, err)
assert.Len(t, layers, 1)
}
server := httptest.NewServer(registry.New(registry.WithReferrersSupport(true)))
defer server.Close()
u, err := url.Parse(server.URL)
require.NoError(t, err)
indexName := fmt.Sprintf("%s/repo:root", u.Host)
output, err := oci.ParseImageSpecs(indexName)
require.NoError(t, err)
err = mirror.SaveReferrers(manifest, output)
require.NoError(t, err)
})
}
}

View File

@@ -1,37 +0,0 @@
package attest
import (
"fmt"
"github.com/docker/attest/pkg/policy"
v1 "github.com/google/go-containerregistry/pkg/v1"
intoto "github.com/in-toto/in-toto-golang/in_toto"
)
type Outcome string
const (
OutcomeSuccess Outcome = "success"
OutcomeFailure Outcome = "failure"
OutcomeNoPolicy Outcome = "no_policy"
)
func (o Outcome) StringForVSA() (string, error) {
switch o {
case OutcomeSuccess:
return "PASSED", nil
case OutcomeFailure:
return "FAILED", nil
default:
return "", fmt.Errorf("unknown outcome: %s", o)
}
}
type VerificationResult struct {
Outcome Outcome
Policy *policy.Policy
Input *policy.PolicyInput
VSA *intoto.Statement
Violations []policy.Violation
SubjectDescriptor *v1.Descriptor
}

View File

@@ -1,176 +0,0 @@
package attest
import (
"context"
"fmt"
"strings"
"time"
"github.com/distribution/reference"
"github.com/docker/attest/pkg/attestation"
"github.com/docker/attest/pkg/config"
"github.com/docker/attest/pkg/oci"
"github.com/docker/attest/pkg/policy"
v1 "github.com/google/go-containerregistry/pkg/v1"
intoto "github.com/in-toto/in-toto-golang/in_toto"
)
func Verify(ctx context.Context, src *oci.ImageSpec, opts *policy.PolicyOptions) (result *VerificationResult, err error) {
// so that we can resolve mapping from the image name earlier
detailsResolver, err := policy.CreateImageDetailsResolver(src)
if err != nil {
return nil, fmt.Errorf("failed to create image details resolver: %w", err)
}
if opts.AttestationStyle == "" {
opts.AttestationStyle = config.AttestationStyleReferrers
}
if opts.ReferrersRepo != "" && opts.AttestationStyle != config.AttestationStyleReferrers {
return nil, fmt.Errorf("referrers repo specified but attestation source not set to referrers")
}
pctx, err := policy.ResolvePolicy(ctx, detailsResolver, opts)
if err != nil {
return nil, fmt.Errorf("failed to resolve policy: %w", err)
}
if pctx == nil {
return &VerificationResult{
Outcome: OutcomeNoPolicy,
}, nil
}
// this is overriding the mapping with a referrers config. Useful for testing if nothing else
if opts.ReferrersRepo != "" {
pctx.Mapping.Attestations = &config.AttestationConfig{
Repo: opts.ReferrersRepo,
Style: config.AttestationStyleReferrers,
}
} else if opts.AttestationStyle == config.AttestationStyleAttached {
pctx.Mapping.Attestations = &config.AttestationConfig{
Repo: opts.ReferrersRepo,
Style: config.AttestationStyleAttached,
}
}
// because we have a mapping now, we can select a resolver based on its contents (ie. referrers or attached)
resolver, err := policy.CreateAttestationResolver(detailsResolver, pctx.Mapping)
if err != nil {
return nil, fmt.Errorf("failed to create attestation resolver: %w", err)
}
result, err = VerifyAttestations(ctx, resolver, pctx)
if err != nil {
return nil, fmt.Errorf("failed to evaluate policy: %w", err)
}
return result, nil
}
func toVerificationResult(p *policy.Policy, input *policy.PolicyInput, result *policy.Result) (*VerificationResult, error) {
dgst, err := oci.SplitDigest(input.Digest)
if err != nil {
return nil, fmt.Errorf("failed to split digest: %w", err)
}
subject := intoto.Subject{
Name: input.Purl,
Digest: dgst,
}
resourceUri, err := attestation.ToVSAResourceURI(subject)
if err != nil {
return nil, fmt.Errorf("failed to create resource uri: %w", err)
}
var outcome Outcome
if result.Success {
outcome = OutcomeSuccess
} else {
outcome = OutcomeFailure
}
outcomeStr, err := outcome.StringForVSA()
if err != nil {
return nil, err
}
return &VerificationResult{
Policy: p,
Outcome: outcome,
Violations: result.Violations,
Input: input,
VSA: &intoto.Statement{
StatementHeader: intoto.StatementHeader{
PredicateType: attestation.VSAPredicateType,
Type: intoto.StatementInTotoV01,
Subject: result.Summary.Subjects,
},
Predicate: attestation.VSAPredicate{
Verifier: attestation.VSAVerifier{
ID: result.Summary.Verifier,
},
TimeVerified: time.Now().UTC().Format(time.RFC3339),
ResourceUri: resourceUri,
Policy: attestation.VSAPolicy{URI: result.Summary.PolicyURI},
VerificationResult: outcomeStr,
VerifiedLevels: result.Summary.SLSALevels,
},
},
}, nil
}
func VerifyAttestations(ctx context.Context, resolver oci.AttestationResolver, pctx *policy.Policy) (*VerificationResult, error) {
desc, err := resolver.ImageDescriptor(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get image descriptor: %w", err)
}
digest := desc.Digest.String()
name, err := resolver.ImageName(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get image name: %w", err)
}
platform, err := resolver.ImagePlatform(ctx)
if err != nil {
return nil, err
}
if pctx.ResolvedName != "" {
// this means the name we have is not the one we want to use for policy evaluation
// so we need to replace it with the one we resolved during policy resolution.
// this can happen if the name is an alias for another image, e.g. if it is a mirror
ref, err := reference.ParseNormalizedNamed(name)
if err != nil {
return nil, fmt.Errorf("failed to parse image name: %w", err)
}
oldName := ref.Name()
name = strings.Replace(name, oldName, pctx.ResolvedName, 1)
}
purl, canonical, err := oci.RefToPURL(name, platform)
if err != nil {
return nil, fmt.Errorf("failed to convert ref to purl: %w", err)
}
input := &policy.PolicyInput{
Digest: digest,
Purl: purl,
IsCanonical: canonical,
}
evaluator, err := policy.GetPolicyEvaluator(ctx)
if err != nil {
return nil, err
}
result, err := evaluator.Evaluate(ctx, resolver, pctx, input)
if err != nil {
return nil, fmt.Errorf("policy evaluation failed: %w", err)
}
verificationResult, err := toVerificationResult(pctx, input, result)
if err != nil {
return nil, fmt.Errorf("failed to convert to policy result: %w", err)
}
verificationResult.SubjectDescriptor = desc
return verificationResult, nil
}
func NewAttestationManifest(subject *v1.Descriptor) (*attestation.AttestationManifest, error) {
return &attestation.AttestationManifest{
OriginalDescriptor: &v1.Descriptor{
MediaType: "application/vnd.oci.image.manifest.v1+json",
},
OriginalLayers: []*attestation.AttestationLayer{},
SubjectDescriptor: subject,
}, nil
}

View File

@@ -1,259 +0,0 @@
package attest
import (
"context"
"encoding/json"
"fmt"
"os"
"path/filepath"
"testing"
"github.com/docker/attest/internal/test"
"github.com/docker/attest/pkg/attestation"
"github.com/docker/attest/pkg/oci"
"github.com/docker/attest/pkg/policy"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/empty"
"github.com/google/go-containerregistry/pkg/v1/layout"
"github.com/google/go-containerregistry/pkg/v1/mutate"
intoto "github.com/in-toto/in-toto-golang/in_toto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var (
ExampleAttestation = filepath.Join("..", "..", "test", "testdata", "example_attestation.json")
)
const (
LinuxAMD64 = "linux/amd64"
)
func TestVerifyAttestations(t *testing.T) {
ex, err := os.ReadFile(ExampleAttestation)
assert.NoError(t, err)
var env = new(attestation.Envelope)
err = json.Unmarshal(ex, env)
assert.NoError(t, err)
resolver := &test.MockResolver{
Envs: []*attestation.Envelope{env},
}
testCases := []struct {
name string
policyEvaluationError error
expectedError error
}{
{"policy ok", nil, nil},
{"policy error", fmt.Errorf("policy error"), fmt.Errorf("policy evaluation failed: policy error")},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
mockPE := policy.MockPolicyEvaluator{
EvaluateFunc: func(ctx context.Context, resolver oci.AttestationResolver, pctx *policy.Policy, input *policy.PolicyInput) (*policy.Result, error) {
return policy.AllowedResult(), tc.policyEvaluationError
},
}
ctx := policy.WithPolicyEvaluator(context.Background(), &mockPE)
_, err := VerifyAttestations(ctx, resolver, &policy.Policy{ResolvedName: ""})
if tc.expectedError != nil {
if assert.Error(t, err) {
assert.Equal(t, tc.expectedError.Error(), err.Error())
}
} else {
assert.NoError(t, err)
}
})
}
}
func TestVSA(t *testing.T) {
ctx, signer := test.Setup(t)
ctx = policy.WithPolicyEvaluator(ctx, policy.NewRegoEvaluator(true))
// setup an image with signed attestations
outputLayout := test.CreateTempDir(t, "", TestTempDir)
opts := &attestation.SigningOptions{}
attIdx, err := oci.IndexFromPath(UnsignedTestImage)
assert.NoError(t, err)
signedManifests, err := SignStatements(ctx, attIdx.Index, signer, opts)
require.NoError(t, err)
signedIndex := attIdx.Index
signedIndex, err = attestation.UpdateIndexImages(signedIndex, signedManifests)
require.NoError(t, err)
// output signed attestations
idx := v1.ImageIndex(empty.Index)
idx = mutate.AppendManifests(idx, mutate.IndexAddendum{
Add: signedIndex,
Descriptor: v1.Descriptor{
Annotations: map[string]string{
oci.OciReferenceTarget: attIdx.Name,
},
},
})
_, err = layout.Write(outputLayout, idx)
assert.NoError(t, err)
// mocked vsa query should pass
policyOpts := &policy.PolicyOptions{
LocalPolicyDir: PassPolicyDir,
}
src, err := oci.ParseImageSpec("oci://"+outputLayout, oci.WithPlatform(LinuxAMD64))
require.NoError(t, err)
results, err := Verify(ctx, src, policyOpts)
require.NoError(t, err)
assert.Equal(t, OutcomeSuccess, results.Outcome)
assert.Empty(t, results.Violations)
if assert.NotNil(t, results.Input) {
assert.Equal(t, "sha256:da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620", results.Input.Digest)
assert.False(t, results.Input.IsCanonical)
}
assert.Equal(t, intoto.StatementInTotoV01, results.VSA.Type)
assert.Equal(t, attestation.VSAPredicateType, results.VSA.PredicateType)
assert.Len(t, results.VSA.Subject, 1)
require.IsType(t, attestation.VSAPredicate{}, results.VSA.Predicate)
attestationPredicate := results.VSA.Predicate.(attestation.VSAPredicate)
assert.Equal(t, "PASSED", attestationPredicate.VerificationResult)
assert.Equal(t, "docker-official-images", attestationPredicate.Verifier.ID)
assert.Equal(t, []string{"SLSA_BUILD_LEVEL_3"}, attestationPredicate.VerifiedLevels)
assert.Equal(t, "https://docker.com/official/policy/v0.1", attestationPredicate.Policy.URI)
}
func TestVerificationFailure(t *testing.T) {
ctx, signer := test.Setup(t)
ctx = policy.WithPolicyEvaluator(ctx, policy.NewRegoEvaluator(true))
// setup an image with signed attestations
outputLayout := test.CreateTempDir(t, "", TestTempDir)
opts := &attestation.SigningOptions{}
attIdx, err := oci.IndexFromPath(UnsignedTestImage)
assert.NoError(t, err)
signedManifests, err := SignStatements(ctx, attIdx.Index, signer, opts)
require.NoError(t, err)
signedIndex := attIdx.Index
signedIndex, err = attestation.UpdateIndexImages(signedIndex, signedManifests, attestation.WithReplacedLayers(true))
require.NoError(t, err)
// output signed attestations
idx := v1.ImageIndex(empty.Index)
idx = mutate.AppendManifests(idx, mutate.IndexAddendum{
Add: signedIndex,
Descriptor: v1.Descriptor{
Annotations: map[string]string{
oci.OciReferenceTarget: attIdx.Name,
},
},
})
_, err = layout.Write(outputLayout, idx)
assert.NoError(t, err)
// mocked vsa query should fail
policyOpts := &policy.PolicyOptions{
LocalPolicyDir: FailPolicyDir,
}
src, err := oci.ParseImageSpec("oci://"+outputLayout, oci.WithPlatform(LinuxAMD64))
require.NoError(t, err)
results, err := Verify(ctx, src, policyOpts)
require.NoError(t, err)
assert.Equal(t, OutcomeFailure, results.Outcome)
assert.Len(t, results.Violations, 1)
violation := results.Violations[0]
assert.Equal(t, "missing_attestation", violation.Type)
assert.Equal(t, "Attestation missing for subject", violation.Description)
assert.Nil(t, violation.Attestation)
assert.Equal(t, intoto.StatementInTotoV01, results.VSA.Type)
assert.Equal(t, attestation.VSAPredicateType, results.VSA.PredicateType)
assert.Len(t, results.VSA.Subject, 1)
require.IsType(t, attestation.VSAPredicate{}, results.VSA.Predicate)
attestationPredicate := results.VSA.Predicate.(attestation.VSAPredicate)
assert.Equal(t, "FAILED", attestationPredicate.VerificationResult)
assert.Equal(t, "docker-official-images", attestationPredicate.Verifier.ID)
assert.Equal(t, []string{"SLSA_BUILD_LEVEL_3"}, attestationPredicate.VerifiedLevels)
assert.Equal(t, "https://docker.com/official/policy/v0.1", attestationPredicate.Policy.URI)
}
func TestSignVerify(t *testing.T) {
ctx, signer := test.Setup(t)
ctx = policy.WithPolicyEvaluator(ctx, policy.NewRegoEvaluator(true))
// setup an image with signed attestations
outputLayout := test.CreateTempDir(t, "", TestTempDir)
testCases := []struct {
name string
signTL bool
policyDir string
imageName string
expectError bool
}{
{name: "happy path", signTL: true, policyDir: PassNoTLPolicyDir},
{name: "sign tl, verify no tl", signTL: true, policyDir: PassPolicyDir},
{name: "no tl", signTL: false, policyDir: PassPolicyDir},
{name: "mirror", signTL: true, policyDir: PassMirrorPolicyDir, imageName: "mirror.org/library/test-image:test"},
{name: "mirror no match", signTL: true, policyDir: PassMirrorPolicyDir, imageName: "incorrect.org/library/test-image:test", expectError: true},
}
attIdx, err := oci.IndexFromPath(UnsignedTestImage)
assert.NoError(t, err)
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
opts := &attestation.SigningOptions{
SkipTL: tc.signTL,
}
signedManifests, err := SignStatements(ctx, attIdx.Index, signer, opts)
require.NoError(t, err)
signedIndex := attIdx.Index
signedIndex, err = attestation.UpdateIndexImages(signedIndex, signedManifests, attestation.WithReplacedLayers(true))
require.NoError(t, err)
imageName := tc.imageName
if imageName == "" {
imageName = attIdx.Name
}
// output signed attestations
idx := v1.ImageIndex(empty.Index)
idx = mutate.AppendManifests(idx, mutate.IndexAddendum{
Add: signedIndex,
Descriptor: v1.Descriptor{
Annotations: map[string]string{
oci.OciReferenceTarget: imageName,
},
},
})
_, err = layout.Write(outputLayout, idx)
assert.NoError(t, err)
policyOpts := &policy.PolicyOptions{
LocalPolicyDir: tc.policyDir,
}
src, err := oci.ParseImageSpec("oci://"+outputLayout, oci.WithPlatform(LinuxAMD64))
require.NoError(t, err)
results, err := Verify(ctx, src, policyOpts)
if tc.expectError {
require.Error(t, err)
return
}
require.NoError(t, err)
assert.Equal(t, OutcomeSuccess, results.Outcome)
platform, err := oci.ParsePlatform(LinuxAMD64)
require.NoError(t, err)
expectedPURL, _, err := oci.RefToPURL(attIdx.Name, platform)
require.NoError(t, err)
assert.Equal(t, expectedPURL, results.Input.Purl)
})
}
}

View File

@@ -1,324 +0,0 @@
package attestation
import (
"context"
"encoding/json"
"fmt"
"maps"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/empty"
"github.com/google/go-containerregistry/pkg/v1/match"
"github.com/google/go-containerregistry/pkg/v1/mutate"
"github.com/google/go-containerregistry/pkg/v1/partial"
"github.com/google/go-containerregistry/pkg/v1/static"
"github.com/google/go-containerregistry/pkg/v1/types"
intoto "github.com/in-toto/in-toto-golang/in_toto"
"github.com/secure-systems-lab/go-securesystemslib/dsse"
)
// GetAttestationManifestsFromIndex extracts all attestation manifests from an index
func GetAttestationManifestsFromIndex(index v1.ImageIndex) ([]*AttestationManifest, error) {
idx, err := index.IndexManifest()
if err != nil {
return nil, fmt.Errorf("failed to extract IndexManifest from ImageIndex: %w", err)
}
subjects := make(map[string]*v1.Descriptor)
for _, subject := range idx.Manifests {
subjects[subject.Digest.String()] = &subject
}
var attestationManifests []*AttestationManifest
for _, desc := range idx.Manifests {
if desc.Annotations[DockerReferenceType] == AttestationManifestType {
subject := subjects[desc.Annotations[DockerReferenceDigest]]
if subject == nil {
return nil, fmt.Errorf("failed to find subject for attestation manifest: %w", err)
}
attestationImage, err := index.Image(desc.Digest)
if err != nil {
return nil, fmt.Errorf("failed to extract attestation image with digest %s: %w", desc.Digest.String(), err)
}
attestationLayers, err := GetAttestationsFromImage(attestationImage)
if err != nil {
return nil, fmt.Errorf("failed to get attestations from image: %w", err)
}
attestationManifests = append(attestationManifests,
&AttestationManifest{
OriginalDescriptor: &desc,
SubjectDescriptor: subject,
OriginalLayers: attestationLayers})
}
}
return attestationManifests, nil
}
// GetAttestationsFromImage extracts all attestation layers from an image
func GetAttestationsFromImage(image v1.Image) ([]*AttestationLayer, error) {
layers, err := image.Layers()
if err != nil {
return nil, fmt.Errorf("failed to extract layers from image: %w", err)
}
var attestationLayers []*AttestationLayer
for _, layer := range layers {
// parse layer blob as json
r, err := layer.Uncompressed()
if err != nil {
return nil, fmt.Errorf("failed to get layer contents: %w", err)
}
defer r.Close()
mt, err := layer.MediaType()
if err != nil {
return nil, fmt.Errorf("failed to get layer media type: %w", err)
}
layerDesc, err := partial.Descriptor(layer)
if err != nil {
return nil, fmt.Errorf("failed to get descriptor for layer: %w", err)
}
// copy original annotations
ann := maps.Clone(layerDesc.Annotations)
// only decode intoto statements
var stmt = new(intoto.Statement)
if mt == types.MediaType(intoto.PayloadType) {
err = json.NewDecoder(r).Decode(&stmt)
if err != nil {
return nil, fmt.Errorf("failed to decode statement layer contents: %w", err)
}
}
attestationLayers = append(attestationLayers, &AttestationLayer{Layer: layer, Statement: stmt, Annotations: ann})
}
return attestationLayers, nil
}
func (manifest *AttestationManifest) AddAttestation(ctx context.Context, signer dsse.SignerVerifier, statement *intoto.Statement, opts *SigningOptions) error {
layer, err := createSignedImageLayer(ctx, statement, signer, opts)
if err != nil {
return fmt.Errorf("failed to create signed layer: %w", err)
}
manifest.SignedLayers = append(manifest.SignedLayers, layer)
return nil
}
func createSignedImageLayer(ctx context.Context, statement *intoto.Statement, signer dsse.SignerVerifier, opts *SigningOptions) (*AttestationLayer, error) {
// sign the statement
env, err := SignInTotoStatement(ctx, statement, signer, opts)
if err != nil {
return nil, fmt.Errorf("failed to sign statement: %w", err)
}
mediaType, err := DSSEMediaType(statement.PredicateType)
if err != nil {
return nil, fmt.Errorf("failed to get DSSE media type: %w", err)
}
data, err := json.Marshal(env)
if err != nil {
return nil, fmt.Errorf("failed to marshal envelope: %w", err)
}
return &AttestationLayer{
Statement: statement,
Annotations: map[string]string{
InTotoPredicateType: statement.PredicateType,
InTotoReferenceLifecycleStage: LifecycleStageExperimental,
},
Layer: static.NewLayer(data, types.MediaType(mediaType)),
}, nil
}
func SignInTotoStatement(ctx context.Context, statement *intoto.Statement, signer dsse.SignerVerifier, opts *SigningOptions) (*Envelope, error) {
payload, err := json.Marshal(statement)
if err != nil {
return nil, fmt.Errorf("failed to marshal statement: %w", err)
}
env, err := SignDSSE(ctx, payload, signer, opts)
if err != nil {
return nil, fmt.Errorf("failed to sign statement: %w", err)
}
return env, nil
}
func UpdateIndexImage(
idx v1.ImageIndex,
manifest *AttestationManifest,
options ...func(*AttestationManifestImageOptions) error) (v1.ImageIndex, error) {
image, err := manifest.BuildAttestationImage(options...)
if err != nil {
return nil, fmt.Errorf("failed to build image: %w", err)
}
newDesc, err := partial.Descriptor(image)
if err != nil {
return nil, fmt.Errorf("failed to get descriptor: %w", err)
}
newDesc.Platform = &v1.Platform{
Architecture: "unknown",
OS: "unknown",
}
newDesc.MediaType = manifest.OriginalDescriptor.MediaType
newDesc.Annotations = manifest.OriginalDescriptor.Annotations
idx = mutate.RemoveManifests(idx, match.Digests(manifest.OriginalDescriptor.Digest))
idx = mutate.AppendManifests(idx, mutate.IndexAddendum{
Add: image,
Descriptor: *newDesc,
})
return idx, nil
}
func UpdateIndexImages(idx v1.ImageIndex, manifest []*AttestationManifest, options ...func(*AttestationManifestImageOptions) error) (v1.ImageIndex, error) {
var err error
for _, m := range manifest {
idx, err = UpdateIndexImage(idx, m, options...)
if err != nil {
return nil, fmt.Errorf("failed to add image to index: %w", err)
}
}
return idx, nil
}
func newOptions(options ...func(*AttestationManifestImageOptions) error) (*AttestationManifestImageOptions, error) {
opts := &AttestationManifestImageOptions{}
for _, opt := range options {
err := opt(opts)
if err != nil {
return nil, err
}
}
return opts, nil
}
func WithoutSubject(skipSubject bool) func(*AttestationManifestImageOptions) error {
return func(r *AttestationManifestImageOptions) error {
r.skipSubject = skipSubject
return nil
}
}
func WithReplacedLayers(replaceLayers bool) func(*AttestationManifestImageOptions) error {
return func(r *AttestationManifestImageOptions) error {
r.replaceLayers = replaceLayers
return nil
}
}
// build an image with signed attestations, optionally replacing existing layers with signed layers
func (manifest *AttestationManifest) BuildAttestationImage(options ...func(*AttestationManifestImageOptions) error) (v1.Image, error) {
opts, err := newOptions(options...)
if err != nil {
return nil, fmt.Errorf("failed to create options: %w", err)
}
resultLayers := manifest.SignedLayers
for _, existingLayer := range manifest.OriginalLayers {
var found bool
for _, signedLayer := range manifest.SignedLayers {
if existingLayer.Statement == signedLayer.Statement {
found = true
// copy over original annotations
for k, v := range existingLayer.Annotations {
signedLayer.Annotations[k] = v
}
break
}
}
//add existing layers if they've not been signed or we're not replacing them
if !found || !opts.replaceLayers {
resultLayers = append(resultLayers, existingLayer)
}
}
// so taht we attach all attestations to a single attestations image - as per current buildkit
opts.laxReferrers = true
newImg, err := buildImage(resultLayers, manifest.OriginalDescriptor, manifest.SubjectDescriptor, opts)
if err != nil {
return nil, fmt.Errorf("failed to build image: %w", err)
}
return newImg, nil
}
// build an image per attestation (layer) suitable for use as Referrers
func (manifest *AttestationManifest) BuildReferringArtifacts() ([]v1.Image, error) {
var images []v1.Image
for _, layer := range manifest.SignedLayers {
opts := &AttestationManifestImageOptions{}
newImg, err := buildImage([]*AttestationLayer{layer}, manifest.OriginalDescriptor, manifest.SubjectDescriptor, opts)
if err != nil {
return nil, fmt.Errorf("failed to build image: %w", err)
}
images = append(images, newImg)
}
return images, nil
}
// build and image containing only layers
func buildImage(layers []*AttestationLayer, manifest *v1.Descriptor, subject *v1.Descriptor, opts *AttestationManifestImageOptions) (v1.Image, error) {
newImg := empty.Image
var err error
if len(layers) == 0 {
return nil, fmt.Errorf("no layers supplied to build image")
}
// NB: if we add the subject before the layers, it does not end up being computed/serialised in the output for some reason
//TODO - recreate this bug and push upstream
for _, layer := range layers {
add := mutate.Addendum{
Layer: layer.Layer,
Annotations: layer.Annotations,
}
newImg, err = mutate.Append(newImg, add)
if err != nil {
return nil, fmt.Errorf("failed to add layer to image: %w", err)
}
}
// this is for attaching attestations to an attestation image in the index
if opts.laxReferrers {
newImg = mutate.ConfigMediaType(newImg, "application/vnd.oci.image.config.v1+json")
} else {
dsseMediatType, err := DSSEMediaType(layers[0].Statement.PredicateType)
if err != nil {
return nil, fmt.Errorf("failed to get DSSE media type: %w", err)
}
newImg = mutate.ArtifactType(newImg, dsseMediatType)
newImg = mutate.ConfigMediaType(newImg, "application/vnd.oci.empty.v1+json")
}
// we need to set this even when we set the artifact type otherwise things break (even the go-container-registry client)
// even though it's allowed to be empty by spec when setting artifact type
newImg = mutate.MediaType(newImg, manifest.MediaType)
// see note above - must be added after the layers!
if !opts.skipSubject {
subject.Platform = nil
newImg = mutate.Subject(newImg, *subject).(v1.Image)
}
if !opts.laxReferrers {
// as per https://github.com/opencontainers/image-spec/blob/main/manifest.md#guidance-for-an-empty-descriptor
newImg = &EmptyConfigImage{newImg}
}
return newImg, nil
}
type EmptyConfigImage struct {
v1.Image
}
func (i *EmptyConfigImage) RawConfigFile() ([]byte, error) {
return []byte("{}"), nil
}
func (i *EmptyConfigImage) Manifest() (*v1.Manifest, error) {
mf, err := i.Image.Manifest()
if err != nil {
return nil, fmt.Errorf("failed to get manifest: %w", err)
}
mf.Config = v1.Descriptor{
MediaType: "application/vnd.oci.empty.v1+json",
Size: 2,
Digest: v1.Hash{Algorithm: "sha256", Hex: "44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a"},
Data: []byte("{}"),
}
return mf, nil
}
func (i *EmptyConfigImage) RawManifest() ([]byte, error) {
mf, err := i.Manifest()
if err != nil {
return nil, fmt.Errorf("failed to get manifest: %w", err)
}
return json.Marshal(mf)
}

View File

@@ -1,151 +0,0 @@
package attestation_test
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"encoding/json"
"fmt"
"testing"
"time"
"github.com/docker/attest/internal/test"
"github.com/docker/attest/pkg/attestation"
"github.com/docker/attest/pkg/signerverifier"
intoto "github.com/in-toto/in-toto-golang/in_toto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestSignVerifyAttestation(t *testing.T) {
ctx, signer := test.Setup(t)
stmt := &intoto.Statement{
StatementHeader: intoto.StatementHeader{
Type: intoto.StatementInTotoV01,
PredicateType: intoto.PredicateSPDX,
},
Predicate: "test",
}
payload, err := json.Marshal(stmt)
require.NoError(t, err)
opts := &attestation.SigningOptions{}
env, err := attestation.SignDSSE(ctx, payload, signer, opts)
require.NoError(t, err)
// marshal envelope to json to test for bugs when marshaling envelope data
serializedEnv, err := json.Marshal(env)
require.NoError(t, err)
deserializedEnv := new(attestation.Envelope)
err = json.Unmarshal(serializedEnv, deserializedEnv)
require.NoError(t, err)
// signer.Public() calls AWS API when using AWS signer, use attestation.GetPublicVerificationKey() to get key from TUF repo
// signer.Public() used here for test purposes
ecPub, ok := signer.Public().(*ecdsa.PublicKey)
assert.True(t, ok)
pem, err := signerverifier.ToPEM(ecPub)
assert.NoError(t, err)
keyId, err := signerverifier.KeyID(ecPub)
assert.NoError(t, err)
badKeyPriv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
require.NoError(t, err)
badKey := &badKeyPriv.PublicKey
badPEM, err := signerverifier.ToPEM(badKey)
require.NoError(t, err)
testCases := []struct {
name string
keyId string
pem []byte
distrust bool
from time.Time
to *time.Time
status string
expectedError string
}{
{
name: "all OK",
keyId: keyId,
pem: pem,
distrust: false,
from: time.Time{},
to: nil,
status: "active",
expectedError: "",
},
{
name: "key not found",
keyId: "someotherkey",
pem: pem,
distrust: false,
from: time.Time{},
to: nil,
status: "active",
expectedError: fmt.Sprintf("key not found: %s", keyId),
},
{
name: "key distrusted",
keyId: keyId,
pem: pem,
distrust: true,
from: time.Time{},
to: nil,
status: "active",
expectedError: "distrusted",
},
{
name: "key not yet valid",
keyId: keyId,
pem: pem,
distrust: false,
from: time.Now().Add(time.Hour),
to: nil,
status: "active",
expectedError: "not yet valid",
},
{
name: "key already revoked",
keyId: keyId,
pem: pem,
distrust: false,
from: time.Time{},
to: new(time.Time),
status: "revoked",
expectedError: "already revoked",
},
{
name: "bad key",
keyId: keyId,
pem: badPEM,
distrust: false,
from: time.Time{},
to: nil,
status: "active",
expectedError: "signature is not valid",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
keyMeta := attestation.KeyMetadata{
ID: tc.keyId,
PEM: string(tc.pem),
Distrust: tc.distrust,
From: tc.from,
To: tc.to,
Status: tc.status,
}
opts := &attestation.VerifyOptions{
Keys: attestation.Keys{keyMeta},
}
_, err = attestation.VerifyDSSE(ctx, deserializedEnv, opts)
if tc.expectedError != "" {
assert.Contains(t, err.Error(), tc.expectedError)
} else {
assert.NoError(t, err)
}
})
}
}

View File

@@ -1,101 +0,0 @@
package attestation
import (
"encoding/base64"
"fmt"
v1 "github.com/google/go-containerregistry/pkg/v1"
intoto "github.com/in-toto/in-toto-golang/in_toto"
v02 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2"
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
)
const (
DockerReferenceType = "vnd.docker.reference.type"
AttestationManifestType = "attestation-manifest"
InTotoPredicateType = "in-toto.io/predicate-type"
DockerReferenceDigest = "vnd.docker.reference.digest"
DockerDsseExtKind = "application/vnd.docker.attestation-verification.v1+json"
RekorTlExtKind = "Rekor"
OCIDescriptorDSSEMediaType = ociv1.MediaTypeDescriptor + "+dsse"
InTotoReferenceLifecycleStage = "vnd.docker.lifecycle-stage"
LifecycleStageExperimental = "experimental"
)
var base64Encoding = base64.StdEncoding.Strict()
type AttestationLayer struct {
Statement *intoto.Statement
Layer v1.Layer
Annotations map[string]string
}
type AttestationManifest struct {
OriginalDescriptor *v1.Descriptor
OriginalLayers []*AttestationLayer
// accumulated during signing
SignedLayers []*AttestationLayer
// details of subect image
SubjectName string
SubjectDescriptor *v1.Descriptor
}
type AttestationManifestImageOptions struct {
// how to output the image
skipSubject bool
replaceLayers bool
laxReferrers bool
}
// the following types are needed until https://github.com/secure-systems-lab/dsse/pull/61 is merged
type Envelope struct {
PayloadType string `json:"payloadType"`
Payload string `json:"payload"`
Signatures []Signature `json:"signatures"`
}
type Signature struct {
KeyID string `json:"keyid"`
Sig string `json:"sig"`
Extension Extension `json:"extension,omitempty"`
}
type Extension struct {
Kind string `json:"kind"`
Ext DockerDsseExtension `json:"ext"`
}
type DockerDsseExtension struct {
Tl DockerTlExtension `json:"tl"`
}
type DockerTlExtension struct {
Kind string `json:"kind"`
Data any `json:"data"`
}
type VerifyOptions struct {
Keys []KeyMetadata `json:"keys"`
SkipTL bool `json:"skip_tl"`
}
type SigningOptions struct {
// don't log to the configured transparency log
SkipTL bool
}
func DSSEMediaType(predicateType string) (string, error) {
var predicateName string
switch predicateType {
case v02.PredicateSLSAProvenance:
predicateName = "provenance"
case intoto.PredicateSPDX:
predicateName = "spdx"
case VSAPredicateType:
predicateName = "verification_summary"
default:
return "", fmt.Errorf("unknown predicate type %q", predicateType)
}
return fmt.Sprintf("application/vnd.in-toto.%s+dsse", predicateName), nil
}

View File

@@ -1,137 +0,0 @@
package attestation
import (
"context"
"crypto/ecdsa"
"crypto/x509"
"encoding/base64"
"encoding/json"
"fmt"
"time"
"github.com/docker/attest/internal/util"
"github.com/docker/attest/pkg/signerverifier"
"github.com/docker/attest/pkg/tlog"
intoto "github.com/in-toto/in-toto-golang/in_toto"
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/secure-systems-lab/go-securesystemslib/dsse"
)
type KeyMetadata struct {
ID string `json:"id"`
PEM string `json:"key"`
From time.Time `json:"from"`
To *time.Time `json:"to"`
Status string `json:"status"`
SigningFormat string `json:"signing-format"`
Distrust bool `json:"distrust,omitempty"`
}
type Keys []KeyMetadata
type KeysMap map[string]KeyMetadata
func VerifyDSSE(ctx context.Context, env *Envelope, opts *VerifyOptions) ([]byte, error) {
// enforce payload type
if !ValidPayloadType(env.PayloadType) {
return nil, fmt.Errorf("unsupported payload type %s", env.PayloadType)
}
if len(env.Signatures) == 0 {
return nil, fmt.Errorf("no signatures found")
}
payload, err := base64Encoding.DecodeString(env.Payload)
if err != nil {
return nil, fmt.Errorf("error failed to decode payload: %w", err)
}
encPayload := dsse.PAE(env.PayloadType, payload)
// verify signatures and transparency log entry
for _, sig := range env.Signatures {
err := verifySignature(ctx, sig, encPayload, opts)
if err != nil {
return nil, err
}
}
return payload, nil
}
func verifySignature(ctx context.Context, sig Signature, payload []byte, opts *VerifyOptions) error {
keys := make(map[string]KeyMetadata, len(opts.Keys))
for _, key := range opts.Keys {
keys[key.ID] = key
}
keyMeta, ok := keys[sig.KeyID]
if !ok {
return fmt.Errorf("error key not found: %s", sig.KeyID)
}
if keyMeta.Distrust {
return fmt.Errorf("key %s is distrusted", keyMeta.ID)
}
// TODO: this is unmarshalling with MarshalPKIXPublicKey only for us to marshal it again
publicKey, err := signerverifier.Parse([]byte(keyMeta.PEM))
if err != nil {
return fmt.Errorf("failed to parse public key: %w", err)
}
if !opts.SkipTL {
t := tlog.GetTL(ctx)
if sig.Extension.Kind == "" {
return fmt.Errorf("error missing signature extension kind")
}
if sig.Extension.Kind != DockerDsseExtKind {
return fmt.Errorf("error unsupported signature extension kind: %s", sig.Extension.Kind)
}
// verify TL entry
if sig.Extension.Ext.Tl.Kind != RekorTlExtKind {
return fmt.Errorf("error unsupported TL extension kind: %s", sig.Extension.Ext.Tl.Kind)
}
entry := sig.Extension.Ext.Tl.Data
entryBytes, err := json.Marshal(entry)
if err != nil {
return fmt.Errorf("failed to marshal TL entry: %w", err)
}
integratedTime, err := t.VerifyLogEntry(ctx, entryBytes)
if err != nil {
return fmt.Errorf("TL entry failed verification: %w", err)
}
if integratedTime.Before(keyMeta.From) {
return fmt.Errorf("key %s was not yet valid at TL log time %s (key valid from %s)", keyMeta.ID, integratedTime, keyMeta.From)
}
if keyMeta.To != nil && !integratedTime.Before(*keyMeta.To) {
return fmt.Errorf("key %s was already %s at TL log time %s (key %s at %s)", keyMeta.ID, keyMeta.Status, integratedTime, keyMeta.Status, *keyMeta.To)
}
// verify TL entry payload
encodedPub, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return fmt.Errorf("error failed to marshal public key: %w", err)
}
err = t.VerifyEntryPayload(entryBytes, payload, encodedPub)
if err != nil {
return fmt.Errorf("TL entry failed payload verification: %w", err)
}
}
// decode signature
signature, err := base64.StdEncoding.Strict().DecodeString(sig.Sig)
if err != nil {
return fmt.Errorf("error failed to decode signature: %w", err)
}
// verify payload ecdsa signature
ok = ecdsa.VerifyASN1(publicKey, util.SHA256(payload), signature)
if !ok {
return fmt.Errorf("payload signature is not valid")
}
return nil
}
func ValidPayloadType(payloadType string) bool {
return payloadType == intoto.PayloadType || payloadType == ociv1.MediaTypeDescriptor
}

View File

@@ -1,49 +0,0 @@
package attestation
import (
"fmt"
intoto "github.com/in-toto/in-toto-golang/in_toto"
"github.com/package-url/packageurl-go"
)
const (
VSAPredicateType = "https://slsa.dev/verification_summary/v1"
)
type VSAPredicate struct {
Verifier VSAVerifier `json:"verifier"`
TimeVerified string `json:"timeVerified"`
ResourceUri string `json:"resourceUri"`
Policy VSAPolicy `json:"policy"`
InputAttestations []VSAInputAttestation `json:"inputAttestations"`
VerificationResult string `json:"verificationResult"`
VerifiedLevels []string `json:"verifiedLevels"`
}
type VSAVerifier struct {
ID string `json:"id"`
}
type VSAPolicy struct {
URI string `json:"uri"`
}
type VSAInputAttestation struct {
Digest map[string]string `json:"digest"`
MediaType string `json:"mediaType"`
}
func ToVSAResourceURI(sub intoto.Subject) (string, error) {
//parse purl
purl, err := packageurl.FromString(sub.Name)
if err != nil {
return "", fmt.Errorf("failed to parse package url: %w", err)
}
quals := purl.Qualifiers.Map()
if quals["digest"] == "" {
quals["digest"] = "sha256:" + sub.Digest["sha256"]
}
purl.Qualifiers = packageurl.QualifiersFromMap(quals)
return purl.String(), nil
}

View File

@@ -1,77 +0,0 @@
package config
import (
"fmt"
"os"
"path/filepath"
"regexp"
"github.com/docker/attest/pkg/tuf"
goyaml "gopkg.in/yaml.v3"
)
const (
MappingFilename = "mapping.yaml"
)
func LoadLocalMappings(configDir string) (*PolicyMappings, error) {
if configDir == "" {
return nil, nil
}
mappings := &policyMappingsFile{}
path := filepath.Join(configDir, MappingFilename)
mappingFile, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("failed to read local policy mapping file %s: %w", path, err)
}
err = goyaml.Unmarshal(mappingFile, mappings)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal policy mapping file %s: %w", path, err)
}
return expandMappingFile(mappings)
}
func LoadTufMappings(tufClient tuf.TUFClient, localTargetsDir string) (*PolicyMappings, error) {
if tufClient == nil {
return nil, fmt.Errorf("tuf client not set")
}
filename := MappingFilename
_, fileContents, err := tufClient.DownloadTarget(filename, filepath.Join(localTargetsDir, filename))
if err != nil {
return nil, fmt.Errorf("failed to download policy mapping file %s: %w", filename, err)
}
mappings := &policyMappingsFile{}
err = goyaml.Unmarshal(fileContents, mappings)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal policy mapping file %s: %w", filename, err)
}
return expandMappingFile(mappings)
}
func expandMappingFile(mappingFile *policyMappingsFile) (*PolicyMappings, error) {
policies := make(map[string]*PolicyMapping)
for _, policy := range mappingFile.Policies {
policies[policy.Id] = policy
}
var rules []*PolicyRule
for _, rule := range mappingFile.Rules {
r, err := regexp.Compile(rule.Pattern)
if err != nil {
return nil, err
}
rules = append(rules, &PolicyRule{
Pattern: r,
PolicyId: rule.PolicyId,
Replacement: rule.Replacement,
})
}
return &PolicyMappings{
Version: mappingFile.Version,
Kind: mappingFile.Kind,
Policies: policies,
Rules: rules,
}, nil
}

View File

@@ -1,52 +0,0 @@
package config
import "regexp"
type policyMappingsFile struct {
Version string `yaml:"version"`
Kind string `yaml:"kind"`
Policies []*PolicyMapping `yaml:"policies"`
Rules []*policyRuleFile `yaml:"rules"`
}
type policyRuleFile struct {
Pattern string `yaml:"pattern"`
PolicyId string `yaml:"policy-id"`
Replacement string `yaml:"rewrite"`
}
type PolicyMappings struct {
Version string
Kind string
Policies map[string]*PolicyMapping
Rules []*PolicyRule
}
type AttestationStyle string
const (
AttestationStyleAttached AttestationStyle = "attached"
AttestationStyleReferrers AttestationStyle = "referrers"
)
type PolicyMapping struct {
Id string `yaml:"id"`
Description string `yaml:"description"`
Files []PolicyMappingFile `yaml:"files"`
Attestations *AttestationConfig `yaml:"attestations"`
}
type AttestationConfig struct {
Style AttestationStyle `yaml:"style"`
Repo string `yaml:"repo"`
}
type PolicyMappingFile struct {
Path string `yaml:"path"`
}
type PolicyRule struct {
Pattern *regexp.Regexp
PolicyId string
Replacement string
}

View File

@@ -1,34 +0,0 @@
//go:build e2e
package mirror_test
import (
"path/filepath"
"testing"
"github.com/docker/attest/pkg/mirror"
"github.com/docker/attest/pkg/oci"
"github.com/stretchr/testify/require"
)
func TestRegistryAuth(t *testing.T) {
UnsignedTestImage := filepath.Join("..", "..", "test", "testdata", "unsigned-test-image")
attIdx, err := oci.IndexFromPath(UnsignedTestImage)
require.NoError(t, err)
// test cases for ecr, gcr and dockerhub
testCases := []struct {
Image string
}{
{Image: "175142243308.dkr.ecr.us-east-1.amazonaws.com/e2e-test-image:latest"},
{Image: "docker/image-signer-verifier-test:latest"},
}
for _, tc := range testCases {
t.Run(tc.Image, func(t *testing.T) {
err := mirror.PushIndexToRegistry(attIdx.Index, tc.Image)
require.NoError(t, err)
_, err = oci.IndexFromRemote(tc.Image)
require.NoError(t, err)
})
}
}

View File

@@ -1,111 +0,0 @@
package mirror
import (
"fmt"
"net/http/httptest"
"net/url"
"path/filepath"
"testing"
"github.com/docker/attest/internal/test"
"github.com/docker/attest/pkg/attest"
"github.com/docker/attest/pkg/attestation"
"github.com/docker/attest/pkg/oci"
"github.com/google/go-containerregistry/pkg/registry"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/empty"
intoto "github.com/in-toto/in-toto-golang/in_toto"
"github.com/stretchr/testify/require"
)
func TestSavingIndex(t *testing.T) {
UnsignedTestImage := filepath.Join("..", "..", "test", "testdata", "unsigned-test-image")
outputLayout := test.CreateTempDir(t, "", "mirror-test")
attIdx, err := oci.IndexFromPath(UnsignedTestImage)
require.NoError(t, err)
server := httptest.NewServer(registry.New())
defer server.Close()
u, err := url.Parse(server.URL)
require.NoError(t, err)
indexName := fmt.Sprintf("%s/repo:root", u.Host)
output, err := oci.ParseImageSpecs(indexName)
require.NoError(t, err)
err = SaveIndex(output, attIdx.Index, indexName)
require.NoError(t, err)
ociOutput, err := oci.ParseImageSpecs("oci://" + outputLayout)
require.NoError(t, err)
err = SaveIndex(ociOutput, attIdx.Index, indexName)
require.NoError(t, err)
}
func TestSavingImage(t *testing.T) {
outputLayout := test.CreateTempDir(t, "", "mirror-test")
img := empty.Image
server := httptest.NewServer(registry.New())
defer server.Close()
u, err := url.Parse(server.URL)
require.NoError(t, err)
indexName := fmt.Sprintf("%s/repo:root", u.Host)
output, err := oci.ParseImageSpec(indexName)
require.NoError(t, err)
err = SaveImage(output, img, indexName)
require.NoError(t, err)
ociOutput, err := oci.ParseImageSpec("oci://" + outputLayout)
require.NoError(t, err)
err = SaveImage(ociOutput, img, indexName)
require.NoError(t, err)
}
func TestSavingReferrers(t *testing.T) {
ctx, signer := test.Setup(t)
opts := &attestation.SigningOptions{}
statement := &intoto.Statement{
StatementHeader: intoto.StatementHeader{
PredicateType: attestation.VSAPredicateType,
},
}
digest, err := v1.NewHash("sha256:da8b190665956ea07890a0273e2a9c96bfe291662f08e2860e868eef69c34620")
require.NoError(t, err)
subject := &v1.Descriptor{
MediaType: "application/vnd.oci.image.manifest.v1+json",
Digest: digest,
}
manifest, err := attest.NewAttestationManifest(subject)
require.NoError(t, err)
err = manifest.AddAttestation(ctx, signer, statement, opts)
require.NoError(t, err)
server := httptest.NewServer(registry.New(registry.WithReferrersSupport(true)))
defer server.Close()
u, err := url.Parse(server.URL)
require.NoError(t, err)
indexName := fmt.Sprintf("%s/repo:root", u.Host)
output, err := oci.ParseImageSpecs(indexName)
require.NoError(t, err)
err = SaveReferrers(manifest, output)
require.NoError(t, err)
reg := &test.MockRegistryResolver{
Subject: subject,
MockResolver: &test.MockResolver{},
ImageNameStr: indexName,
}
require.NoError(t, err)
refResolver, err := oci.NewReferrersAttestationResolver(reg)
require.NoError(t, err)
attestations, err := refResolver.Attestations(ctx, attestation.VSAPredicateType)
require.NoError(t, err)
require.Len(t, attestations, 1)
}

View File

@@ -1,49 +0,0 @@
package mirror
import (
"github.com/docker/attest/pkg/tuf"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/theupdateframework/go-tuf/v2/metadata"
)
const (
DefaultMetadataURL = "https://docker.github.io/tuf/metadata"
DefaultTargetsURL = "https://docker.github.io/tuf/targets"
tufMetadataMediaType = "application/vnd.tuf.metadata+json"
tufTargetMediaType = "application/vnd.tuf.target"
tufFileAnnotation = "tuf.io/filename"
)
type TufRole string
var TufRoles = []TufRole{metadata.ROOT, metadata.SNAPSHOT, metadata.TARGETS, metadata.TIMESTAMP}
type TufMetadata struct {
Root map[string][]byte
Snapshot map[string][]byte
Targets map[string][]byte
Timestamp []byte
}
type DelegatedTargetMetadata struct {
Name string
Version string
Data []byte
}
type MirrorImage struct {
Image v1.Image
Tag string
}
type MirrorIndex struct {
Index v1.ImageIndex
Tag string
}
type TufMirror struct {
TufClient *tuf.TufClient
tufPath string
metadataURL string
targetsURL string
}

View File

@@ -1,21 +0,0 @@
package oci
import (
ecr "github.com/awslabs/amazon-ecr-credential-helper/ecr-login"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/v1/google"
"github.com/google/go-containerregistry/pkg/v1/remote"
)
func MultiKeychainOption() remote.Option {
return remote.WithAuthFromKeychain(MultiKeychainAll())
}
func MultiKeychainAll() authn.Keychain {
// Create a multi-keychain that will use the default Docker, Google, or ECR keychain
return authn.NewMultiKeychain(
authn.DefaultKeychain,
google.Keychain,
authn.NewKeychainFromHelper(ecr.NewECRHelper()),
)
}

View File

@@ -1,27 +0,0 @@
package oci
import (
"net/http"
"github.com/hashicorp/go-cleanhttp"
)
type userAgentTransporter struct {
ua string
rt http.RoundTripper
}
type Option = func(*http.Client)
func (u *userAgentTransporter) RoundTrip(req *http.Request) (*http.Response, error) {
req.Header.Set("User-Agent", u.ua)
return u.rt.RoundTrip(req)
}
func HttpTransport() http.RoundTripper {
return &userAgentTransporter{
ua: "Docker-Client",
rt: cleanhttp.DefaultTransport(),
}
}

Some files were not shown because too many files have changed in this diff Show More