# SALT How To…​

The following sections review common needs related to software attestations and how they could be met with SALT.

### Store attestations in my registry of choice

Storing the attestation documents in the central Attestation Registry is optional: organizations might prefer to store attestations (which physically are JSON files) co-located with the software artifacts referenced. For example, attestations related to an image may be stored in the same OCI registry where the container images are stored.

{% hint style="info" %}
There is a project named [ORAS](https://oras.land/docs/) (OCI Registry As Storage) that looks for using OCI Registries for *arbitrary* artifacts, including attestations. You may use its command-line tool to upload attestations to any compatible OCI registry.
{% endhint %}

Other alternatives are to push the attestation as an artifact in your CI/CD, co-located with the product artifact it references, or embedded as metadata in the packaged software artifact itself. The location of the attestation depends on your use-case and how consumers of the software will perform verifications downstream.

To disable automatic upload to the configured central attestation registry, use the `--no-upload` and `--output` options in the `attestation commit | attestation provenance` commands to not upload the attestation to the central registry and instead store it in a local file that could later be published in your registry of choice.

{% hint style="info" %}
Xygeni provides a distribution of the Attestation Registry, so organizations may use their own instance, instead of using the public one. Please contact your Xygeni representative for further information.
{% endhint %}

### Use keyless signatures

To use keyless signing, the `--keyless` option could be passed to the attestation `commit | provenance` commands. This will fetch an OpenID Connect (OIDC) from specific issuers, using an OAuth flow (standard or device).

Jobs running in CI/CD runners use an OIDC provider that authenticates the job and generates an OIDC ID token. The token will be stored either in an environment variable or in a CI/CD file.The variable and the path are configured in the `conf/salt.yaml` file:

```yaml
# Configuration for identity-based ("keyless") certification authority,
# to use for certifying ephemeral public keys.
keylessConfig:
  # The environment variable which may contain a valid OIDC id_token,
  # typically obtained from an OIDC provider in CI/CD systems.
  tokenVar: SIGSTORE_ID_TOKEN
  # The filesystem path where the OIDC token will be loaded
  tokenPath: /var/run/sigstore/cosign/oidc-token
  # ...
```

For interactive usage (e.g. when NOT in a CI/CD pipeline), the end-user is authenticated using the browser against one of the supported OIDC providers (Google, GitHub or Azure), when the token cannot be found in the configured env-var or file:

<figure><img src="https://4096647782-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUTz59rJLkJBjiRWAMknU%2Fuploads%2FBcZPn478lqWmHAmK60ki%2Fimage.png?alt=media&#x26;token=bd58b6ee-f017-4de7-9731-c108c416fb18" alt="" width="251"><figcaption></figcaption></figure>

Example: For **GitLab**, ID tokens could be declared in the GitLab pipeline using the `id_tokens` entry. GitLab will authenticate the running job with the OIDC provider, and place the OIDC ID token in the specified environment variable. For the default environment variable with the token, you may use the default `SIGSTORE_ID_TOKEN`, and set `aud: sigstore` so the JWT token is recognized by Fulcio.

```yaml
generate_attestation_job:
  # GitLab puts the OIDC token in SIGSTORE_ID_TOKEN env-var
  id_tokens:
    SIGSTORE_ID_TOKEN:
      aud: sigstore

  script:
     # salt will fetch from $SIGSTORE_ID_TOKEN
     - salt at slsa --keyless ... rest of command here ...
```

See [OIDC Authentication in GitLab](https://docs.gitlab.com/ee/ci/secrets/id_token_authentication.htm) for further details.

See [Keyless Signing](https://docs.xygeni.io/xygeni-products/build-security-concepts#keyless-signing) for details about how OpenID Connect and OAuth authentication can be used for creating ephemeral keys and certificates that could be trusted for attestation verification.

### Add SBOM and other reports to attestations

The `attestation add` allows you to pass an item to be included in the attestation as the predicate (or part of the compound predicate). There are predicates designed to convey SBOM and reports from security tools as part of an attestation, for example for SBOM formats like CycloneDX and SPDX, or for vulnerability reports from security scanners.

Please read [Available Predicate Types](https://docs.xygeni.io/xygeni-products/attestation-format#available-predicate-types) for further information.

### Set command autocompletion

The `salt` command may export command-line completion (for Bash or ZSH shells only).To install completion, simply run:

```bash
source <(salt generate-completion)
```

Autocompletion helps with writing complex commands, and the `-h |--help` flag makes it easier to build and test the commands for adding software attestations to your pipelines.

### Using the Xygeni Build Attestation Task for Azure Pipelines

The simplest way to run Build Attestation in Azure Pipelines is to use the [Xygeni Build Attestation Task](https://marketplace.visualstudio.com/items?itemName=xygeni-security.xygeni-salt). The task uses the Build Attestation CLI to generate software attestations for your builds.

The API token should be registered safely as a (secret) pipeline variable. If you name the variable `XYGENI_TOKEN`, the task will look for it automatically. Otherwise, you can pass it in an environment variable such as `XYGENI_TOKEN` and set the input property `xygeniToken = 'env:XYGENI_TOKEN'`.

#### Installation

From the [Xygeni Build Attestation Task](https://marketplace.visualstudio.com/items?itemName=xygeni-security.xygeni-salt) in the [Azure DevOps Marketplace](https://marketplace.visualstudio.com/azuredevops), you can install for an Azure DevOps organization by clicking the **Get it free** button. There you select the Azure DevOps organizations where you want to install the task.

For Azure DevOps Server, the task can be downloaded as a `.vsix` file and installed in your Azure DevOps Server Extensions page (For example, `http://someserver/_gallery/manage`). Click upload new extension, select the downloaded `.vsix` file, click Install and select the Team Project Collection to install into.

#### Adding the task as a pipeline step

Edit your pipeline and add the Xygeni Build Attestation task as a pipeline step, using the Task Assistant filter by Xygeni and click Xygeni Build Attestation:

<figure><img src="https://4096647782-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUTz59rJLkJBjiRWAMknU%2Fuploads%2Fgit-blob-9ae49d5787705cc8c2907cbb372f6a64e2f9df84%2Fazure-build-at-task.png?alt=media" alt="" width="251"><figcaption></figcaption></figure>

Edit the attestation properties (1) by choosing the attestation type, the directory to attest, and other configuration options. Then click **Add** button to add the YAML to the pipeline.

By default the XYGENI\_TOKEN pipeline (secret) variable will be used if the `Xygeni API Token` field is not specified.

You can also edit the YAML source directly in the Pipeline Editor. Autocomplete will work to help you fill in the task properties.

<figure><img src="https://4096647782-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUTz59rJLkJBjiRWAMknU%2Fuploads%2Fgit-blob-1434cad85ebc837d27e0b9ea6b6e1e3f9a07e855%2Fsalt-task-edit.png?alt=media" alt="" width="251"><figcaption></figcaption></figure>

#### Task properties

The following is an example of the Xygeni Build Attestation task, including the most relevant parameters for generating SLSA attestations.

```yaml
steps:
# ...Other build steps here...  
  
- task: xygeni-salt@1
  displayName: 'Generate SLSA Attestation with Build Attestation'
  env:
    XYGENI_TOKEN: $(XYGENI_TOKEN)
  inputs:
    command: 'attestation'
    attestationType: 'slsa'
    buildType: 'github_actions'
    sourceDirectory: '$(Build.Repository.LocalPath)'
    xygeniToken: 'env:XYGENI_TOKEN'
    outputFile: '$(Build.ArtifactStagingDirectory)/attestations/slsa.json'
    keyless: true

- task: PublishBuildArtifacts@1
  displayName: 'Publish attestations as artifacts'
  inputs:
    PathtoPublish: '$(Build.ArtifactStagingDirectory)/attestations'
    ArtifactName: 'Build Attestation_Attestations'
```

{% hint style="info" %}
For keyless signing in Azure Pipelines, you may need to configure OIDC authentication. See the [Keyless signatures](#use-keyless-signatures) section above for details on configuring OIDC tokens in your pipeline.
{% endhint %}

#### Using the installation script

Another option is to download and install Build Attestation CLI and run the commands directly. Suppose that the secret `xygeniToken` stores the Xygeni API token. In a Linux runner, you may use the [Bash](https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/reference/bash-v3?view=azure-pipelines) task:

```yaml
steps:
- task: Bash@3
  displayName: 'Install SALT CLI'
  inputs:
    targetType: 'inline'
    script: >
      curl -s -L https://get.xygeni.io/latest/salt/xygeni-salt-linux-amd64.tar.gz -o salt.tar.gz
      tar -xzf salt.tar.gz -C $(Pipeline.Workspace)
      rm salt.tar.gz

- task: Bash@3
  displayName: 'Generate SLSA attestation'
  inputs:
    targetType: 'inline'
    script: |
      echo "Generating SLSA attestation for $(PROJECT_NAME)"
      $(Pipeline.Workspace)/salt attestation slsa \
        --build-type azure_pipelines \
        --source $(Build.SourcesDirectory) \
        --output $(Build.ArtifactStagingDirectory)/attestations/slsa.json \
        --keyless
  env:
    PROJECT_NAME: $(System.TeamProject)
    XYGENI_TOKEN: $(xygeniToken)
```

{% hint style="info" %}
We recommend using the Build Attestation task, as it keeps the CLI cached between runs and makes configuration easier using the Azure Pipelines UI instead of manually editing the pipeline YAML.

Please refer to the [Build Attestation documentation](https://github.com/xygeni/UserDoc/blob/main/xygeni-products/salt-command-line-reference.md) for full details on the SALT command line options and configuration.
{% endhint %}

### Using the Verify Attestation Task for Azure Devops

The Xygeni Verify Attestation Task allows you to verify software attestations in your Azure Pipelines. This task uses the SALT CLI to perform attestation verification, ensuring the integrity and authenticity of your software artifacts.

To add the Verify Attestation task to your Azure Pipeline, edit your pipeline and add the Xygeni Verify Attestation task as a pipeline step:

<figure><img src="https://4096647782-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FUTz59rJLkJBjiRWAMknU%2Fuploads%2Fgit-blob-89048d391da427924ff6ee6d4f3dde5aa52c23c8%2Fazure-verify-at-task.png?alt=media" alt="" width="251"><figcaption></figcaption></figure>

Edit the verification properties by specifying the attestation file, the subject to verify (e.g., container image), and the public key or certificate for verification.

**Using the Installation Script**

Alternatively, you can download and install Build Attestation CLI and run the verify commands directly:

```yaml
steps:

- task: Bash@3
  displayName: 'Verify SLSA attestation'
  inputs:
    targetType: 'inline'
    script: |
      echo "Verifying SLSA attestation for $(PROJECT_NAME)"
      $(Pipeline.Workspace)/salt verify \
        --image=myorg/myimage:my_tag \
        --attestation=$(Build.ArtifactStagingDirectory)/attestations/slsa.json \
        --public-key=$(Build.SourcesDirectory)/certs/ephemeral_cert.crt \
        --keyless
  env:
    PROJECT_NAME: $(System.TeamProject)
```

{% hint style="info" %}
We recommend using the Verify Attestation task, as it keeps the CLI cached between runs and makes configuration easier using the Azure Pipelines UI instead of manually editing the pipeline YAML.

Please refer to the [Build Attestation documentation](https://github.com/xygeni/UserDoc/blob/main/xygeni-products/salt-command-line-reference.md) for full details on the SALT command line options and configuration.
{% endhint %}
