Skip to content

feat(rest): add SigV4 auth manager for the REST catalog - #2660

Open
plusplusjiajia wants to merge 8 commits into
apache:mainfrom
plusplusjiajia:feat/rest-sigv4
Open

feat(rest): add SigV4 auth manager for the REST catalog#2660
plusplusjiajia wants to merge 8 commits into
apache:mainfrom
plusplusjiajia:feat/rest-sigv4

Conversation

@plusplusjiajia

@plusplusjiajia plusplusjiajia commented Jun 16, 2026

Copy link
Copy Markdown
Member

Stacked on #2838 — the first 7 commits are from that PR; only the last commit is this PR. Will be rebased once it merges.

Which issue does this PR close?

  • Follow-up to #2838, split from the #2815 prototype per review.

What changes are included in this PR?

SigV4 as a SigV4AuthManager wrapping a delegate auth manager, per #2838's design:

  • The delegate authenticates first (e.g. an OAuth2 bearer); its Authorization is relocated to Original-Authorization (Java convention) and included in the signature, then the request is SigV4-signed.
  • SigV4Signer follows AWS canonical-request rules with Java parity (path normalization + double encoding, all-headers-minus-blacklist, IcebergRest/StandardAws payload-hash modes).
  • Properties match Java's AwsProperties (rest.signing-region, rest.signing-name default execute-api, rest.access-key-id/rest.secret-access-key/rest.session-token, single-source credential resolution). Delegate defaults to oauth2; an injected signer is never rebuilt from server properties; signed catalogs
    don't follow redirects.

@dannycjones

Copy link
Copy Markdown
Contributor

There's a PR open for SigV4 signing, is this picking up from that one? #2311

I ask as its had a few rounds of feedback already.

@plusplusjiajia

plusplusjiajia commented Jun 17, 2026

Copy link
Copy Markdown
Member Author

There's a PR open for SigV4 signing, is this picking up from that one? #2311

I ask as its had a few rounds of feedback already.

@dannycjones Thanks for the pointer — I'd missed #2311, just took a look and compared the two. Mine isn't based on it: it follows Iceberg Java's RESTSigV4AuthSessionRESTSigV4AuthSession(apache/iceberg#11995) and the merged iceberg-cpp version(apache/iceberg-cpp#616). The main difference I see is the base64-encoded x-amz-content-sha256 convention (the Java behavior), which #2311's hex-only signing doesn't cover and which some REST servers require.
I'm keen to help get SigV4 support landed either way. Since #2311 is further along, I'm happy to fold the base64 support into it rather than duplicate — or carry this one forward if you'd prefer. Whatever helps move it forward.

@CTTY

CTTY commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

I haven't thought quite clearly about this part yet, my general intuition is that it would be better to start from something like a AuthManager so we have a clean interface before diving into the specific implementation.

Would be happy to hear more thoughts on this

Comment thread crates/catalog/rest/src/catalog.rs Outdated
}

/// Injects a custom request signer, overriding the `rest.sigv4-*` configuration.
pub fn with_signer(mut self, signer: Arc<dyn HttpRequestSigner>) -> Self {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need a more general design rather than just a signer. some authentication mechanism is token-based.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@CTTY I dug into how Java structures this, and I think your point is well taken: OAuth2 token handling is hardcoded inside HttpClient today, and this PR adds a second, parallel mechanism that is mutually exclusive with token auth. In Java the two compose — SigV4AuthManager wraps a delegate session, relocates its Authorization header to X-Iceberg-Authorization, then signs — so SigV4-over-OAuth2 is a real combination the current design can't express.

Is something along these lines what you had in mind, mirroring Java's AuthManager/AuthSession?

#[async_trait]
pub trait AuthManager: Debug + Send + Sync {
    /// Session used for catalog-level requests.
    async fn catalog_session(
        &self,
        props: &HashMap<String, String>,
    ) -> Result<Arc<dyn AuthSession>>;
    // room to grow, matching Java: init_session() for the config
    // handshake, table_session() for table-scoped auth, close().
}

#[async_trait]
pub trait AuthSession: Debug + Send + Sync {
    /// Applies authentication to an outgoing request (headers, signing, ...).
    async fn authenticate(&self, request: &mut reqwest::Request) -> Result<()>;
}

with NoopAuthManager / OAuth2Manager (existing logic extracted, behavior unchanged) / SigV4AuthManager (wrapping a delegate, Java-style) as the initial implementations, selected via rest.auth.type or injected through the builder.

If that matches your intuition, my instinct would be to land the interface plus the OAuth2 extraction as a small standalone refactor first, then rework this PR on top as the SigV4 implementation — which would also give #2311 a common landing spot.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prototype is up as a draft PR: #2815 — full AuthManager/AuthSession shape with Noop/OAuth2/SigV4 managers; details and known simplifications in the PR description.

IcebergRest,
/// Standard AWS SigV4 style: hex everywhere (e.g. AWS Glue).
StandardAws,
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know this detail until this PR. Thanks for capturing this!

@plusplusjiajia

Copy link
Copy Markdown
Member Author

Update: this PR will be reworked in place as a SigV4AuthManager on top of #2838 (implementation ready locally, tracking that PR's review). Will push once #2838 merges.

- hold the token lock across the OAuth2 exchange (single flight)
- three-state AuthRequestBody: Empty/Buffered/Streaming; pub AuthRequest::new
- zeroize OAuth2 secrets via a redacting SensitiveString
- split the OAuth2 session into static-token and client-credentials types
- init_session returns Box<dyn AuthSession>; catalog_session stays Arc
- unset rest.auth.type resolves to oauth2 only when a token, credential
  or oauth2-server-uri is configured, none otherwise
- drop RestCatalog::invalidate_token/regenerate_token and
  AuthSession::invalidate/refresh (out-of-box refresh tracked separately)
- hint at with_auth_manager for unknown auth types
Replaces the crate-private SensitiveString with the equivalent
iceberg::Credential introduced in apache#2836.
@plusplusjiajia plusplusjiajia changed the title feat(rest): support AWS SigV4 request signing for the REST catalog feat(rest): add SigV4 auth manager for the REST catalog Aug 5, 2026
@plusplusjiajia

Copy link
Copy Markdown
Member Author

Pushed the rework as planned — stacked on #2838 for now (see the note in the description; only the last commit is this PR). Will rebase to a single commit once #2838 merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants