github.com/yogeshkumararora/slsa-github-generator@v1.10.1-0.20240520161934-11278bd5afb4/BYOB.md (about)

     1  # Build Your Own Builder (BYOB) Framework
     2  
     3  <!-- toc -->
     4  
     5  - [Design Overview](#design-overview)
     6    - [Project Workflow (PW)](#project-workflow-pw)
     7    - [Tool Repository](#tool-repository)
     8      - [Tool Reusable Workflow (TRW)](#tool-reusable-workflow-trw)
     9      - [Tool Callback Action (TCA)](#tool-callback-action-tca)
    10    - [SLSA GitHub Repository](#slsa-github-repository)
    11      - [SLSA Setup Action (SSA)](#slsa-setup-action-ssa)
    12      - [SLSA Reusable Workflow (SRW)](#slsa-reusable-workflow-srw)
    13  - [Example: Convert a GitHub Action to be SLSA3 Compliant](#example-convert-a-github-action-to-be-slsa3-compliant)
    14    - [Before you begin: understand supported triggers](#before-you-begin-understand-supported-triggers)
    15    - [Step 1: TRW inputs](#step-1-trw-inputs)
    16      - [Inputs](#inputs)
    17      - [Secrets](#secrets)
    18      - [Outputs](#outputs)
    19      - [Important Notes](#important-notes)
    20    - [Step 2: SRW Setup](#step-2-srw-setup)
    21    - [Step 3: SRW Invocation](#step-3-srw-invocation)
    22    - [Step 4: Creating a TCA](#step-4-creating-a-tca)
    23      - [Inputs](#inputs-1)
    24      - [Outputs](#outputs-1)
    25      - [Invocation of Existing Action](#invocation-of-existing-action)
    26      - [Generation of Metadata Layout File](#generation-of-metadata-layout-file)
    27    - [Step 5: Upload Attestations](#step-5-upload-attestations)
    28  - [PW Integration](#pw-integration)
    29    - [PW Call](#pw-call)
    30    - [Provenance Example](#provenance-example)
    31  - [Hardening](#hardening)
    32    - [Least Privileged TCA](#least-privileged-tca)
    33      - [Low-Permission SRW](#low-permission-srw)
    34      - [Update TCA](#update-tca)
    35      - [Update TRW](#update-trw)
    36    - [Best SDLC Practices](#best-sdlc-practices)
    37  
    38  <!-- tocstop -->
    39  
    40  ## Design Overview
    41  
    42  The Build Your Own Builder (BYOB) framework makes it simple to make an existing GitHub Action SLSA3 compliant. Instead of handling the complexity around reuseable workflows, signing, intoto, Sigstore, etc, you can simply delegate orchestration and provenance generation to the BYOB framework.
    43  
    44  The diagram below depicts the different components of the BYOB framework. We'll cover the different portions in our overview.
    45  
    46  ![Screenshot](images/byob-design.png)
    47  
    48  ### Project Workflow (PW)
    49  
    50  The Project Workflow (PW) is hosted in the repository that wants to build an artifact. As part of a build, the PW invokes the SLSA compliant builder defined by the Tool Reuseable Workflow (TRW):
    51  
    52  ```yaml
    53  - uses: npm/builder/.github/workflows/slsa.3.yml@vx.y.z
    54  ```
    55  
    56  The example snippet shows the invocation of a builder with path `.github/workflows/slsa.3.yml` from the GitHub's `npm/builder` repository.
    57  
    58  ### Tool Repository
    59  
    60  The tool repository hosts the builder invoked by PWs. The tool repository MUST be public. The repository contains two components, the Tool Reuseable Workflow and the Tool Callback Action.
    61  
    62  #### Tool Reusable Workflow (TRW)
    63  
    64  The "Tool Reusable Workflow" (TRW) is the SLSA compliant builder that will "wrap" an existing GitHub Action. End users' PWs invoke the TRW to build their artifacts. The TRW workflow file must be created as part of the integration.
    65  
    66  #### Tool Callback Action (TCA)
    67  
    68  The "Tool Callback Action" (TCA) is the GitHub Action that is invoked by the BYOB framework in an isolated GitHub job. The TCA does the following:
    69  
    70  - Sets the environment. For example, if the builder wants to build Go projects, the TCA would install the Go compiler.
    71  - Calls your existing GitHub Action. For example, if the builder wants to make the GoReleaser Action SLSA compliant, the TCA would call the existing `goreleaser/goreleaser-action` after it has set up the environment.
    72  - Outputs attestation metadata (name, binaries and hashes) that are used by the framework to generate SLSA provenance.
    73  
    74  ### SLSA GitHub Repository
    75  
    76  The [slsa-github-generator](https://github.com/yogeshkumararora/slsa-github-generator) repository hosts the code for the BYOB framework maintained by the OpenSSF SLSA tooling team. There are two main components you will use for your integration, the SLSA Setup Action and the SLSA Reuseable Workflow.
    77  
    78  #### SLSA Setup Action (SSA)
    79  
    80  The [setup-generic](https://github.com/yogeshkumararora/slsa-github-generator/blob/main/actions/delegator/setup-generic) Action is used to initialize the BYOB framework. It returns a so-called "SLSA token" which is used in later steps:
    81  
    82  ```yaml
    83  - uses: yogeshkumararora/slsa-github-generator/actions/delegator/setup-generic@v2.0.0
    84  ```
    85  
    86  #### SLSA Reusable Workflow (SRW)
    87  
    88  The SLSA Reuseable Workflow (SRW) acts as the build's orchestrator. It calls the TCA, generates provenance, and returns the provenance to its TRW caller. A TRW would typically call the SRW as follows:
    89  
    90  ```yaml
    91  - uses: yogeshkumararora/slsa-github-generator/.github/workflow/delegator_generic_slsa3.yml@v2.0.0
    92    with:
    93      slsa-token: ${{ needs.slsa-setup.outputs.slsa-token }}
    94  ```
    95  
    96  ## Example: Convert a GitHub Action to be SLSA3 Compliant
    97  
    98  In this example, we will assume there is an existing [GitHub Action](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/action.yml) which builds an artifact.
    99  The Action does the following:
   100  
   101  - [Echos the parameters into the artifact](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/action.yml#L58).
   102  - Takes a [username, password and token](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/action.yml#L31-L34) to retrieve / push information from a remote registry.
   103  - [Releases the built artifact to GitHub releases](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/action.yml#L67-L78) (similarly to popular release Actions).
   104  - Outputs the [name of the built artifact and the status of the build](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/action.yml#L35-L41).
   105  
   106  See the full [action.yml](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/action.yml).
   107  
   108  Some more advanced topics are ommitted for clarity, but can be found in the [Section: Hardening](#hardening). Once you have completed this example and the [provenance example](#provenance-example), we recommend following the steps in [Section: Hardening](#hardening), as it represents best security practice.
   109  
   110  ### Before you begin: understand supported triggers
   111  
   112  Only the following [event types] are supported as recommended by the [SLSA specifications](https://github.com/slsa-framework/github-actions-buildtypes/tree/main/workflow/v1#description):
   113  
   114  | Supported event type  | Event description                          |
   115  | --------------------- | ------------------------------------------ |
   116  | [`create`]            | Creation of a git tag or branch.           |
   117  | [`release`]           | Creation or update of a GitHub release.    |
   118  | [`push`]              | Creation or update of a git tag or branch. |
   119  | [`workflow_dispatch`] | Manual trigger of a workflow.              |
   120  
   121  `pull_request` events are currently not supported. If you would like support for
   122  `pull_request`, please tell us about your use case on
   123  [issue #358](https://github.com/yogeshkumararora/slsa-github-generator/issues/358). If
   124  you have an issue related to any other triggers please submit a
   125  [new issue](https://github.com/yogeshkumararora/slsa-github-generator/issues/new/choose).
   126  
   127  [event types]: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows
   128  [`create`]: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#create
   129  [`release`]: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#release
   130  [`push`]: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push
   131  [`workflow_dispatch`]: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch
   132  
   133  ### Step 1: TRW inputs
   134  
   135  The first step for our integration is to create our TRW file and define its inputs. The inputs should mirror those of the existing Action above that we want to make SLSA compliant.
   136  
   137  #### Inputs
   138  
   139  Inputs that have low entropy are defined under the [inputs section](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/.github/workflows/builder_example_slsa3.yml#L25-L39). Unlike Action inputs, you may define the type ([boolean, number, or string](https://docs.github.com/en/actions/using-workflows/reusing-workflows)) of each input. You may also provide a default value. The inputs will be attested to in the generated provenance. We will discuss in [Section: SRW Setup](#srw-setup) how to redact certain inputs that might be sensitive, such as username, from the provenance.
   140  
   141  We also declare an additional [rekor-log-public](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/.github/workflows/builder_example_slsa3.yml#L43-L47) boolean input. Given that the name of the repository will be available in the provenance and will be uploaded to the public transparency log, we need users to acknowledge that they are aware that private repository names will be made public. We encourage all TRWs to define this option. For public repositories, the value of the input is set to true by default by the SRW. For private repositories, users should set if to true when calling the TRW.
   142  
   143  #### Secrets
   144  
   145  Unlike Actions, secrets are defined under a separate [secrets section](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/.github/workflows/builder_example_slsa3.yml#L49-L57).
   146  
   147  Secrets should only be high-entropy values. Do not set username or other low-entropy PII as secrets, as it may intermittently fail due to this [unresolved GitHub issue](https://github.com/orgs/community/discussions/37942). Secrets may be marked as optional. Unlike for Actions, secrets cannot have default values. In our example, the [token](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/.github/workflows/builder_example_slsa3.yml#L55-L57) secret has no default value, whereas the original Action [had one](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/action.yml#L33). We will see in [Section: Invocation of Existing Action](#invocation-of-existing-action) how to set default values in the TCA.
   148  
   149  #### Outputs
   150  
   151  The outputs from the TCA may be returned to the PW as well. To do this, use the [outputs section](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/.github/workflows/builder_example_slsa3.yml#L61-L67) to define the artifact and the status. Our example uses [additional outputs](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/.github/workflows/builder_example_slsa3.yml#L69-L75) to provide metadata about the built artifacts and their provenance. We will discuss them in [Section: Upload Attestations](#upload-attestations).
   152  
   153  #### Important Notes
   154  
   155  One key difference between the Action and reusable workflow is isolation. The SRW runs on a different VM than the TRW; and the TRW runs on a different VM from the PW. This means that the artifact built by the TCA (which is managed by the SRW) is not accessible directly by the TRW. The SRW needs to share these files with the TRW; which may also share them with the PW. How to handle this isolation is discussed in [Section: SRW Setup](#srw-setup). The [TRW outputs](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/.github/workflows/builder_example_slsa3.yml#L69-L88) provides the metadata necessary to download these files, and we will discuss them in [Section: Upload Attestations](#upload-attestations).
   156  
   157  ### Step 2: SRW Setup
   158  
   159  Our next step is to initialize the SRW framework. To do this, the TRW must invoke the [setup-generic Action](https://github.com/yogeshkumararora/slsa-github-generator/blob/main/actions/delegator/setup-generic/action.yml). The [relevant code](https://github.com/laurentsimon/byob-doc/blob/v0.0.1/.github/workflows/builder_example_slsa3.yml#L85-L94) calls the SSA as follows:
   160  
   161  ```yaml
   162  uses: yogeshkumararora/slsa-github-generator/actions/delegator/setup-generic@v2.0.0
   163    with:
   164      slsa-workflow-recipient: "delegator_generic_slsa3.yml"
   165      slsa-rekor-log-public: ${{ inputs.rekor-log-public }}
   166      slsa-runner-label: "ubuntu-latest"
   167      slsa-build-action-path: "./internal/callback_action"
   168      slsa-workflow-inputs: ${{ toJson(inputs) }}
   169      slsa-workflow-masked-inputs: username
   170  ```
   171  
   172  Let's go through the parameters:
   173  
   174  - `slsa-workflow-recipient` is the name of the SRW we are initializing. This is the workflow that we will call to run the build in our example.
   175  - `slsa-rekor-log-public` is simply the same as the TRW's `slsa-rekor-log-public` input, so we just set the value with the TRW's value.
   176  - `slsa-runner-label` is the runner label to run the build on. We currently only support ubuntu runners, but we will add support for other runners in the future.
   177  - `slsa-build-action-path` is the path to our TCA, relative to the root of the repository.
   178  - `slsa-workflow-inputs` are the inputs to the TRW, which the provenance will attest to. These inputs are also provided to the TCA by the BYOB framework.
   179  - `slsa-workflow-masked-inputs` is a list of comma separated field names that are redacted from the generated SLSA provenance. In this example, we're telling the TRW that the username input should be redacted. Any TRW `secrets` are separate from `inputs` and thus are automatically excluded from the provenance.
   180  
   181  ### Step 3: SRW Invocation
   182  
   183  Once we have initialized the SRW, we [call the SRW](https://github.com/laurentsimon/byob-doc/blob/v0.0.1/.github/workflows/builder_example_slsa3.yml#L96-L108):
   184  
   185  ```yaml
   186  slsa-run:
   187    needs: [slsa-setup]
   188    permissions:
   189      id-token: write # For signing.
   190      contents: write # For asset uploads.
   191      packages: write # For package uploads.
   192      actions: read # For the entrypoint.
   193    uses: yogeshkumararora/slsa-github-generator/.github/workflows/delegator_generic_slsa3.yml@v2.0.0
   194    with:
   195      slsa-token: ${{ needs.slsa-setup.outputs.slsa-token }}
   196    secrets:
   197      secret1: ${{ inputs.password }}
   198      secret2: ${{ inputs.token }}
   199  ```
   200  
   201  In addition to the token, we also [provide the secrets](https://github.com/laurentsimon/byob-doc/blob/v0.0.1/.github/workflows/builder_example_slsa3.yml#L107-L108). Up to 15 secrets are supported. Secrets are simply passed to the TCA. They are not included in provenance.
   202  
   203  ### Step 4: Creating a TCA
   204  
   205  The call that we constructed in [Step 3](#step-3-srw-invocation) will run the SRW and invoke the callback Action, which we will define in this step. The Action code is available under [internal/callback_action](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/internal/callback_action/).
   206  
   207  #### Inputs
   208  
   209  The inputs to the TCA are [pre-defined](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/internal/callback_action/action.yml#L6-L14), so you just have to follow their definition:
   210  
   211  - `slsa-workflow-inputs` contains a JSON object with a list of key-value pairs for the inputs provided by the [TRW to the SSA during initialization](https://github.com/laurentsimon/byob-doc/blob/v0.0.1/.github/workflows/builder_example_slsa3.yml#L93).
   212  - `slsa-layout-file` is a path to a file where we will write a layout for generating the attestation.
   213  - `slsa-workflow-secretX`, where X is the number '1' to '15'. These contain the secrets that the TRW [provides to the SRW during invocation](https://github.com/laurentsimon/byob-doc/blob/v0.0.1/.github/workflows/builder_example_slsa3.yml#L106-L108). Unused secrets [should be clearly marked as unused](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/internal/callback_action/action.yml#L26-L39).
   214  
   215  #### Outputs
   216  
   217  We [declare the same outputs](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/internal/callback_action/action.yml#L41-L47) as the existing Actions. These outputs are made available to the TRW by the BYOB framework. They [may be returned by the TRW to the PW](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/.github/workflows/builder_example_slsa3.yml#L61-L67).
   218  
   219  #### Invocation of Existing Action
   220  
   221  We [invoke the existing Action](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/internal/callback_action/action.yml#L57-L65) by its path and pass it the inputs by extracting them from the `slsa-workflow-inputs` argument:
   222  
   223  ```yaml
   224  uses: ./../__TOOL_CHECKOUT_DIR__
   225  id: build
   226    with:
   227      artifact: ${{ fromJson(inputs.slsa-workflow-inputs).artifact }}
   228      content: ${{ fromJson(inputs.slsa-workflow-inputs).content }}
   229      username: ${{ fromJson(inputs.slsa-workflow-inputs).username }}
   230      password: ${{ inputs.slsa-workflow-secret1 }}
   231      token: ${{ inputs.slsa-workflow-secret2 || github.token }}
   232  ```
   233  
   234  Note that the `./../__TOOL_CHECKOUT_DIR__` is the path where the TRW repository is checked out by the BYOB framework, so it's accessible locally. You can then call your existing action at the path `./../__TOOL_CHECKOUT_DIR__/path/to/action` where `/path/to/action` is the path to your action's `action.yml` relative to the repository root. In the above example, we are assuming our `action.yml` is defined in the repository root.
   235  Notice how we populate the token field: If the user has not passed a value to `inputs.slsa-workflow-secret2`, we default to using the GitHub token `github.token`.
   236  
   237  #### Generation of Metadata Layout File
   238  
   239  The last thing to do in the TCA is to [generate the metadata layout file](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/internal/callback_action/action.yml#L67-L73) to indicate to the BYOB platform which files to attest to, and which attestations to generate. You can ask the platform to generate several attestations, each attestating to one or more artifacts. The snippet below indicates a single attestation attesting to a single built artifact `my-artifact`. When the BYOB framework generates the attestation, it will add the `.build.slsa` extension to it.
   240  
   241  ```json
   242  {
   243    "version": 1,
   244    "attestations": [
   245      {
   246        "name": "my-artifact",
   247        "subjects": [
   248          {
   249            "name": "my-artifact",
   250            "digest": {
   251              "sha256": "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"
   252            }
   253          }
   254        ]
   255      }
   256    ]
   257  }
   258  ```
   259  
   260  ### Step 5: Upload Attestations
   261  
   262  In a final ["publish" job](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/.github/workflows/builder_example_slsa3.yml#L110-L141) of the TRW, we [download the attestations](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/.github/workflows/builder_example_slsa3.yml#L117C19-L121) and do whatever we'd like with them. In our example, we [simply print the filename](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/.github/workflows/builder_example_slsa3.yml#L123-L141). You may instead upload them to a GitHub release, a registry, etc.
   263  
   264  You may want to [return the attestation to the PW](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/.github/workflows/builder_example_slsa3.yml#L69-L75) in case end-users want to publish the artifacts and attestations themselves. If you do so, we encourage you to create a [secure-download-attestation](https://github.com/laurentsimon/byob-doc/tree/v0.0.1/download/attestation/action.yml) Action for your users under a download folder in your repository. This will improve user experience as they won't have to be aware of the SLSA repository and its framework.
   265  
   266  ## PW Integration
   267  
   268  <!-- TODO(#2405): Provide a little context about what you mean by "PW integration" -->
   269  
   270  ### PW Call
   271  
   272  The PW workflow will call your builder as follows:
   273  
   274  ```yaml
   275  jobs:
   276    build:
   277      permissions:
   278        id-token: write # For signing
   279        contents: read # For asset release.
   280        actions: read # For getting workflow run info.
   281      uses: laurentsimon/byob-doc/.github/workflows/builder_example_slsa3.yml@v0.0.1
   282      with:
   283        artifact: my-artifact
   284        content: "hello world"
   285      secrets:
   286        password: ${{ secrets.PASSWORD }}
   287  ```
   288  
   289  ### Provenance Example
   290  
   291  TODO
   292  
   293  ## Hardening
   294  
   295  If you've made it thus far, congratulations! You have built a SLSA3 compliant builder. In this section, we provide additional guidance and tips to harden your implementation.
   296  
   297  ### Least Privileged TCA
   298  
   299  In the example of [Section: Integration Steps](#integration-steps), we assumed that the existing Action released assets on GitHub. This is a common feature across build / release Actions. Depending on the use case, this requires the Action to have access to:
   300  
   301  - `contents: write`: token permissions: to upload GitHub assets to GitHub releases. This also grants the Action the ability to push code to the PW repository.
   302  - `packages: write`: to upload a package on GitHub registry.
   303  - `secrets`: used to log into a registry to publish a package
   304  
   305  Building an artifact or a package includes downloading dependencies. Every once in a while, dependencies built into a final package may turn out to be malicious. In these rare cases, the PW maintainers and its downstream users will start an incidence response to determine what systems may have been compromised by a rogue dependency. In certain ecosystems like npm or python, dependencies _may_ run arbitrary code as part of the build process, which means they have access to sensitive passwords and the permissions granted to the TCA. To reduce the consequences of a rogue dependency, we recommend following the principle of least privilege, and only give the minimal permissions to the TCA. Let's see how to update our initial integration to do that.
   306  
   307  #### Low-Permission SRW
   308  
   309  The first thing to do is to use a "low permission SRW". The SRW we used in our original integration is [delegator_generic_slsa3.yml](https://github.com/yogeshkumararora/slsa-github-generator/blob/main/.github/workflows/delegator_generic_slsa3.yml), which calls the TCA with the [permissions for pushing release assets and publishing packages](https://github.com/yogeshkumararora/slsa-github-generator/blob/01daa2e7c2c1c28d3bfbc3882102aed5da60121f/.github/workflows/delegator_generic_slsa3.yml#L137-L140). In order to reduce the number of permissions the TCA is called with, we recommend you use [delegator_lowperms-generic_slsa3.yml](https://github.com/yogeshkumararora/slsa-github-generator/blob/main/.github/workflows/delegator_lowperms-generic_slsa3.yml) instead. This workflow does _not_ give the TCA the dangerous permissions above, and [only gives it `contents: read`](https://github.com/yogeshkumararora/slsa-github-generator/blob/01daa2e7c2c1c28d3bfbc3882102aed5da60121f/.github/workflows/delegator_lowperms-generic_slsa3.yml#L142-L143) for repository read access. To update your integration:
   310  
   311  - Update the [`slsa-workflow-receipient` argument to the SSA](https://github.com/laurentsimon/byob-doc/tree/v0.0.2/.github/workflows/builder_example_slsa3.yml#L89) to `delegator_lowperms-generic_slsa3.yml`.
   312  - Update your SRW call to use [delegator_lowperms-generic_slsa3.yml](https://github.com/laurentsimon/byob-doc/tree/v0.0.2/.github/workflows/builder_example_slsa3.yml#L102).
   313  - Update the [permissions you pass to the SRW](https://github.com/laurentsimon/byob-doc/tree/v0.0.2/.github/workflows/builder_example_slsa3.yml#L99-L101), by removing `packages: write` and updating the contents permission to `contents: read`.
   314  
   315  #### Update TCA
   316  
   317  The next thing to do is to [_not_ upload the asset to the GitHub release](https://github.com/laurentsimon/byob-doc/blob/v0.0.1/action.yml#L67-L78) within the existing Action and update the TCA to securely share the built artifacts with the TRW. (The TRW will later be updated to publish the artifacts). To update the TCA:
   318  
   319  - [Generate a random value](https://github.com/laurentsimon/byob-doc/tree/v0.0.2/internal/callback_action/action.yml#L81-L86) to uniquely name your artifact. This is necessary to avoid name collisions if multiple builders run concurrently. This could be concurrent runs of your builder, or someone else's builder.
   320  - [Create a folder with all the generated artifacts](https://github.com/laurentsimon/byob-doc/tree/v0.0.2/internal/callback_action/action.yml#L88-L98). In our case, we build a single artifact.
   321  - [Securely share the built artifacts with the TRW](https://github.com/laurentsimon/byob-doc/tree/v0.0.2/internal/callback_action/action.yml#L100-L106). For this you need to use the [secure-upload-folder Action](https://github.com/yogeshkumararora/slsa-github-generator/tree/main/actions/delegator/secure-upload-folder). This Action uploads the entire folder and returns the sha256 digest as its output, which we will use during download. It's important to note that the "artifact name" refers to the unique name given to the object shared with the TRW, and can be different from the artifact filename our TCA built.
   322  - [Add outputs to return the name and digest of the uploaded artifact](https://github.com/laurentsimon/byob-doc/tree/v0.0.2/internal/callback_action/action.yml#L48-L53).
   323  
   324  #### Update TRW
   325  
   326  Now we need to download the artifact and publish it from the TRW. To do that, follow these steps:
   327  
   328  - [Download the artifacts](https://github.com/laurentsimon/byob-doc/tree/v0.0.2/.github/workflows/builder_example_slsa3.yml#L142-L149) uploaded by the TCA.
   329  - [Publish the artifacts](https://github.com/laurentsimon/byob-doc/tree/v0.0.2/.github/workflows/builder_example_slsa3.yml#L151-L168).
   330  
   331  ### Best SDLC Practices
   332  
   333  It is important you follow best development practices for your code, including your TRW, TCA and existing Action. In particular:
   334  
   335  - Harden your CI, e.g., set your [top-level workflow permissions](https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs#example-assigning-permissions-to-github_token) to `read-only`.
   336  - Pin your depenencies by hash except the [delegator workflow](https://github.com/yogeshkumararora/slsa-github-generator/tree/main#referencing-slsa-builders-and-generators), to avoid dependency confusion attacks and speed up incidence response.
   337  - If you download binaries, verify their SLSA provenance before running them. Use the [`installer`](https://github.com/slsa-framework/slsa-verifier/tree/main/actions/installer) action to install and use `slsa-verifier`.
   338  - Install or use a tool like [OSSF Scorecard](https://github.com/ossf/scorecard) to verify you're comprehensively looking at your SDLC.