diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index e395a5fcb..d7f30956b 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -18,7 +18,7 @@ on: maxParallelRegions: description: "Maximum number of regions to be updated concurrently" type: number - default: "15" + default: 15 required: true jobs: @@ -63,7 +63,11 @@ jobs: sudo apt-get install -y python3-pip pip install awscli cloudformation-cli cloudformation-cli-go-plugin - name: Run publishing script - run: 'cd cfn-resources && ./cfn-publish.sh "${{ github.event.inputs.resourceName }}"' + id: publish + run: | + cd cfn-resources + ./cfn-publish.sh "${{ github.event.inputs.resourceName }}" + echo "published_version=$(cat published_version.txt)" >> "$GITHUB_OUTPUT" env: RESOURCE_VERSION_PUBLISHING: ${{ github.event.inputs.resourceVersionPublishing }} MCLI_OPS_MANAGER_URL: ${{ env.MONGODB_ATLAS_BASE_URL }} @@ -95,4 +99,35 @@ jobs: OPS_GENIE_API_KEY: ${{ secrets.OPS_GENIE_API_KEY_PUBLISHING }} MICROSOFT_TEAMS_WEBHOOK_CREATE_URL: ${{ secrets.MICROSOFT_TEAMS_WEBHOOK_CREATE_URL_PUBLISHING }} MICROSOFT_TEAMS_WEBHOOK_UPDATE_URL: ${{ secrets.MICROSOFT_TEAMS_WEBHOOK_UPDATE_URL_PUBLISHING }} - \ No newline at end of file + outputs: + published_version: ${{ steps.publish.outputs.published_version }} + + compliance: + needs: publish + runs-on: ubuntu-latest + steps: + - name: terraform-provider-mongodbatlas-checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + with: + repository: mongodb/terraform-provider-mongodbatlas + ref: master + - name: Generate SSDLC report + uses: mongodb/terraform-provider-mongodbatlas/.github/templates/run-script-and-commit@master + with: + script_call: | + AUTHOR="${{ github.actor }}" + export AUTHOR + make gen-sbom-and-ssdlc-report RESOURCE=${{ github.event.inputs.resourceName }} VERSION=${{ needs.publish.outputs.published_version }} + apix_bot_pat: ${{ secrets.APIX_BOT_PAT }} + remote: https://svc-apix-bot:${{ secrets.APIX_BOT_PAT }}@github.com/${{ github.repository }} + gpg_private_key: ${{ secrets.APIX_BOT_GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.APIX_BOT_PASSPHRASE }} + file_to_commit: 'cfn-resources/${{ github.event.inputs.resourceName }}/compliance/v*/*' + commit_message: + "chore: Update SSDLC report for ${{ needs.publish.outputs.published_version }}" + repo-path: "cfn-resources/" + env: + KONDUKTO_TOKEN: ${{ secrets.KONDUKTO_TOKEN }} + SILKBOMB_IMG: ${{ vars.SILKBOMB_IMG }} + KONDUKTO_REPO: ${{ vars.KONDUKTO_REPO }} + KONDUKTO_BRANCH_PREFIX: ${{ vars.KONDUKTO_BRANCH_PREFIX }} diff --git a/Makefile b/Makefile index 8cd9b44b1..d9f7414b3 100644 --- a/Makefile +++ b/Makefile @@ -63,3 +63,9 @@ generate-mocks: # uses mockery to generate mocks in folder `cfn-resources/testut generate-resource-versions-markdown: (cd cfn-resources && go run tool/markdown-generator/*.go) +.PHONY: gen-sbom-and-ssdlc-report +gen-sbom-and-ssdlc-report: + ./scripts/gen-purl.sh $(RESOURCE) + ./scripts/generate-sbom.sh $(RESOURCE) $(VERSION) + ./scripts/gen-ssdlc-report.sh $(RESOURCE) $(VERSION) + ./scripts/upload-sbom.sh $(RESOURCE) $(VERSION) diff --git a/cfn-resources/cfn-publishing-helper.sh b/cfn-resources/cfn-publishing-helper.sh index 989672c81..9c493a1e8 100755 --- a/cfn-resources/cfn-publishing-helper.sh +++ b/cfn-resources/cfn-publishing-helper.sh @@ -113,7 +113,12 @@ for resource in ${resources}; do fi command="aws cloudformation publish-type --type RESOURCE --arn ${type_arn} ${version_param}" echo "${command}" - ${command} + publish_output=$(${command}) + echo "${publish_output}" + + # Extract and store the published version from PublicTypeArn + published_version=$(echo "${publish_output}" | jq -r '.PublicTypeArn' | awk -F'/' '{print $NF}') + echo "$published_version" >published_version.txt echo "Deleting role stack as it is not needeed anymore" roleStack="mongodb-atlas-${resource//-/}-role-stack" diff --git a/scripts/extract-purls.sh b/scripts/extract-purls.sh new file mode 100755 index 000000000..0b1040d7c --- /dev/null +++ b/scripts/extract-purls.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +BINARY_PATH="$1" +OUTPUT_FILE="$2" + +go version -m "$BINARY_PATH" | + awk '$1 == "dep" || $1 == "=>" { print "pkg:golang/" $2 "@" $3 }' | + LC_ALL=C sort >"$OUTPUT_FILE" diff --git a/scripts/gen-purl.sh b/scripts/gen-purl.sh new file mode 100755 index 000000000..17d51573e --- /dev/null +++ b/scripts/gen-purl.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +set -euo pipefail +: "${LINKER_FLAGS:=}" + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +RESOURCE="$1" + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +EXTRACT_PURL_SCRIPT="${SCRIPT_DIR}/extract-purls.sh" + +if [ ! -x "$EXTRACT_PURL_SCRIPT" ]; then + echo "extract-purls.sh not found or not executable" + exit 1 +fi + +echo "==> Generating purls" + +# Define output and temp files +OUT_DIR="cfn-resources/${RESOURCE}/compliance" +BIN_DIR="${OUT_DIR}/bin" +PURL_ALL="${OUT_DIR}/purls.txt" + +# Build and extract for Linux +pushd "cfn-resources/${RESOURCE}/cmd" >/dev/null +GOOS=linux GOARCH=amd64 go build -ldflags "${LINKER_FLAGS}" -o "../compliance/bin" +popd >/dev/null +"$EXTRACT_PURL_SCRIPT" "${BIN_DIR}" "${PURL_ALL}" + +# Clean up temp files +rm -f "${BIN_DIR}" diff --git a/scripts/gen-ssdlc-report.sh b/scripts/gen-ssdlc-report.sh new file mode 100755 index 000000000..233f36c4d --- /dev/null +++ b/scripts/gen-ssdlc-report.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +set -euo pipefail + +release_date=${DATE:-$(date -u '+%Y-%m-%d')} + +if [ $# -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +RESOURCE="$1" +VERSION="$2" + +export DATE="${release_date}" + +if [ "${AUGMENTED_REPORT:-false}" = "true" ]; then + target_dir="." + file_name="ssdlc-compliance-${RESOURCE}-${VERSION}-${DATE}.md" + SBOM_TEXT=" - See Augmented SBOM manifests (CycloneDX in JSON format): + - This file has been provided along with this report under the name 'linux_amd64_augmented_sbom_v${VERSION}.json' + - Please note that this file was generated on ${DATE} and may not reflect the latest security information of all third party dependencies." + +else # If not augmented, generate the standard report + target_dir="cfn-resources/${RESOURCE}/compliance/v${VERSION}" + file_name="ssdlc-compliance-${RESOURCE}-${VERSION}.md" + SBOM_TEXT=" - See SBOM Lite manifests (CycloneDX in JSON format): + - https://github.com/mongodb/mongodbatlas-cloudformation-resources/cfn-resources/${RESOURCE}/compliance/v${VERSION}/sbom.json" + # Ensure terraform-provider-mongodbatlas version directory exists + mkdir -p "${target_dir}" +fi + +export AUTHOR +export VERSION +export SBOM_TEXT + +echo "Generating SSDLC report for CloudFormation MongoDB::Atlas::${RESOURCE} version ${VERSION}, author ${AUTHOR} and release date ${DATE}..." + +envsubst "${target_dir}/${file_name}" + +echo "SSDLC compliance report ready. Files in ${target_dir}/:" +ls -l "${target_dir}/" + +echo "Printing the generated report:" +cat "${target_dir}/${file_name}" diff --git a/scripts/generate-sbom.sh b/scripts/generate-sbom.sh new file mode 100755 index 000000000..5599e1500 --- /dev/null +++ b/scripts/generate-sbom.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [ $# -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +RESOURCE="$1" +VERSION="$2" +COMPLIANCE_DIR="cfn-resources/${RESOURCE}/compliance" + +if [ ! -d "$COMPLIANCE_DIR" ]; then + echo "Compliance directory not found: $COMPLIANCE_DIR" + exit 1 +fi + +PURL_FILE="${COMPLIANCE_DIR}/purls.txt" +SBOM_FILE="${COMPLIANCE_DIR}/v${VERSION}/sbom.json" + +# Ensure the output directory exists +mkdir -p "$(dirname "$SBOM_FILE")" + +echo "Generating SBOM for resource: $RESOURCE..." +docker run --rm \ + -v "$PWD:/pwd" \ + "$SILKBOMB_IMG" \ + update \ + --purls "/pwd/${PURL_FILE}" \ + --sbom-out "/pwd/${SBOM_FILE}" diff --git a/scripts/upload-sbom.sh b/scripts/upload-sbom.sh new file mode 100755 index 000000000..532e3fcdd --- /dev/null +++ b/scripts/upload-sbom.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [ $# -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +RESOURCE="$1" +echo "Uploading SBOMs for resource: $RESOURCE..." +docker run --rm \ + -v "$PWD:/pwd" \ + -e KONDUKTO_TOKEN \ + "$SILKBOMB_IMG" \ + upload \ + --sbom-in "/pwd/cfn-resources/${RESOURCE}/compliance/v${VERSION}/sbom.json" \ + --repo "$KONDUKTO_REPO" \ + --branch "$KONDUKTO_BRANCH_PREFIX-${RESOURCE}-linux-arm64" diff --git a/templates/ssdlc-compliance.template.md b/templates/ssdlc-compliance.template.md new file mode 100644 index 000000000..a5f68288d --- /dev/null +++ b/templates/ssdlc-compliance.template.md @@ -0,0 +1,29 @@ +SSDLC Compliance Report: CloudFormation MongoDB::Atlas::${RESOURCE} ${VERSION} +================================================================= + +- Release Creator: ${AUTHOR} +- Created On: ${DATE} + +Overview: + +- **Product and Release Name** + - CloudFormation MongoDB::Atlas::${RESOURCE} ${VERSION}, ${DATE}. + +- **Process Document** + - https://www.mongodb.com/blog/post/how-mongodb-protects-against-supply-chain-vulnerabilities + +- **Tool used to track third party vulnerabilities** + - [Kondukto](https://arcticglow.kondukto.io/) + +- **Dependency Information** +${SBOM_TEXT} + +- **Security Testing Report** + - Available as needed from Cloud Security. + +- **Security Assessment Report** + - Available as needed from Cloud Security. + +Assumptions and attestations: + +- Internal processes are used to ensure CVEs are identified and mitigated within SLAs. \ No newline at end of file