From eee80bd9c4f7a64efdcfb1a90a1385deda9d4d81 Mon Sep 17 00:00:00 2001 From: Anthony Viriya <16130362+avltree9798@users.noreply.github.com> Date: Tue, 16 Jun 2026 17:49:24 +0100 Subject: [PATCH 1/3] Add support for custom HTTP headers in GitLab CI Adds an optional FLEET_CUSTOM_HEADERS variable (comma-separated "Header:Value" pairs) applied to both the fleetctl version check (curl) and fleetctl (config set --custom-header, which persists to ~/.fleet/config so gitops uses them too). This enables running GitOps against a Fleet server behind a reverse proxy or zero-trust access layer that requires extra request headers, e.g. a Cloudflare Access service token (CF-Access-Client-Id / CF-Access-Client-Secret). Defaults to empty, so existing pipelines are unaffected. --- .gitlab-ci.yml | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 04afa15..e6fd077 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,6 +2,16 @@ fleet-gitops: image: node:22 variables: FLEET_DRY_RUN_ONLY: true + # Optional. Extra HTTP headers to send on every request to Fleet. They are applied to + # both the version check (curl) and all fleetctl commands (config set / gitops). + # + # Format: a comma-separated list of "Header:Value" pairs. Header values cannot contain + # commas. Leave empty to send no extra headers. + # + # Set the real value as a (masked) CI/CD variable in Settings > CI/CD > Variables, which + # overrides this default. Example for a Cloudflare Access service token: + # FLEET_CUSTOM_HEADERS: "CF-Access-Client-Id:,CF-Access-Client-Secret:" + FLEET_CUSTOM_HEADERS: "" rules: - if: $CI_PIPELINE_SOURCE == 'merge_request_event' - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH @@ -14,8 +24,19 @@ fleet-gitops: - apt-get -qq update - apt-get install -y 'jq=1.6-2.1*' script: + # Parse FLEET_CUSTOM_HEADERS into argument arrays for curl and fleetctl. + - | + CURL_HEADER_ARGS=() + FLEETCTL_HEADER_ARGS=() + if [[ -n "$FLEET_CUSTOM_HEADERS" ]]; then + IFS=',' read -ra _CUSTOM_HEADERS <<< "$FLEET_CUSTOM_HEADERS" + for _header in "${_CUSTOM_HEADERS[@]}"; do + CURL_HEADER_ARGS+=(--header "$_header") + FLEETCTL_HEADER_ARGS+=(--custom-header "$_header") + done + fi - > - FLEET_VERSION="$(curl "$FLEET_URL/api/v1/fleet/version" --header "Authorization: Bearer $FLEET_API_TOKEN" --fail --silent | jq --raw-output '.version')" + FLEET_VERSION="$(curl "$FLEET_URL/api/v1/fleet/version" --header "Authorization: Bearer $FLEET_API_TOKEN" "${CURL_HEADER_ARGS[@]}" --fail --silent | jq --raw-output '.version')" - > if [[ -n "$FLEET_VERSION" ]] ; then npm install -g "fleetctl@$FLEET_VERSION" || npm install -g fleetctl @@ -23,5 +44,5 @@ fleet-gitops: echo "Failed to get Fleet version from $FLEET_URL, installing latest version of fleetctl" npm install -g fleetctl fi - - fleetctl config set --address $FLEET_URL --token $FLEET_API_TOKEN + - fleetctl config set --address $FLEET_URL --token $FLEET_API_TOKEN "${FLEETCTL_HEADER_ARGS[@]}" - ./gitops.sh From 55844ae52bde5fe3bb36a62c5d8a6d1f93d8d5ff Mon Sep 17 00:00:00 2001 From: Anthony Viriya <16130362+avltree9798@users.noreply.github.com> Date: Wed, 17 Jun 2026 18:31:55 +0100 Subject: [PATCH 2/3] Add support for custom HTTP headers in GitHub Actions Mirrors the GitLab CI change for the GitHub Actions path. FLEET_CUSTOM_HEADERS (comma-separated "Header:Value" pairs) is applied to the fleetctl version check (curl) and to fleetctl (config set --custom-header, which persists the headers so gitops uses them too) across the gitops-action, gitops-action-fleets, and gitops-action-rc composite actions, and is passed through the workflow env block. This enables running GitOps against a Fleet server behind a reverse proxy or zero-trust access layer that requires extra request headers, e.g. a Cloudflare Access service token (CF-Access-Client-Id / CF-Access-Client-Secret). Unset/empty by default, so existing workflows are unaffected. --- .github/gitops-action-fleets/action.yml | 26 +++++++++++++++++++++++-- .github/gitops-action-rc/action.yml | 13 ++++++++++++- .github/gitops-action/action.yml | 26 +++++++++++++++++++++++-- .github/workflows/workflow.yml | 4 ++++ 4 files changed, 64 insertions(+), 5 deletions(-) diff --git a/.github/gitops-action-fleets/action.yml b/.github/gitops-action-fleets/action.yml index 6acbe2f..f6b30b4 100644 --- a/.github/gitops-action-fleets/action.yml +++ b/.github/gitops-action-fleets/action.yml @@ -20,7 +20,18 @@ runs: working-directory: ${{ inputs.working-directory }} run: | FLEET_URL="${FLEET_URL%/}" - FLEET_VERSION="$(curl "$FLEET_URL/api/v1/fleet/version" --header "Authorization: Bearer $FLEET_API_TOKEN" --fail --silent | jq --raw-output '.version')" + + # Build optional custom request headers from FLEET_CUSTOM_HEADERS, a comma-separated + # list of "Header:Value" pairs (e.g. a Cloudflare Access service token). Empty by default. + CURL_HEADER_ARGS=() + if [[ -n "${FLEET_CUSTOM_HEADERS:-}" ]]; then + IFS=',' read -ra _CUSTOM_HEADERS <<< "$FLEET_CUSTOM_HEADERS" + for _header in "${_CUSTOM_HEADERS[@]}"; do + CURL_HEADER_ARGS+=(--header "$_header") + done + fi + + FLEET_VERSION="$(curl "$FLEET_URL/api/v1/fleet/version" --header "Authorization: Bearer $FLEET_API_TOKEN" "${CURL_HEADER_ARGS[@]}" --fail --silent | jq --raw-output '.version')" DEFAULT_FLEETCTL_VERSION="4.86.1" # Decide which fleetctl version to install: @@ -48,7 +59,18 @@ runs: - name: Configure fleetctl shell: bash working-directory: ${{ inputs.working-directory }} - run: fleetctl config set --address ${{ env.FLEET_URL }} --token ${{ env.FLEET_API_TOKEN }} + run: | + # Build optional custom request headers from FLEET_CUSTOM_HEADERS, a comma-separated + # list of "Header:Value" pairs. fleetctl persists them and sends them on every request, + # so the gitops commands below use them too. + CUSTOM_HEADER_ARGS=() + if [[ -n "${FLEET_CUSTOM_HEADERS:-}" ]]; then + IFS=',' read -ra _CUSTOM_HEADERS <<< "$FLEET_CUSTOM_HEADERS" + for _header in "${_CUSTOM_HEADERS[@]}"; do + CUSTOM_HEADER_ARGS+=(--custom-header "$_header") + done + fi + fleetctl config set --address "$FLEET_URL" --token "$FLEET_API_TOKEN" "${CUSTOM_HEADER_ARGS[@]}" - name: Run fleetctl gitops commands shell: bash diff --git a/.github/gitops-action-rc/action.yml b/.github/gitops-action-rc/action.yml index cfa560f..e605b70 100644 --- a/.github/gitops-action-rc/action.yml +++ b/.github/gitops-action-rc/action.yml @@ -37,7 +37,18 @@ runs: - name: Configure fleetctl shell: bash working-directory: ${{ inputs.working-directory }} - run: fleetctl config set --address ${{ env.FLEET_URL }} --token ${{ env.FLEET_API_TOKEN }} + run: | + # Build optional custom request headers from FLEET_CUSTOM_HEADERS, a comma-separated + # list of "Header:Value" pairs. fleetctl persists them and sends them on every request, + # so the gitops commands below use them too. + CUSTOM_HEADER_ARGS=() + if [[ -n "${FLEET_CUSTOM_HEADERS:-}" ]]; then + IFS=',' read -ra _CUSTOM_HEADERS <<< "$FLEET_CUSTOM_HEADERS" + for _header in "${_CUSTOM_HEADERS[@]}"; do + CUSTOM_HEADER_ARGS+=(--custom-header "$_header") + done + fi + fleetctl config set --address "$FLEET_URL" --token "$FLEET_API_TOKEN" "${CUSTOM_HEADER_ARGS[@]}" - name: Run fleetctl gitops commands shell: bash diff --git a/.github/gitops-action/action.yml b/.github/gitops-action/action.yml index e2da8a0..9f4917c 100644 --- a/.github/gitops-action/action.yml +++ b/.github/gitops-action/action.yml @@ -20,7 +20,18 @@ runs: working-directory: ${{ inputs.working-directory }} run: | FLEET_URL="${FLEET_URL%/}" - FLEET_VERSION="$(curl "$FLEET_URL/api/v1/fleet/version" --header "Authorization: Bearer $FLEET_API_TOKEN" --fail --silent | jq --raw-output '.version')" + + # Build optional custom request headers from FLEET_CUSTOM_HEADERS, a comma-separated + # list of "Header:Value" pairs (e.g. a Cloudflare Access service token). Empty by default. + CURL_HEADER_ARGS=() + if [[ -n "${FLEET_CUSTOM_HEADERS:-}" ]]; then + IFS=',' read -ra _CUSTOM_HEADERS <<< "$FLEET_CUSTOM_HEADERS" + for _header in "${_CUSTOM_HEADERS[@]}"; do + CURL_HEADER_ARGS+=(--header "$_header") + done + fi + + FLEET_VERSION="$(curl "$FLEET_URL/api/v1/fleet/version" --header "Authorization: Bearer $FLEET_API_TOKEN" "${CURL_HEADER_ARGS[@]}" --fail --silent | jq --raw-output '.version')" DEFAULT_FLEETCTL_VERSION="4.86.1" # Decide which fleetctl version to install: @@ -48,7 +59,18 @@ runs: - name: Configure fleetctl shell: bash working-directory: ${{ inputs.working-directory }} - run: fleetctl config set --address ${{ env.FLEET_URL }} --token ${{ env.FLEET_API_TOKEN }} + run: | + # Build optional custom request headers from FLEET_CUSTOM_HEADERS, a comma-separated + # list of "Header:Value" pairs. fleetctl persists them and sends them on every request, + # so the gitops commands below use them too. + CUSTOM_HEADER_ARGS=() + if [[ -n "${FLEET_CUSTOM_HEADERS:-}" ]]; then + IFS=',' read -ra _CUSTOM_HEADERS <<< "$FLEET_CUSTOM_HEADERS" + for _header in "${_CUSTOM_HEADERS[@]}"; do + CUSTOM_HEADER_ARGS+=(--custom-header "$_header") + done + fi + fleetctl config set --address "$FLEET_URL" --token "$FLEET_API_TOKEN" "${CUSTOM_HEADER_ARGS[@]}" - name: Run fleetctl gitops commands shell: bash diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 57a42d6..9f77087 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -40,6 +40,10 @@ jobs: FLEET_API_TOKEN: ${{ secrets.FLEET_API_TOKEN }} FLEET_PERSONAL_MOBILE_DEVICES_ENROLL_SECRET: ${{ secrets.FLEET_PERSONAL_MOBILE_DEVICES_ENROLL_SECRET }} FLEET_URL: ${{ secrets.FLEET_URL }} + # Optional. Comma-separated list of extra HTTP headers ("Header:Value") sent on every + # request to Fleet, e.g. a Cloudflare Access service token. Add it as a repository + # secret to use it; leave the secret unset to send no extra headers. + FLEET_CUSTOM_HEADERS: ${{ secrets.FLEET_CUSTOM_HEADERS }} FLEET_WORKSTATIONS_ENROLL_SECRET: ${{ secrets.FLEET_WORKSTATIONS_ENROLL_SECRET }} FLEET_GLOBAL_ENROLL_SECRET: ${{ secrets.FLEET_GLOBAL_ENROLL_SECRET }} From 621a5ca4d8787eaaeafdf53f25452deb4704f2ab Mon Sep 17 00:00:00 2001 From: Luke Heath Date: Sat, 20 Jun 2026 08:09:03 -0700 Subject: [PATCH 3/3] Apply suggestion from @lukeheath --- .github/gitops-action-fleets/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/gitops-action-fleets/action.yml b/.github/gitops-action-fleets/action.yml index e29445a..cf7b51e 100644 --- a/.github/gitops-action-fleets/action.yml +++ b/.github/gitops-action-fleets/action.yml @@ -32,7 +32,7 @@ runs: fi FLEET_VERSION="$(curl "$FLEET_URL/api/v1/fleet/version" --header "Authorization: Bearer $FLEET_API_TOKEN" "${CURL_HEADER_ARGS[@]}" --fail --silent | jq --raw-output '.version')" - DEFAULT_FLEETCTL_VERSION="4.87.1" + DEFAULT_FLEETCTL_VERSION="4.87.0" # Decide which fleetctl version to install: # If the server returns a clean version (e.g. 4.74.0), use that.