Skip to content

Custom Credential Registry ​

The CredentialRegistry trait defines how the proxy looks up credentials and roles for authentication. Implement it to plug in your own credential backend.

The Trait ​

rust
use multistore::registry::CredentialRegistry;
use multistore::error::ProxyError;
use multistore::types::*;

pub trait CredentialRegistry: Clone + MaybeSend + MaybeSync + 'static {
    fn get_credential(&self, access_key_id: &str)
        -> impl Future<Output = Result<Option<StoredCredential>, ProxyError>> + MaybeSend;
    fn get_role(&self, role_id: &str)
        -> impl Future<Output = Result<Option<RoleConfig>, ProxyError>> + MaybeSend;
}

Example: Redis Provider ​

rust
use multistore::registry::CredentialRegistry;
use multistore::error::ProxyError;
use multistore::types::*;

#[derive(Clone)]
struct RedisCredentialRegistry {
    client: redis::Client,
}

impl CredentialRegistry for RedisCredentialRegistry {
    async fn get_credential(&self, access_key_id: &str)
        -> Result<Option<StoredCredential>, ProxyError>
    {
        let mut conn = self.client.get_async_connection().await
            .map_err(|e| ProxyError::Internal(e.to_string()))?;

        let json: Option<String> = redis::cmd("GET")
            .arg(format!("credential:{}", access_key_id))
            .query_async(&mut conn)
            .await
            .map_err(|e| ProxyError::Internal(e.to_string()))?;

        match json {
            Some(j) => Ok(Some(serde_json::from_str(&j)
                .map_err(|e| ProxyError::ConfigError(e.to_string()))?)),
            None => Ok(None),
        }
    }

    async fn get_role(&self, role_id: &str) -> Result<Option<RoleConfig>, ProxyError> {
        // Similar Redis GET with key "role:{role_id}"
        todo!()
    }
}

Using with the Gateway ​

Pass your credential registry directly to ProxyGateway. The gateway handles S3 request parsing and identity resolution internally:

rust
let bucket_registry = MyBucketRegistry::new(/* ... */);
let cred_registry = RedisCredentialRegistry::new(redis_client);

let gateway = ProxyGateway::new(
    backend,
    bucket_registry,
    cred_registry,
    virtual_host_domain,
);