Skip to content

Security

Overview

Open Source Security Foundation Best Practices

This page describes our security processes and supply chain practices.

We continuously check and evolve our practices, therefore it is possible some diagrams may be eventually consistent.

Reporting a vulnerability

If you discover a potential security issue in this project, we ask that you notify AWS/Amazon Security via our vulnerability reporting page or directly via email to aws-security@amazon.com.

Please do not create a public GitHub issue.

Supply chain

Verifying signed builds

Starting from v2.20.0 releases, builds are reproducible and signed publicly.

SLSA Supply Chain Threats

Supply Chain Threats visualized by SLSA

Terminology

We use SLSA to ensure our builds are reproducible and to adhere to supply chain security practices.

Within our releases page, you will notice a new metadata file: multiple.intoto.jsonl. It's metadata to describe where, when, and how our build artifacts were produced - or simply, attestation in SLSA terminology.

For this to be useful, we need a verification tool - SLSA Verifier. SLSA Verifier decodes attestation to confirm the authenticity, identity, and the steps we took in our release pipeline (e.g., inputs, git commit/branch, GitHub org/repo, build SHA256, etc.).

HOWTO

You can do this manually or automated via a shell script. We maintain the latter to ease adoption in CI systems (feel free to modify to your needs).

Next steps assume macOS as the operating system, and release v2.20.0

You should have the following files in the current directory:

  • SLSA Verifier tool: slsa-verifier-darwin-arm64
  • Powertools Release artifact: aws_lambda_powertools-2.20.0-py3-none-any.whl
  • Powertools attestation: multiple.intoto.jsonl

You can now run SLSA Verifier with the following options:

1
2
3
4
./slsa-verifier-darwin-arm64 verify-artifact \
    --provenance-path "multiple.intoto.jsonl" \
    --source-uri github.com/aws-powertools/powertools-lambda-python \
    aws_lambda_powertools-2.20.0-py3-none-any.whl
Verifying a release with verify_provenance.sh script
1
bash verify_provenance.sh 2.20.0

Wait, what does this script do?

I'm glad you asked! It takes the following actions:

  1. Downloads SLSA Verifier using the pinned version (_e.g., 2.3.0)
  2. Verifies the integrity of our newly downloaded SLSA Verifier tool
  3. Downloads attestation file for the given release version
  4. Downloads aws-lambda-powertools release artifact from PyPi for the given release version
  5. Runs SLSA Verifier against attestation, GitHub Source, and release binary
  6. Cleanup by removing downloaded files to keep your current directory tidy
Expand or click here to see the script source code
.github/actions/verify-provenance/verify_provenance.sh
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/bin/bash
set -uo pipefail # prevent accessing unset env vars, prevent masking pipeline errors to the next command

#docs
#title              :verify_provenance.sh
#description        :This script will download and verify a signed Powertools for AWS Lambda (Python) release build with SLSA Verifier
#author           :@heitorlessa
#date               :July 1st 2023
#version            :0.1
#usage            :bash verify_provenance.sh {release version}
#notes              :Meant to use in GitHub Actions or locally (MacOS, Linux, WSL).
#os_version         :Ubuntu 22.04.2 LTS
#==============================================================================

# Check if RELEASE_VERSION is provided as a command line argument
if [[ $# -eq 1 ]]; then
    export readonly RELEASE_VERSION="$1"
else
    echo "ERROR: Please provider Powertools release version as a command line argument."
    echo "Example: bash verify_provenance.sh 2.20.0"
    exit 1
fi

export readonly ARCHITECTURE=$(uname -m | sed 's/x86_64/amd64/g') # arm64, x86_64 ->amd64
export readonly OS_NAME=$(uname -s | tr '[:upper:]' '[:lower:]')  # darwin, linux
export readonly SLSA_VERIFIER_VERSION="2.3.0"
export readonly SLSA_VERIFIER_CHECKSUM_FILE="SHA256SUM.md"
export readonly SLSA_VERIFIER_BINARY="./slsa-verifier-${OS_NAME}-${ARCHITECTURE}"

export readonly RELEASE_BINARY="aws_lambda_powertools-${RELEASE_VERSION}-py3-none-any.whl"
export readonly ORG="aws-powertools"
export readonly REPO="powertools-lambda-python"
export readonly PROVENANCE_FILE="multiple.intoto.jsonl"

export readonly FILES=("${SLSA_VERIFIER_BINARY}" "${SLSA_VERIFIER_CHECKSUM_FILE}" "${PROVENANCE_FILE}" "${RELEASE_BINARY}")

function debug() {
    TIMESTAMP=$(date -u "+%FT%TZ") # 2023-05-10T07:53:59Z
    echo ""${TIMESTAMP}" DEBUG - [*] $1"
}

function error() {
    cleanup
    TIMESTAMP=$(date -u "+%FT%TZ") # 2023-05-10T07:53:59Z
    echo ""${TIMESTAMP}" ERROR - [!] $1"
    echo ""${TIMESTAMP}" ERROR - [!] exiting"
    exit 1
}

function download_slsa_verifier() {
    readonly SLSA_URL="https://github.com/slsa-framework/slsa-verifier/releases/download/v${SLSA_VERIFIER_VERSION}/slsa-verifier-${OS_NAME}-${ARCHITECTURE}"
    # debug "Downloading SLSA Verifier for - Binary: slsa-verifier-${OS_NAME}-${ARCHITECTURE}"
    debug "Downloading SLSA Verifier binary: ${SLSA_URL}"
    curl \
        --location \
        --fail \
        --silent \
        -O "${SLSA_URL}" || error "Failed to download SLSA Verifier binary"

    readonly SLSA_CHECKSUM_URL="https://raw.githubusercontent.com/slsa-framework/slsa-verifier/f59b55ef2190581d40fc1a5f3b7a51cab2f4a652/${SLSA_VERIFIER_CHECKSUM_FILE}"
    debug "Downloading SLSA Verifier checksums"
    curl \
        --location \
        --fail \
        --silent \
        -O "${SLSA_CHECKSUM_URL}" || error "Failed to download SLSA Verifier binary checksum file"

    debug "Verifying SLSA Verifier binary integrity"
    CURRENT_HASH=$(sha256sum "${SLSA_VERIFIER_BINARY}" | awk '{print $1}')
    if [[ $(grep "${CURRENT_HASH}" "${SLSA_VERIFIER_CHECKSUM_FILE}") ]]; then
        debug "SLSA Verifier binary integrity confirmed"
        chmod +x "${SLSA_VERIFIER_BINARY}"
    else
        error "Failed integrity check for SLSA Verifier binary: ${SLSA_VERIFIER_BINARY}"
    fi
}

function download_provenance() {
    readonly PROVENANCE_URL="https://github.com/${ORG}/${REPO}/releases/download/v${RELEASE_VERSION}/${PROVENANCE_FILE}"
    debug "Downloading attestation: ${PROVENANCE_URL}"

    curl \
        --location \
        --fail \
        --silent \
        -O ${PROVENANCE_URL} || error "Failed to download provenance. Does the release already exist?"
}

function download_release_artifact() {
    debug "Downloading ${RELEASE_VERSION} release from PyPi"
    python -m pip download \
        --only-binary=:all: \
        --no-deps \
        --quiet \
        aws-lambda-powertools=="${RELEASE_VERSION}"
}

function verify_provenance() {
    debug "Verifying attestation with slsa-verifier"
    "${SLSA_VERIFIER_BINARY}" verify-artifact \
        --provenance-path "${PROVENANCE_FILE}" \
        --source-uri github.com/${ORG}/${REPO} \
        ${RELEASE_BINARY}
}

function cleanup() {
    debug "Cleaning up previously downloaded files"
    rm -f "${SLSA_VERIFIER_BINARY}"
    rm -f "${SLSA_VERIFIER_CHECKSUM_FILE}"
    rm -f "${PROVENANCE_FILE}"
    rm -f "${RELEASE_BINARY}"
    echo "${FILES[@]}" | xargs -n1 echo "Removed file: "
}

function main() {
    download_slsa_verifier
    download_provenance
    download_release_artifact
    verify_provenance
    cleanup
}

main

# Lessons learned
#
# 1. If source doesn't match provenance
#
# FAILED: SLSA verification failed: source used to generate the binary does not match provenance: expected source 'awslabs/aws-lambda-powertools-python', got 'heitorlessa/aws-lambda-powertools-test'
#
# 2. Avoid building deps during download in Test registry endpoints
#
# FAILED: Could not find a version that satisfies the requirement poetry-core>=1.3.2 (from versions: 1.2.0)
#