cloud-sdk 0.41.0

no_std-first provider-neutral cloud SDK foundations.
Documentation
use super::{
    AuthenticationScope, AuthenticationScopePolicy, CredentialGeneration,
    CredentialGenerationError, ScopeField, ScopeRequirement, ScopeValue, ScopeValueError,
    ScopeViolation,
};
use crate::transport::{EndpointIdentity, EndpointScheme};
use crate::{ProviderId, ServiceId};

struct FormatBuffer {
    bytes: [u8; 128],
    len: usize,
}

impl FormatBuffer {
    const fn new() -> Self {
        Self {
            bytes: [0; 128],
            len: 0,
        }
    }

    fn as_str(&self) -> &str {
        let Some(bytes) = self.bytes.get(..self.len) else {
            return "";
        };
        core::str::from_utf8(bytes).unwrap_or("")
    }
}

impl core::fmt::Write for FormatBuffer {
    fn write_str(&mut self, value: &str) -> core::fmt::Result {
        let Some(end) = self.len.checked_add(value.len()) else {
            return Err(core::fmt::Error);
        };
        let Some(output) = self.bytes.get_mut(self.len..end) else {
            return Err(core::fmt::Error);
        };
        output.copy_from_slice(value.as_bytes());
        self.len = end;
        Ok(())
    }
}

fn provider() -> ProviderId {
    ProviderId::new("example").unwrap_or_else(|_| unreachable!())
}

fn other_provider() -> ProviderId {
    ProviderId::new("other").unwrap_or_else(|_| unreachable!())
}

fn service() -> ServiceId {
    ServiceId::new("compute").unwrap_or_else(|_| unreachable!())
}

fn endpoint() -> EndpointIdentity<'static> {
    EndpointIdentity::new(EndpointScheme::Https, "api.example.test", 443, "/v1")
        .unwrap_or_else(|_| unreachable!())
}

fn other_endpoint() -> EndpointIdentity<'static> {
    EndpointIdentity::new(EndpointScheme::Https, "other.example.test", 443, "/v1")
        .unwrap_or_else(|_| unreachable!())
}

fn value(text: &'static str) -> ScopeValue<'static> {
    ScopeValue::new(text).unwrap_or_else(|_| unreachable!())
}

fn all_forbidden() -> AuthenticationScopePolicy<'static> {
    AuthenticationScopePolicy::new(
        ScopeRequirement::Forbidden,
        ScopeRequirement::Forbidden,
        ScopeRequirement::Forbidden,
        ScopeRequirement::Forbidden,
        ScopeRequirement::Forbidden,
        ScopeRequirement::Forbidden,
    )
}

#[test]
fn scope_values_are_bounded_validated_and_redacted() {
    assert_eq!(ScopeValue::new(""), Err(ScopeValueError::Empty));
    assert_eq!(
        ScopeValue::new("contains space"),
        Err(ScopeValueError::InvalidByte)
    );
    assert_eq!(
        ScopeValue::new("contains\\backslash"),
        Err(ScopeValueError::InvalidByte)
    );
    let too_long = "a".repeat(super::MAX_SCOPE_VALUE_BYTES.saturating_add(1));
    assert_eq!(ScopeValue::new(&too_long), Err(ScopeValueError::TooLong));
    let accepted = ScopeValue::new("urn:example:tenant/a?b=c");
    assert!(accepted.is_ok());
    if let Ok(accepted) = accepted {
        let mut debug = FormatBuffer::new();
        assert!(core::fmt::write(&mut debug, format_args!("{accepted:?}")).is_ok());
        let debug = debug.as_str();
        assert!(debug.contains("[redacted]"));
        assert!(!debug.contains("tenant"));
    }
}

#[test]
fn unscoped_credentials_cannot_bypass_required_bindings() {
    let policy = AuthenticationScopePolicy::new(
        ScopeRequirement::Required(provider()),
        ScopeRequirement::Required(service()),
        ScopeRequirement::Required(endpoint()),
        ScopeRequirement::Required(value("audience")),
        ScopeRequirement::Required(value("account")),
        ScopeRequirement::Required(value("tenant")),
    );
    for field in [
        ScopeField::Provider,
        ScopeField::Service,
        ScopeField::Endpoint,
        ScopeField::Audience,
        ScopeField::Account,
        ScopeField::Tenant,
    ] {
        let result = match field {
            ScopeField::Provider => policy.validate(AuthenticationScope::unscoped()),
            ScopeField::Service => {
                policy.validate(AuthenticationScope::unscoped().with_provider(provider()))
            }
            ScopeField::Endpoint => policy.validate(
                AuthenticationScope::unscoped()
                    .with_provider(provider())
                    .with_service(service()),
            ),
            ScopeField::Audience => policy.validate(
                AuthenticationScope::unscoped()
                    .with_provider(provider())
                    .with_service(service())
                    .with_endpoint(endpoint()),
            ),
            ScopeField::Account => policy.validate(
                AuthenticationScope::unscoped()
                    .with_provider(provider())
                    .with_service(service())
                    .with_endpoint(endpoint())
                    .with_audience(value("audience")),
            ),
            ScopeField::Tenant => policy.validate(
                AuthenticationScope::unscoped()
                    .with_provider(provider())
                    .with_service(service())
                    .with_endpoint(endpoint())
                    .with_audience(value("audience"))
                    .with_account(value("account")),
            ),
        };
        assert!(result.is_err());
        let Err(error) = result else { return };
        assert_eq!(error.field(), field);
        assert_eq!(error.violation(), ScopeViolation::MissingRequired);
    }
}

#[test]
fn every_field_enforces_forbidden_and_mismatch_rules() {
    let supplied = [
        AuthenticationScope::unscoped().with_provider(provider()),
        AuthenticationScope::unscoped().with_service(service()),
        AuthenticationScope::unscoped().with_endpoint(endpoint()),
        AuthenticationScope::unscoped().with_audience(value("audience")),
        AuthenticationScope::unscoped().with_account(value("account")),
        AuthenticationScope::unscoped().with_tenant(value("tenant")),
    ];
    for (field, scope) in [
        ScopeField::Provider,
        ScopeField::Service,
        ScopeField::Endpoint,
        ScopeField::Audience,
        ScopeField::Account,
        ScopeField::Tenant,
    ]
    .into_iter()
    .zip(supplied)
    {
        let result = all_forbidden().validate(scope);
        assert!(result.is_err());
        let Err(error) = result else { return };
        assert_eq!(error.field(), field);
        assert_eq!(error.violation(), ScopeViolation::SuppliedForbidden);
    }

    let mismatch_cases = [
        (
            AuthenticationScopePolicy::new(
                ScopeRequirement::Required(other_provider()),
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
            ),
            AuthenticationScope::unscoped().with_provider(provider()),
            ScopeField::Provider,
        ),
        (
            AuthenticationScopePolicy::new(
                ScopeRequirement::Forbidden,
                ScopeRequirement::Required(ServiceId::new("storage").unwrap_or(service())),
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
            ),
            AuthenticationScope::unscoped().with_service(service()),
            ScopeField::Service,
        ),
        (
            AuthenticationScopePolicy::new(
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
                ScopeRequirement::Required(other_endpoint()),
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
            ),
            AuthenticationScope::unscoped().with_endpoint(endpoint()),
            ScopeField::Endpoint,
        ),
    ];
    for (policy, scope, field) in mismatch_cases {
        let result = policy.validate(scope);
        assert!(result.is_err());
        let Err(error) = result else { return };
        assert_eq!(error.field(), field);
        assert_eq!(error.violation(), ScopeViolation::Mismatch);
    }

    for (field, policy, scope) in [
        (
            ScopeField::Audience,
            AuthenticationScopePolicy::new(
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
                ScopeRequirement::Required(value("expected")),
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
            ),
            AuthenticationScope::unscoped().with_audience(value("actual")),
        ),
        (
            ScopeField::Account,
            AuthenticationScopePolicy::new(
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
                ScopeRequirement::Required(value("expected")),
                ScopeRequirement::Forbidden,
            ),
            AuthenticationScope::unscoped().with_account(value("actual")),
        ),
        (
            ScopeField::Tenant,
            AuthenticationScopePolicy::new(
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
                ScopeRequirement::Forbidden,
                ScopeRequirement::Required(value("expected")),
            ),
            AuthenticationScope::unscoped().with_tenant(value("actual")),
        ),
    ] {
        let result = policy.validate(scope);
        assert!(result.is_err());
        let Err(error) = result else { return };
        assert_eq!(error.field(), field);
        assert_eq!(error.violation(), ScopeViolation::Mismatch);
    }
}

#[test]
fn optional_fields_accept_omission_and_exact_presence() {
    let policy = AuthenticationScopePolicy::new(
        ScopeRequirement::Optional(provider()),
        ScopeRequirement::Optional(service()),
        ScopeRequirement::Optional(endpoint()),
        ScopeRequirement::Optional(value("audience")),
        ScopeRequirement::Optional(value("account")),
        ScopeRequirement::Optional(value("tenant")),
    );
    assert!(policy.validate(AuthenticationScope::unscoped()).is_ok());
    let complete = AuthenticationScope::unscoped()
        .with_provider(provider())
        .with_service(service())
        .with_endpoint(endpoint())
        .with_audience(value("audience"))
        .with_account(value("account"))
        .with_tenant(value("tenant"));
    assert!(policy.validate(complete).is_ok());
}

#[test]
fn endpoint_policy_rejects_plain_http_before_scope_comparison() {
    let http = EndpointIdentity::new(EndpointScheme::Http, "127.0.0.1", 80, "/")
        .unwrap_or_else(|_| unreachable!());
    let policy = AuthenticationScopePolicy::new(
        ScopeRequirement::Forbidden,
        ScopeRequirement::Forbidden,
        ScopeRequirement::Required(http),
        ScopeRequirement::Forbidden,
        ScopeRequirement::Forbidden,
        ScopeRequirement::Forbidden,
    );
    let result = policy.validate(AuthenticationScope::unscoped().with_endpoint(http));
    assert!(result.is_err());
    let Err(error) = result else { return };
    assert_eq!(error.field(), ScopeField::Endpoint);
    assert_eq!(error.violation(), ScopeViolation::InsecureEndpoint);
}

#[test]
fn credential_generations_never_wrap_and_create_stable_handoffs() {
    let initial = CredentialGeneration::INITIAL;
    assert_eq!(initial.get(), 1);
    let handoff = initial.refresh_handoff();
    assert_eq!(handoff.expected_generation(), initial);
    assert_eq!(
        CredentialGeneration::from_raw_for_test(u64::MAX).checked_next(),
        Err(CredentialGenerationError::Exhausted)
    );
}