Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
204 changes: 204 additions & 0 deletions VERIFY_ATTESTATIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
# Using artifact attestations to achieve SLSA v1 Build Level 3

This project started to use GitHub Action to create attestations for the release artifacts. Building software with artifact attestation streamlines supply chain security and helps us achieve [SLSA](https://slsa.dev/) v1.0 Build Level 3 for this project.

## Verifying release artifacts attestations with GitHub CLI

> [!WARNING]
> Not all artifacts may have attestations generated for them. Please check the [attestations](https://github.com/integrations/terraform-provider-github/attestations) page for this repository to see which artifacts have attestations available.

> [!CAUTION]
> The attestations are available only for the releases created since the version `v6.9.0` of this project.

### Prerequisites

First, install GitHub CLI if you haven't already. See the [installation instructions](https://github.com/cli/cli#installation) for your platform.

### Verifying attestations

To verify artifact attestations generated during the build process, use the `gh attestation verify` command from the GitHub CLI.

The `gh attestation verify` command requires either `--owner` or `--repo` flags to be used with it.

> [!NOTE]
> Make sure to replace x.y.z with the actual release tag you want to verify.

Download the release artifacts first:

```bash
version="x.y.z"
gh release download "v${version}" --repo integrations/terraform-provider-github -p "*.zip" --clobber
```

To verify the artifact attestations for this project, you can run the following command:

```bash
gh attestation verify --repo integrations/terraform-provider-github --source-ref "refs/tags/v${version}"\
--signer-workflow integrations/terraform-provider-github/.github/workflows/release.yaml@refs/tags/v${version} \
"terraform-provider-github_${version}_darwin_amd64.zip"
```

### Verifying all artifacts at once

Alternatively, you can verify all downloaded artifacts with a loop that provides individual status reporting:

```bash
for artifact in terraform-provider-github_${version}_*.zip; do
echo "Verifying: $artifact"
gh attestation verify --repo integrations/terraform-provider-github --source-ref "refs/tags/v${version}" \
--signer-workflow integrations/terraform-provider-github/.github/workflows/release.yaml@refs/tags/v${version} \
"$artifact" && echo "✓ Verified" || echo "✗ Failed"
done
```

### Using optional flags

The `gh attestation verify` command supports additional flags for more specific verification:

Use the `--signer-repo` flag to specify the repository:

```bash
gh attestation verify --owner integrations --signer-repo \
integrations/terraform-provider-github \
terraform-provider-github_${version}_darwin_amd64.zip
```

If you would like to require an artifact attestation to be signed with a specific workflow, use the `--signer-workflow` flag to indicate the workflow file that should be used.

```bash
gh attestation verify --owner integrations --signer-workflow \
integrations/terraform-provider-github/.github/workflows/release.yaml@refs/tags/v${version} \
terraform-provider-github_${version}_darwin_amd64.zip
```

## Verifying checksums file signature with Cosign and checking artifact integrity

> [!WARNING]
> Not all the releases may have Cosign signature for the checksum files.

> [!CAUTION]
> The Cosign signatures are available only for the releases created since the version `v6.9.0` of this project.

In addition to artifact attestations, you can verify release artifacts using [Cosign](https://docs.sigstore.dev/cosign/overview/). Cosign is a tool for signing and verifying software artifacts and container images.

### Prerequisites

First, install Cosign if you haven't already. See the [installation instructions](https://docs.sigstore.dev/cosign/system_config/installation/) for your platform.

### Verify checksums file

Download the checksums file and its signature bundle:

```bash
gh release download v${version} --repo integrations/terraform-provider-github \
-p "terraform-provider-github_${version}_SHA256SUMS" \
-p "terraform-provider-github_${version}_SHA256SUMS.sbom.json.bundle" --clobber
```

Verify the checksums file signature:

```bash
cosign verify-blob \
--bundle "terraform-provider-github_${version}_SHA256SUMS.sbom.json.bundle" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity "https://github.com/integrations/terraform-provider-github/.github/workflows/release.yaml@refs/tags/v${version}" \
"terraform-provider-github_${version}_SHA256SUMS"
```

### Verify artifact checksums

After verifying the checksums file, verify your downloaded artifacts match the checksums:

Download the artifact you want to verify:

```bash
gh release download v${version} --repo integrations/terraform-provider-github \
-p "terraform-provider-github_${version}_darwin_amd64.zip" --clobber
```

Verify the checksum:

```bash
shasum -a 256 -c terraform-provider-github_${version}_SHA256SUMS --ignore-missing
```

This will verify that your downloaded artifact matches the signed checksum, confirming its integrity and authenticity.

## Verifying SLSA Provenance Attestations with Cosign

In addition to using the GitHub CLI, you can verify SLSA provenance attestations using Cosign by downloading the attestation and verifying it against your local artifact.

### Prerequisites

1. Install `cosign` for verifying attestations. See the [installation instructions](https://docs.sigstore.dev/cosign/system_config/installation/).
2. Install `gh` (GitHub CLI) if you haven't already. See the [installation instructions](https://github.com/cli/cli#installation).

### Download and verify attestation

> [!NOTE]
> Make sure to replace x.y.z with the actual release tag you want to verify.

> [!CAUTION]
> The attestations are available only for the releases created since the version `v6.9.0` of this project.

First, download the artifact you want to verify:

```bash
version="x.y.z"
gh release download "v${version}" --repo integrations/terraform-provider-github \
-p "terraform-provider-github_${version}_darwin_amd64.zip" --clobber
```

Then, download the attestation associated with the artifact:

```bash
gh attestation download "terraform-provider-github_${version}_darwin_amd64.zip" \
--repo integrations/terraform-provider-github
```

This will create a file named `sha256:[digest].jsonl` in the current directory.

Verify the attestation using Cosign:

```bash
# Calculate the digest and verify using the specific bundle file
digest=$(shasum -a 256 "terraform-provider-github_${version}_darwin_amd64.zip" | awk '{ print $1 }')
cosign verify-blob-attestation \
--bundle "sha256:${digest}.jsonl" \
--new-bundle-format \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity "https://github.com/integrations/terraform-provider-github/.github/workflows/release.yaml@refs/tags/v${version}" \
"terraform-provider-github_${version}_darwin_amd64.zip"
```

A successful verification will output `Verified OK`, confirming that the artifact was built by the trusted GitHub Actions workflow and its provenance is securely recorded.

### Verifying all release artifacts

To verify all release artifacts for a specific version:

```bash
version="x.y.z"

# Download all release artifacts
gh release download "v${version}" --repo integrations/terraform-provider-github -p "*.zip" --clobber

# Download attestations for all artifacts
for artifact in terraform-provider-github_${version}_*.zip; do
gh attestation download "$artifact" --repo integrations/terraform-provider-github
done

# Verify all artifacts using specific digest-based bundle files
for artifact in terraform-provider-github_${version}_*.zip; do
echo "Verifying: $artifact"
digest=$(shasum -a 256 "$artifact" | awk '{ print $1 }')
cosign verify-blob-attestation \
--bundle "sha256:${digest}.jsonl" \
--new-bundle-format \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity "https://github.com/integrations/terraform-provider-github/.github/workflows/release.yaml@refs/tags/v${version}" \
"$artifact" > /dev/null && echo "✓ Verified" || echo "✗ Failed"
done
```

This approach calculates the digest for each artifact and uses the corresponding specific bundle file, ensuring each artifact is verified against its own attestation.
28 changes: 23 additions & 5 deletions github/respository_rules_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,10 @@ func expandConditions(input []any, org bool) *github.RulesetConditions {
}
}

protected := inputRepositoryName["protected"].(bool)
protected, ok := inputRepositoryName["protected"].(bool)
if !ok {
protected = false
}

rulesetConditions.RepositoryName = &github.RulesetRepositoryNamesConditionParameters{
Include: include,
Expand Down Expand Up @@ -277,7 +280,10 @@ func expandRules(input []any, org bool) []*github.RepositoryRule {
patternParametersMap := v[0].(map[string]any)

name := patternParametersMap["name"].(string)
negate := patternParametersMap["negate"].(bool)
negate, ok := patternParametersMap["negate"].(bool)
if !ok {
negate = false
}

params := &github.RulePatternParameters{
Name: &name,
Expand Down Expand Up @@ -355,10 +361,17 @@ func expandRules(input []any, org bool) []*github.RepositoryRule {
}
}

doNotEnforceOnCreate := requiredStatusMap["do_not_enforce_on_create"].(bool)
doNotEnforceOnCreate, ok := requiredStatusMap["do_not_enforce_on_create"].(bool)
if !ok {
doNotEnforceOnCreate = false
}
strictRequiredStatusChecksPolicy, ok := requiredStatusMap["strict_required_status_checks_policy"].(bool)
if !ok {
strictRequiredStatusChecksPolicy = false
}
params := &github.RequiredStatusChecksRuleParameters{
RequiredStatusChecks: requiredStatusChecks,
StrictRequiredStatusChecksPolicy: requiredStatusMap["strict_required_status_checks_policy"].(bool),
StrictRequiredStatusChecksPolicy: strictRequiredStatusChecksPolicy,
DoNotEnforceOnCreate: &doNotEnforceOnCreate,
}
rulesSlice = append(rulesSlice, github.NewRequiredStatusChecksRule(params))
Expand Down Expand Up @@ -389,8 +402,13 @@ func expandRules(input []any, org bool) []*github.RepositoryRule {
}
}

doNotEnforceOnCreate, ok := requiredWorkflowsMap["do_not_enforce_on_create"].(bool)
if !ok {
doNotEnforceOnCreate = false
}

params := &github.RequiredWorkflowsRuleParameters{
DoNotEnforceOnCreate: requiredWorkflowsMap["do_not_enforce_on_create"].(bool),
DoNotEnforceOnCreate: doNotEnforceOnCreate,
RequiredWorkflows: requiredWorkflows,
}
rulesSlice = append(rulesSlice, github.NewRequiredWorkflowsRule(params))
Expand Down