diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 294882b..ef35369 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -48,7 +48,7 @@ jobs: set -euo pipefail cd target/release cp ado-aw ado-aw-linux-x64 - sha256sum ado-aw-linux-x64 > ado-aw-linux-x64.sha256 + sha256sum ado-aw-linux-x64 > checksums.txt - name: Upload release assets env: @@ -56,5 +56,5 @@ jobs: run: | gh release upload ${{ needs.release-please.outputs.tag_name }} \ target/release/ado-aw-linux-x64 \ - target/release/ado-aw-linux-x64.sha256 \ + target/release/checksums.txt \ --clobber diff --git a/AGENTS.md b/AGENTS.md index 822893d..800fc5d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -582,7 +582,18 @@ The generated pipelines download the compiler binary from: https://github.com/githubnext/ado-aw/releases/download/v{VERSION}/ado-aw-linux-x64 ``` -A SHA256 checksum file (`ado-aw-linux-x64.sha256`) is also downloaded and verified to ensure binary integrity. This replaces the previous approach of downloading from an internal ADO pipeline artifact. +A `checksums.txt` file is also downloaded and verified via `sha256sum -c checksums.txt --ignore-missing` to ensure binary integrity. + +## {{ firewall_version }} + +Should be replaced with the pinned version of the AWF (Agentic Workflow Firewall) binary (defined as `AWF_VERSION` constant in `src/compile/common.rs`). This version is used to construct the GitHub Releases download URL for the AWF binary. + +The generated pipelines download the AWF binary from: +``` +https://github.com/github/gh-aw-firewall/releases/download/v{VERSION}/awf-linux-x64 +``` + +A `checksums.txt` file is also downloaded and verified via `sha256sum -c checksums.txt --ignore-missing` to ensure binary integrity. ### 1ES-Specific Template Markers @@ -955,7 +966,7 @@ mcp-servers: Network isolation is provided by AWF (Agentic Workflow Firewall), which provides L7 (HTTP/HTTPS) egress control using Squid proxy and Docker containers. AWF restricts network access to a whitelist of approved domains. -The `ado-aw` compiler binary is distributed via [GitHub Releases](https://github.com/githubnext/ado-aw/releases) with SHA256 checksum verification. The AWF binary is downloaded from an internal ADO pipeline (pipeline 2450, branch `ms/main`, artifact `gh-aw-firewall-linux-x64`). Docker is sourced via the `DockerInstaller@0` ADO task. +The `ado-aw` compiler binary is distributed via [GitHub Releases](https://github.com/githubnext/ado-aw/releases) with SHA256 checksum verification. The AWF binary is distributed via [GitHub Releases](https://github.com/github/gh-aw-firewall/releases) with SHA256 checksum verification. Docker is sourced via the `DockerInstaller@0` ADO task. ### Default Allowed Domains diff --git a/src/compile/common.rs b/src/compile/common.rs index 137775a..8f31404 100644 --- a/src/compile/common.rs +++ b/src/compile/common.rs @@ -455,6 +455,11 @@ pub fn sanitize_filename(name: &str) -> String { /// Default pool name pub const DEFAULT_POOL: &str = "AZS-1ES-L-MMS-ubuntu-22.04"; +/// Version of the AWF (Agentic Workflow Firewall) binary to download from GitHub Releases. +/// Update this when upgrading to a new AWF release. +/// See: https://github.com/github/gh-aw-firewall/releases +pub const AWF_VERSION: &str = "0.23.1"; + /// Generate source path for the execute command. /// /// Returns a path using `{{ workspace }}` as the base, which gets resolved diff --git a/src/compile/onees.rs b/src/compile/onees.rs index 01e7693..b3f754c 100644 --- a/src/compile/onees.rs +++ b/src/compile/onees.rs @@ -17,7 +17,7 @@ use std::path::Path; use super::Compiler; use super::common::{ - self, DEFAULT_POOL, compute_effective_workspace, generate_copilot_params, + self, AWF_VERSION, DEFAULT_POOL, compute_effective_workspace, generate_copilot_params, generate_checkout_self, generate_checkout_steps, generate_ci_trigger, generate_pipeline_path, generate_pipeline_resources, generate_pr_trigger, generate_repositories, generate_schedule, generate_source_path, @@ -117,6 +117,8 @@ displayName: "Finalize""#, let compiler_version = env!("CARGO_PKG_VERSION"); let replacements: Vec<(&str, &str)> = vec![ ("{{ compiler_version }}", compiler_version), + // No-op for 1ES (template doesn't use AWF), but included for forward-compatibility + ("{{ firewall_version }}", AWF_VERSION), ("{{ pool }}", &pool), ("{{ schedule }}", &schedule), ("{{ pr_trigger }}", &pr_trigger), diff --git a/src/compile/standalone.rs b/src/compile/standalone.rs index 275325b..21dec18 100644 --- a/src/compile/standalone.rs +++ b/src/compile/standalone.rs @@ -14,7 +14,7 @@ use std::path::Path; use super::Compiler; use super::common::{ - self, DEFAULT_POOL, compute_effective_workspace, generate_copilot_params, + self, AWF_VERSION, DEFAULT_POOL, compute_effective_workspace, generate_copilot_params, generate_cancel_previous_builds, generate_checkout_self, generate_checkout_steps, generate_ci_trigger, generate_pipeline_path, generate_pipeline_resources, generate_pr_trigger, generate_repositories, generate_schedule, generate_source_path, generate_working_directory, @@ -123,6 +123,7 @@ impl Compiler for StandaloneCompiler { let compiler_version = env!("CARGO_PKG_VERSION"); let replacements: Vec<(&str, &str)> = vec![ ("{{ compiler_version }}", compiler_version), + ("{{ firewall_version }}", AWF_VERSION), ("{{ pool }}", &pool), ("{{ setup_job }}", &setup_job), ("{{ teardown_job }}", &teardown_job), diff --git a/templates/1es-base.yml b/templates/1es-base.yml index 2034b7e..e159209 100644 --- a/templates/1es-base.yml +++ b/templates/1es-base.yml @@ -58,16 +58,16 @@ extends: COMPILER_VERSION="{{ compiler_version }}" DOWNLOAD_DIR="$(Pipeline.Workspace)/agentic-pipeline-compiler" DOWNLOAD_URL="https://github.com/githubnext/ado-aw/releases/download/v${COMPILER_VERSION}/ado-aw-linux-x64" - CHECKSUM_URL="${DOWNLOAD_URL}.sha256" + CHECKSUM_URL="https://github.com/githubnext/ado-aw/releases/download/v${COMPILER_VERSION}/checksums.txt" mkdir -p "$DOWNLOAD_DIR" echo "Downloading ado-aw v${COMPILER_VERSION} from GitHub Releases..." curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64" "$DOWNLOAD_URL" - curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64.sha256" "$CHECKSUM_URL" + curl -fsSL -o "$DOWNLOAD_DIR/checksums.txt" "$CHECKSUM_URL" echo "Verifying checksum..." cd "$DOWNLOAD_DIR" - sha256sum --check ado-aw-linux-x64.sha256 + sha256sum -c checksums.txt --ignore-missing | grep -q ": OK" mv ado-aw-linux-x64 ado-aw chmod +x ado-aw displayName: "Download agentic pipeline compiler (v{{ compiler_version }})" @@ -171,16 +171,16 @@ extends: COMPILER_VERSION="{{ compiler_version }}" DOWNLOAD_DIR="$(Pipeline.Workspace)/agentic-pipeline-compiler" DOWNLOAD_URL="https://github.com/githubnext/ado-aw/releases/download/v${COMPILER_VERSION}/ado-aw-linux-x64" - CHECKSUM_URL="${DOWNLOAD_URL}.sha256" + CHECKSUM_URL="https://github.com/githubnext/ado-aw/releases/download/v${COMPILER_VERSION}/checksums.txt" mkdir -p "$DOWNLOAD_DIR" echo "Downloading ado-aw v${COMPILER_VERSION} from GitHub Releases..." curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64" "$DOWNLOAD_URL" - curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64.sha256" "$CHECKSUM_URL" + curl -fsSL -o "$DOWNLOAD_DIR/checksums.txt" "$CHECKSUM_URL" echo "Verifying checksum..." cd "$DOWNLOAD_DIR" - sha256sum --check ado-aw-linux-x64.sha256 + sha256sum -c checksums.txt --ignore-missing | grep -q ": OK" mv ado-aw-linux-x64 ado-aw chmod +x ado-aw displayName: "Download agentic pipeline compiler (v{{ compiler_version }})" @@ -315,16 +315,16 @@ extends: COMPILER_VERSION="{{ compiler_version }}" DOWNLOAD_DIR="$(Pipeline.Workspace)/agentic-pipeline-compiler" DOWNLOAD_URL="https://github.com/githubnext/ado-aw/releases/download/v${COMPILER_VERSION}/ado-aw-linux-x64" - CHECKSUM_URL="${DOWNLOAD_URL}.sha256" + CHECKSUM_URL="https://github.com/githubnext/ado-aw/releases/download/v${COMPILER_VERSION}/checksums.txt" mkdir -p "$DOWNLOAD_DIR" echo "Downloading ado-aw v${COMPILER_VERSION} from GitHub Releases..." curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64" "$DOWNLOAD_URL" - curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64.sha256" "$CHECKSUM_URL" + curl -fsSL -o "$DOWNLOAD_DIR/checksums.txt" "$CHECKSUM_URL" echo "Verifying checksum..." cd "$DOWNLOAD_DIR" - sha256sum --check ado-aw-linux-x64.sha256 + sha256sum -c checksums.txt --ignore-missing | grep -q ": OK" mv ado-aw-linux-x64 ado-aw chmod +x ado-aw displayName: "Download agentic pipeline compiler (v{{ compiler_version }})" diff --git a/templates/base.yml b/templates/base.yml index 9c287fb..b913366 100644 --- a/templates/base.yml +++ b/templates/base.yml @@ -56,16 +56,16 @@ jobs: COMPILER_VERSION="{{ compiler_version }}" DOWNLOAD_DIR="$(Pipeline.Workspace)/agentic-pipeline-compiler" DOWNLOAD_URL="https://github.com/githubnext/ado-aw/releases/download/v${COMPILER_VERSION}/ado-aw-linux-x64" - CHECKSUM_URL="${DOWNLOAD_URL}.sha256" + CHECKSUM_URL="https://github.com/githubnext/ado-aw/releases/download/v${COMPILER_VERSION}/checksums.txt" mkdir -p "$DOWNLOAD_DIR" echo "Downloading ado-aw v${COMPILER_VERSION} from GitHub Releases..." curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64" "$DOWNLOAD_URL" - curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64.sha256" "$CHECKSUM_URL" + curl -fsSL -o "$DOWNLOAD_DIR/checksums.txt" "$CHECKSUM_URL" echo "Verifying checksum..." cd "$DOWNLOAD_DIR" - sha256sum --check ado-aw-linux-x64.sha256 + sha256sum -c checksums.txt --ignore-missing | grep -q ": OK" mv ado-aw-linux-x64 ado-aw chmod +x ado-aw displayName: "Download agentic pipeline compiler (v{{ compiler_version }})" @@ -172,23 +172,25 @@ jobs: - task: DockerInstaller@0 displayName: "Install Docker" - - task: DownloadPipelineArtifact@2 - displayName: "Download AWF (Agentic Workflow Firewall)" - name: awfdrop - inputs: - source: "specific" - project: "4x4" - pipeline: 2450 - runVersion: "latestFromBranch" - branchName: "refs/heads/ms/main" - artifact: "gh-aw-firewall-linux-x64" - targetPath: "$(Pipeline.Workspace)/awf" - - bash: | - chmod +x "$(Pipeline.Workspace)/awf/awf" + AWF_VERSION="{{ firewall_version }}" + DOWNLOAD_DIR="$(Pipeline.Workspace)/awf" + DOWNLOAD_URL="https://github.com/github/gh-aw-firewall/releases/download/v${AWF_VERSION}/awf-linux-x64" + CHECKSUM_URL="https://github.com/github/gh-aw-firewall/releases/download/v${AWF_VERSION}/checksums.txt" + + mkdir -p "$DOWNLOAD_DIR" + echo "Downloading AWF v${AWF_VERSION} from GitHub Releases..." + curl -fsSL -o "$DOWNLOAD_DIR/awf-linux-x64" "$DOWNLOAD_URL" + curl -fsSL -o "$DOWNLOAD_DIR/checksums.txt" "$CHECKSUM_URL" + + echo "Verifying checksum..." + cd "$DOWNLOAD_DIR" + sha256sum -c checksums.txt --ignore-missing | grep -q ": OK" + mv awf-linux-x64 awf + chmod +x awf echo "##vso[task.prependpath]$(Pipeline.Workspace)/awf" - "$(Pipeline.Workspace)/awf/awf" --version || echo "AWF binary ready" - displayName: "Setup AWF" + ./awf --version || echo "AWF binary ready" + displayName: "Download AWF (Agentic Workflow Firewall) v{{ firewall_version }}" - bash: | docker pull ghcr.io/github/gh-aw-firewall/squid:latest @@ -312,16 +314,16 @@ jobs: COMPILER_VERSION="{{ compiler_version }}" DOWNLOAD_DIR="$(Pipeline.Workspace)/agentic-pipeline-compiler" DOWNLOAD_URL="https://github.com/githubnext/ado-aw/releases/download/v${COMPILER_VERSION}/ado-aw-linux-x64" - CHECKSUM_URL="${DOWNLOAD_URL}.sha256" + CHECKSUM_URL="https://github.com/githubnext/ado-aw/releases/download/v${COMPILER_VERSION}/checksums.txt" mkdir -p "$DOWNLOAD_DIR" echo "Downloading ado-aw v${COMPILER_VERSION} from GitHub Releases..." curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64" "$DOWNLOAD_URL" - curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64.sha256" "$CHECKSUM_URL" + curl -fsSL -o "$DOWNLOAD_DIR/checksums.txt" "$CHECKSUM_URL" echo "Verifying checksum..." cd "$DOWNLOAD_DIR" - sha256sum --check ado-aw-linux-x64.sha256 + sha256sum -c checksums.txt --ignore-missing | grep -q ": OK" mv ado-aw-linux-x64 ado-aw chmod +x ado-aw displayName: "Download agentic pipeline compiler (v{{ compiler_version }})" @@ -329,23 +331,25 @@ jobs: - task: DockerInstaller@0 displayName: "Install Docker" - - task: DownloadPipelineArtifact@2 - displayName: "Download AWF (Agentic Workflow Firewall)" - name: awfdrop - inputs: - source: "specific" - project: "4x4" - pipeline: 2450 - runVersion: "latestFromBranch" - branchName: "refs/heads/ms/main" - artifact: "gh-aw-firewall-linux-x64" - targetPath: "$(Pipeline.Workspace)/awf" - - bash: | - chmod +x "$(Pipeline.Workspace)/awf/awf" + AWF_VERSION="{{ firewall_version }}" + DOWNLOAD_DIR="$(Pipeline.Workspace)/awf" + DOWNLOAD_URL="https://github.com/github/gh-aw-firewall/releases/download/v${AWF_VERSION}/awf-linux-x64" + CHECKSUM_URL="https://github.com/github/gh-aw-firewall/releases/download/v${AWF_VERSION}/checksums.txt" + + mkdir -p "$DOWNLOAD_DIR" + echo "Downloading AWF v${AWF_VERSION} from GitHub Releases..." + curl -fsSL -o "$DOWNLOAD_DIR/awf-linux-x64" "$DOWNLOAD_URL" + curl -fsSL -o "$DOWNLOAD_DIR/checksums.txt" "$CHECKSUM_URL" + + echo "Verifying checksum..." + cd "$DOWNLOAD_DIR" + sha256sum -c checksums.txt --ignore-missing | grep -q ": OK" + mv awf-linux-x64 awf + chmod +x awf echo "##vso[task.prependpath]$(Pipeline.Workspace)/awf" - "$(Pipeline.Workspace)/awf/awf" --version || echo "AWF binary ready" - displayName: "Setup AWF" + ./awf --version || echo "AWF binary ready" + displayName: "Download AWF (Agentic Workflow Firewall) v{{ firewall_version }}" - bash: | docker pull ghcr.io/github/gh-aw-firewall/squid:latest @@ -504,16 +508,16 @@ jobs: COMPILER_VERSION="{{ compiler_version }}" DOWNLOAD_DIR="$(Pipeline.Workspace)/agentic-pipeline-compiler" DOWNLOAD_URL="https://github.com/githubnext/ado-aw/releases/download/v${COMPILER_VERSION}/ado-aw-linux-x64" - CHECKSUM_URL="${DOWNLOAD_URL}.sha256" + CHECKSUM_URL="https://github.com/githubnext/ado-aw/releases/download/v${COMPILER_VERSION}/checksums.txt" mkdir -p "$DOWNLOAD_DIR" echo "Downloading ado-aw v${COMPILER_VERSION} from GitHub Releases..." curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64" "$DOWNLOAD_URL" - curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64.sha256" "$CHECKSUM_URL" + curl -fsSL -o "$DOWNLOAD_DIR/checksums.txt" "$CHECKSUM_URL" echo "Verifying checksum..." cd "$DOWNLOAD_DIR" - sha256sum --check ado-aw-linux-x64.sha256 + sha256sum -c checksums.txt --ignore-missing | grep -q ": OK" mv ado-aw-linux-x64 ado-aw chmod +x ado-aw displayName: "Download agentic pipeline compiler (v{{ compiler_version }})" diff --git a/tests/compiler_tests.rs b/tests/compiler_tests.rs index 0743338..5416c21 100644 --- a/tests/compiler_tests.rs +++ b/tests/compiler_tests.rs @@ -145,8 +145,26 @@ fn test_compiled_yaml_structure() { "Template should download the compiler from GitHub Releases" ); assert!( - template_content.contains("sha256sum --check"), - "Template should verify checksum of downloaded compiler" + template_content.contains("sha256sum -c checksums.txt --ignore-missing | grep -q \": OK\""), + "Template should verify checksum using checksums.txt with grep confirmation" + ); + + // Verify AWF (Agentic Workflow Firewall) is downloaded from GitHub Releases, not ADO pipeline artifacts + assert!( + !template_content.contains("pipeline: 2450"), + "Template should not reference ADO pipeline 2450 for the firewall" + ); + assert!( + !template_content.contains("DownloadPipelineArtifact"), + "Template should not use DownloadPipelineArtifact task" + ); + assert!( + template_content.contains("github.com/github/gh-aw-firewall/releases"), + "Template should download AWF from GitHub Releases" + ); + assert!( + template_content.contains("{{ firewall_version }}"), + "Template should contain firewall_version marker" ); } @@ -348,7 +366,13 @@ fn test_compiled_output_no_unreplaced_markers() { ); assert!( compiled.contains("github.com/githubnext/ado-aw/releases"), - "Compiled output should reference GitHub Releases" + "Compiled output should reference GitHub Releases for the compiler" + ); + + // Verify the AWF firewall version was correctly substituted + assert!( + compiled.contains("github.com/github/gh-aw-firewall/releases"), + "Compiled output should reference GitHub Releases for AWF" ); let _ = fs::remove_dir_all(&temp_dir);