From 45671ae1323da4624ced8a39808877e69230d513 Mon Sep 17 00:00:00 2001 From: Wu Sheng Date: Mon, 31 Aug 2026 17:10:39 +0800 Subject: [PATCH] Add a read-only Docker Hub auth check The 5.0.0 chart push failed with 401 from auth.docker.io when asking for repository:apache/skywalking-helm:pull,push, and INFRA reports the configuration as correct. Those two statements cannot both be acted on without knowing what the CI credential actually gets back, and only a workflow run can ask that. Two baselines, measured from outside rather than assumed: anonymous http 200, granted=pull -- a REDUCED scope, not a refusal deliberately bad creds http 401 -- the signature CI saw That distinction matters and corrects an earlier reading of this failure. A 200 does not mean push was granted, so a client that failed to find its credential would have received a pull-only token and died later at the blob upload, not at this endpoint. CI failing here looks like credentials sent and rejected. So this asks for the same scope on the repository that fails and on one the same credential is known to push to -- apache/skywalking-oap-server, whose release publish succeeded on 2026-08-28 -- and prints the two answers side by side. Differing answers mean per-repository permission; identical 401s mean the token itself. Either way the next step stops being a guess. Nothing is published, pushed or written. There is no `set -x`, every curl discards its body, and the only things printed are an HTTP status and the token's "access" claim, which describes the repository's permissions rather than the identity. Dispatch-only, and meant to be deleted once the question is settled. The step's shell was extracted from the YAML and run to check it: it parses, the anonymous path works, the JWT "access" decode works, and stub credentials reproduce the 401. --- .github/workflows/dockerhub-auth-check.yaml | 112 ++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 .github/workflows/dockerhub-auth-check.yaml diff --git a/.github/workflows/dockerhub-auth-check.yaml b/.github/workflows/dockerhub-auth-check.yaml new file mode 100644 index 0000000..11cd1be --- /dev/null +++ b/.github/workflows/dockerhub-auth-check.yaml @@ -0,0 +1,112 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +name: dockerhub-auth-check + +# A read-only diagnostic. It publishes nothing, pushes nothing and writes nothing. +# +# `helm push` of the 5.0.0 chart failed with: +# +# GET https://auth.docker.io/token?scope=repository:apache/skywalking-helm:pull,push +# response status code 401: Unauthorized +# +# Two baselines, both measured rather than assumed: +# +# anonymous -> http 200, granted=pull (a REDUCED scope, not a refusal) +# deliberately bad -> http 401 (matches what CI saw) +# credentials +# +# So a client that failed to find its credential would have got a 200 with pull only, and the push +# would have died later at the blob upload -- not at this endpoint. CI's 401 is the signature of +# credentials that were sent and rejected. The one thing no one outside a workflow run can do is +# ask with the CI credential itself, which is what this does. +# +# It asks for the same scope on two repositories: the one that fails, and one the same credential +# is known to push to (apache/skywalking-oap-server, release publish succeeded 2026-08-28). +# +# Delete this workflow once the question is settled. +on: + workflow_dispatch: + +jobs: + check: + if: github.repository == 'apache/skywalking-helm' + runs-on: ubuntu-latest + timeout-minutes: 5 + name: Docker Hub auth check + steps: + - name: Ask Docker Hub for a push-scoped token + env: + DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }} + DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} + run: | + # No `set -x` anywhere in this file, and every curl discards its body: the only thing + # printed is an HTTP status and, where a token comes back, the "access" claim -- which + # describes the repository's permissions, not the identity's. + set -eu + + if [[ -z "${DOCKERHUB_USER}" || -z "${DOCKERHUB_TOKEN}" ]]; then + echo "::error::DOCKERHUB_USER / DOCKERHUB_TOKEN are empty in this repository" + exit 1 + fi + echo "both secrets are present and non-empty" + echo + + ask() { #