mirror of
https://gitea.com/gitea/act_runner
synced 2026-09-21 19:37:07 +02:00
fix: stop artifact uploads depending on the cache server reaching Gitea (#1216)
Cache v2 makes the cache server the `ACTIONS_RESULTS_URL` origin, so artifact calls arrived there and were proxied on to Gitea, failing whenever it could not reach the instance. - Artifact calls are answered with a redirect, so the cache server opens no connection to Gitea. A scheme change or an untrusted instance is still proxied, but there the cache server is the runner itself, which already reaches Gitea. - Failures answer in twirp, not an empty `502` that clients report as `Unexpected end of JSON input`. - `cache.v2: false` really points artifacts at Gitea now. - Cache reservations are bound to the job that made them, so two jobs saving one key cannot commit against each other's upload, and a retry after a lost answer no longer fails a saved entry. - The toolkit patch, which edits the GitHub-host check out of an action's bundle, was left in the shared checkout where a job running with `runner.patch_actions: false` could inherit it. It is put back after the job's copy. - `exec` names an origin for the cache v2 it advertises, and masks its runtime token. Behaviour changes: `no_proxy` no longer exempts `cache.external_server`, and `cache.enabled: false` also stops external registration. Fixes https://gitea.com/gitea/runner/issues/1208 Fixes https://gitea.com/gitea/runner/issues/1211 Assisted by Claude (Opus 5). Reviewed-on: https://gitea.com/gitea/runner/pulls/1216 Reviewed-by: bircni <bircni@icloud.com> Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
@@ -603,12 +603,12 @@ func (h *Handler) bearerAuth(handler httprouter.Handle) httprouter.Handle {
|
||||
h.logger.Debugf("%s %s", r.Method, r.URL.Path)
|
||||
token := bearerToken(r)
|
||||
if token == "" {
|
||||
h.responseJSON(w, r, http.StatusUnauthorized, errors.New("missing bearer token"))
|
||||
h.unauthorized(w, r, errors.New("missing bearer token"))
|
||||
return
|
||||
}
|
||||
cred, ok := h.lookupCredential(token)
|
||||
if !ok {
|
||||
h.responseJSON(w, r, http.StatusUnauthorized, errors.New("unknown bearer token"))
|
||||
h.unauthorized(w, r, errors.New("unknown bearer token"))
|
||||
return
|
||||
}
|
||||
ctx := context.WithValue(r.Context(), credKey{}, cred)
|
||||
@@ -617,6 +617,14 @@ func (h *Handler) bearerAuth(handler httprouter.Handle) httprouter.Handle {
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Handler) unauthorized(w http.ResponseWriter, r *http.Request, err error) {
|
||||
if strings.HasPrefix(r.URL.Path, cacheServiceV2Path) {
|
||||
h.twirpError(w, r, twirpUnauthenticated, err)
|
||||
return
|
||||
}
|
||||
h.responseJSON(w, r, http.StatusUnauthorized, err)
|
||||
}
|
||||
|
||||
// signedAuth authenticates a signed URL. purpose separates the flavours of URL the
|
||||
// handler hands out, so one cannot be replayed as another; see computeSignature.
|
||||
func (h *Handler) signedAuth(purpose string, handler httprouter.Handle) httprouter.Handle {
|
||||
@@ -720,6 +728,12 @@ func (h *Handler) internalRevoke(w http.ResponseWriter, r *http.Request, _ httpr
|
||||
h.responseJSON(w, r, http.StatusOK)
|
||||
}
|
||||
|
||||
// hashedToken fingerprints a job's bearer, so a reservation can tell its own retry from another job.
|
||||
func hashedToken(token string) string {
|
||||
sum := sha256.Sum256([]byte(token))
|
||||
return hex.EncodeToString(sum[:])
|
||||
}
|
||||
|
||||
func bearerToken(r *http.Request) string {
|
||||
auth := r.Header.Get("Authorization")
|
||||
const prefix = "Bearer "
|
||||
@@ -805,8 +819,8 @@ func findExactCache(db *bolthold.Store, repo, key, version string, complete bool
|
||||
}
|
||||
cache := &Cache{}
|
||||
err := db.FindOne(cache,
|
||||
bolthold.Where("Repo").Eq(repo).
|
||||
And("Key").Eq(key).
|
||||
bolthold.Where("Key").Eq(key).Index("Key").
|
||||
And("Repo").Eq(repo).
|
||||
And("Version").Eq(version).
|
||||
And("Complete").Eq(complete).
|
||||
SortBy(sortBy).Reverse())
|
||||
|
||||
Reference in New Issue
Block a user