You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by "Xuanwo (via GitHub)" <gi...@apache.org> on 2026/07/28 08:22:24 UTC
[I] Add GrantCredential and Granter as a core scoped credential capability [opendal-reqsign]
Xuanwo opened a new issue, #801:
URL: https://github.com/apache/opendal-reqsign/issues/801
## Summary
Add scoped credential granting as a third public capability in `reqsign-core`, alongside credential loading and request signing:
```text
ProvideCredential<K> + SignRequest<Credential = K> -> Signer<K>
ProvideCredential<K> + GrantCredential<Credential = K> -> Granter<K>
```
`GrantCredential` turns an existing service credential into an independently usable, scoped, expiring credential. This covers Azure user delegation SAS, Google Credential Access Boundary downscoping, and selected AWS temporary credential operations without changing `ProvideCredential` or `SignRequest`.
## Public API
```rust
pub trait GrantCredential: Debug + Send + Sync + Unpin + 'static {
type Credential: SigningCredential;
fn required_valid_until(
&self,
credential: &Self::Credential,
expires_in: Option<Duration>,
) -> Timestamp;
fn grant_credential<'a>(
&'a self,
ctx: &'a Context,
credential: &'a Self::Credential,
expires_in: Option<Duration>,
) -> impl Future<Output = Result<Self::Credential>> + MaybeSend + 'a;
}
```
As with the existing async core traits, add `GrantCredentialDyn`, the blanket `GrantCredentialDyn for T: GrantCredential` implementation, and the `GrantCredential for Arc<T: GrantCredentialDyn>` bridge.
The orchestrator mirrors `Signer<K>`:
```rust
pub struct Granter<K: SigningCredential> {
// Context
// Arc<dyn ProvideCredentialDyn<Credential = K>>
// Arc<dyn GrantCredentialDyn<Credential = K>>
// cached source credential
}
impl<K: SigningCredential> Granter<K> {
pub fn new(
ctx: Context,
provider: impl ProvideCredential<Credential = K>,
granter: impl GrantCredential<Credential = K>,
) -> Self;
pub fn with_context(self, ctx: Context) -> Self;
pub fn with_credential_provider(
self,
provider: impl ProvideCredential<Credential = K>,
) -> Self;
pub fn with_credential_granter(
self,
granter: impl GrantCredential<Credential = K>,
) -> Self;
pub async fn grant(&self, expires_in: Option<Duration>) -> Result<K>;
}
```
`Granter<K>` intentionally has only one generic parameter. A concrete service granter binds one service-specific authorization request before it enters core:
```rust
let grant = UserDelegationSasGrant::for_blob(container, blob, permissions);
let operation = UserDelegationSasGranter::new(account, grant);
let credential = Granter::new(ctx, provider, operation)
.grant(Some(Duration::from_secs(3600)))
.await?;
```
Dynamic authorization does not require `Granter<K, G>`. The caller constructs another concrete granter, or clones a `Granter<K>` and replaces it with `with_credential_granter`. This keeps service-specific resource, permission, policy, and condition types out of `reqsign-core` while preserving compile-time validation in each service crate.
## Contract
- The source and result use the existing service `Credential` type. Azure can transform `BearerToken` or `SharedKey` into `SasToken`; AWS and Google return another value of their existing credential type.
- Issued expiration is stored in the returned credential and enforced by `SigningCredential::is_valid_at`. Do not add an `IssuedCredential<C>` envelope.
- `expires_in` is service-specific. `None` never means non-expiring. Implementations may require it, use a service default, or reject a caller-selected duration when the protocol fixes the lifetime.
- `Granter` caches only the source credential and applies the same freshness versus exact-usability checks as `Signer`. A returned credential must still be usable after all issuance I/O completes.
- Service-specific intermediate state, such as an Azure user delegation key cache, remains owned by the service granter and may be shared across externally constructed grant operations with `Arc`.
- Credential material and intermediate signing keys must be redacted from `Debug` output.
- No default provider chain gains a granter automatically. Scoped issuance must be wired explicitly and must not fall through to a broader ambient credential after failure.
A fixed configured `Granter<K>` may be adapted to `ProvideCredential` with a small wrapper that stores `expires_in` and returns `Ok(Some(granter.grant(...).await?))`. This is additive; `ProvideCredential` itself does not change.
## Service mapping
- Azure Service SAS and user delegation SAS implement `GrantCredential`. The public user delegation API in #751 should be a configured `UserDelegationSasGranter`, while the pure user-delegation-key-to-SAS calculation remains an internal helper. Azure SAS credentials must preserve absolute expiration as tracked by #750.
- Google Credential Access Boundary exchange in #749 implements `CredentialAccessBoundaryGranter`. GCE metadata, external account, and other ambient identity loaders remain `ProvideCredential` implementations.
- AWS AssumeRole, S3 Express CreateSession, and S3 Access Grants can implement service granters. Existing fixed-config providers remain compatible and may later delegate internally to this capability. AssumeRoleWithWebIdentity remains a provider because its source is an external web identity rather than an AWS service credential.
- Presigned HTTP requests remain `SignRequest`; they return request artifacts rather than independently reusable credentials.
## Compatibility
This is an additive core API. Existing `ProvideCredential`, `SignRequest`, `Signer`, service credentials, default chains, and configured temporary credential providers remain source-compatible. Initial service implementations can land independently after the core contract is accepted.
Related: #748, #749, #750, #751.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@opendal.apache.org.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [I] Add GrantCredential and Granter as a core credential granting capability [opendal-reqsign]
Posted by "Xuanwo (via GitHub)" <gi...@apache.org>.
Xuanwo closed issue #801: Add GrantCredential and Granter as a core credential granting capability
URL: https://github.com/apache/opendal-reqsign/issues/801
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@opendal.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org