may01 1024#9
Merged
Merged
Conversation
mattbnz
commented
May 1, 2026
- Strip reverse proxy headers in SigV4 processor to fix SignatureDoesNotMatch (Strip reverse proxy headers in SigV4 processor to fix SignatureDoesNo… superfly/tokenizer#42)
- Address bug where aws v4 signatures get their service/region swapped in creds. (Address bug where aws v4 signatures get their service/region swapped in creds. superfly/tokenizer#43)
- Add JWT signing processor for Google service account auth (Add JWT signing processor for Google service account auth superfly/tokenizer#44)
- Client credentials processor (Client credentials processor superfly/tokenizer#45)
- Add more documentation about using tokenizer (Add more documentation about using tokenizer superfly/tokenizer#46)
- Document more processors (Document more processors superfly/tokenizer#48)
- Make tokenizer a multi command binary (Make tokenizer a multi command binary superfly/tokenizer#49)
- Log all decoded tokens and their parameters (Log all decoded tokens and their parameters superfly/tokenizer#47)
- Raise Go toolchain floor to 1.25.9 and bump x/crypto (Raise Go toolchain floor to 1.25.9 and bump x/crypto superfly/tokenizer#50)
- Bump low-risk dependencies (Bump low-risk dependencies superfly/tokenizer#51)
- Add GitHub App processor for installation token auth (Add GitHub App processor for installation token auth superfly/tokenizer#52)
…tMatch (superfly#42) When tokenizer runs behind a reverse proxy (e.g., fly-proxy), standard proxy headers like X-Forwarded-For, Via, etc. get injected into requests. These headers were being signed by the SigV4 processor, but could then be modified by outbound proxies, causing AWS signature verification to fail. Also adds a FIXME noting that region/service parsing from the credential scope appears to be swapped (left unchanged to avoid breaking existing clients).
…in creds. (superfly#43) There's a bug in the aws v4 processor. It reads the existing signature and then updates it with a new signature. It extracts the region and service fields from the old signature in the wrong order, so when it generates a new signature, they are swapped to service then region. Unfortunately we have active use cases that depend on this behavior. So this commit introduces an optional fix, with the default behavior being to preserve the field swapping bug behavior. - Add new flag to the processor "no_swap", defaulting to false. When not present or fault the existing swapping behavior is preserved. When it is true, the fields are not swapped. Co-authored-by: mjbraun <matt@fly.io>
* Add .DS_Store, binary, and scratch files to .gitignore Also deduplicate the .vscode entry. * Add JWTProcessorConfig for Google service account auth Implements a stateless JWT-bearer token exchange flow: 1. Client sends sealed SA private key to tokenizer, proxied to Google's token endpoint 2. Tokenizer signs a JWT (RS256), builds the exchange request body, intercepts Google's response, seals the access token into a new InjectProcessorConfig, and returns the sealed blob to the caller 3. Caller uses the sealed access token for subsequent API requests via the existing InjectProcessor path Key design decisions: - Tokenizer is completely stateless (no cache). Multiple instances and blue/green deploys work without shared state. - The caller never sees any plaintext credential. The private key, JWT, and access token only exist in tokenizer's process memory. - Response body rewriting is a new capability, contained to this processor via the ResponseProcessorConfig interface. - SealingContext passes the parent Secret's auth config and validators into the processor so the derived sealed token carries the same authorization requirements. - Sub and scopes are overridable at request time via params. Adds golang-jwt/jwt/v5 dependency. * Document jwt_processor and SigV4 no_swap in README Adds documentation for: - jwt_processor: two-step sealed token exchange flow for Google SA auth - sigv4_processor: documents the no_swap bug-compatibility field * Add unsealtoken CLI tool for debugging sealed secrets * Address PR review: ECDSA/EdDSA support, rename ctx to sctx, fly-src auth note - Generalize parseKey() to return crypto.Signer, supporting RSA, ECDSA (P-256/P-384/P-521), and Ed25519 keys with auto-selected signing method - Rename SealingContext parameter from ctx to sctx to avoid confusion with context.Context - Add fly-src auth deployment note to README per reviewer suggestion - Add unit tests for ECDSA (ES256) and Ed25519 (EdDSA) signing - Add real-world e2e test (gated on GOOGLE_SA_KEY_FILE env var)
* Add OAuth2 client_credentials processor Implements the client_credentials grant (RFC 6749 §4.4) following the same two-step sealed pattern as JWTProcessorConfig - the caller never sees the plaintext secret or access token. Also extracts a shared sealTokenResponse helper from JWTProcessorConfig so both processors share the response-sealing logic without duplication. * gofmt
* Add more documentation about using tokenizer
* docuemnt more processors * fix strip hazmat for the sigv4 processor to include the new "no_swap" field. Currently we leave it uninitialized, so its always logging as "false" even when provided as "true".
The tokenizer command will support subcommands for displaying its version, running the server, displaying the seal key, sealing tokens, and unsealing tokens. This will allow the deployed binary to be used directly for multiple purposes without shipping seperate helpers and will simplify instructions for setting up and using the tokenizer.
Previously we started logging sanitized decoded tokens, but we only captured one such decoded token per request. Requests can contain multiple tokens and optionally contain parameters that affect token injection. These changes capture all of the decoded tokens with their parameters and log them. This needs to be done with care. I don't believe we're putting any sensitive data in tokenizer params, but if we are, they would land in the tokenizer's logs.
Go 1.24 reached end-of-life when 1.26 shipped; the Go security team is
no longer backporting stdlib fixes to that branch. govulncheck flagged
four call-reachable stdlib vulnerabilities against golang:1.24-alpine
(= go1.24.13) that have no 1.24 patch:
GO-2026-4870 crypto/tls TLS 1.3 KeyUpdate DoS (reachable from the
inbound proxy listener and the outbound
TLS dialer)
GO-2026-4947 crypto/x509 chain-building DoS
GO-2026-4946 crypto/x509 policy-validation DoS
GO-2026-4601 net/url IPv6 host literal misparse
Pin the Dockerfile to golang:1.25.9-alpine (which contains all four
fixes) and raise the go.mod directive to 1.25.0. That in turn unblocks
x/crypto v0.50.0 and the current x/exp snapshot, whose latest releases
already require Go 1.25. govulncheck on the result reports clean.
go mod tidy also promoted golang-jwt/jwt/v5 and icholy/replace from
indirect to direct to match how they're actually imported.
Patch-level updates to keep deps current: - logrus 1.9.3 -> 1.9.4 - alecthomas/repr 0.4.0 -> 0.5.2 - google/uuid 1.3.0 -> 1.6.0 - vmihailenco/msgpack/v5 5.3.5 -> 5.4.1
GitHub Apps use a bespoke flow (JWT in the Authorization header, not an OAuth2 form body) that JWTProcessorConfig can't express. This adds GitHubAppProcessorConfig following the same sealed two-step pattern: sign a 10-minute RS256 JWT, exchange it for an installation token, and return a SealedTokenResponse whose inner InjectProcessorConfig is pinned to api.github.com with a "token %s" Authorization format - so neither the private key nor the installation token is ever plaintext outside tokenizer's process memory.
Brings in 11 upstream commits including JWT/Google service account, client credentials, and GitHub App processors; multi-command binary refactor; and SigV4 bug fixes (superfly#42, superfly#43). Conflict resolution: - Dockerfile: took upstream 1.25.9-alpine pin - go.mod: kept our higher aws-sdk-go-v2/goproxy/macaroon/smithy-go versions, took upstream x/crypto v0.50.0 and added golang-jwt/jwt/v5 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
auto-merge was automatically disabled
May 1, 2026 02:05
Rebase failed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.