use std::collections::BTreeMap;
use std::sync::Arc;
use parking_lot::RwLock;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use fakecloud_core::multi_account::{AccountState, MultiAccountState};
pub const SSOADMIN_SNAPSHOT_SCHEMA_VERSION: u32 = 1;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StoredRegion {
pub region_name: String,
pub status: String,
pub added_date: i64,
pub is_primary: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StoredInstance {
pub arn: String,
pub ssoins: String,
pub identity_store_id: String,
pub owner_account_id: String,
#[serde(default)]
pub name: Option<String>,
pub status: String,
pub created_date: i64,
#[serde(default)]
pub regions: Vec<StoredRegion>,
#[serde(default)]
pub primary_region: Option<String>,
#[serde(default)]
pub attr_config: Option<Value>,
#[serde(default)]
pub attr_config_status: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StoredManagedPolicy {
pub name: String,
pub arn: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StoredPermissionSet {
pub arn: String,
pub instance_arn: String,
pub name: String,
#[serde(default)]
pub description: Option<String>,
#[serde(default)]
pub session_duration: Option<String>,
#[serde(default)]
pub relay_state: Option<String>,
pub created_date: i64,
#[serde(default)]
pub inline_policy: Option<String>,
#[serde(default)]
pub permissions_boundary: Option<Value>,
#[serde(default)]
pub managed_policies: Vec<StoredManagedPolicy>,
#[serde(default)]
pub customer_managed: Vec<Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StoredAssignment {
pub account_id: String,
pub permission_set_arn: String,
pub principal_type: String,
pub principal_id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StoredOpStatus {
pub request_id: String,
pub status: String,
pub target_id: String,
pub target_type: String,
pub permission_set_arn: String,
pub principal_type: String,
pub principal_id: String,
pub created_date: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StoredProvisioningStatus {
pub request_id: String,
pub status: String,
#[serde(default)]
pub account_id: Option<String>,
pub permission_set_arn: String,
pub created_date: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StoredApplication {
pub arn: String,
pub provider_arn: String,
#[serde(default)]
pub name: Option<String>,
pub account: String,
pub instance_arn: String,
pub identity_store_arn: String,
#[serde(default)]
pub status: Option<String>,
#[serde(default)]
pub portal_options: Option<Value>,
#[serde(default)]
pub description: Option<String>,
pub created_date: i64,
#[serde(default)]
pub created_from: Option<String>,
#[serde(default)]
pub assignments: Vec<(String, String)>,
#[serde(default)]
pub assignment_required: Option<bool>,
#[serde(default)]
pub access_scopes: BTreeMap<String, Value>,
#[serde(default)]
pub auth_methods: BTreeMap<String, Value>,
#[serde(default)]
pub grants: BTreeMap<String, Value>,
#[serde(default)]
pub session_status: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StoredTrustedTokenIssuer {
pub arn: String,
pub instance_arn: String,
#[serde(default)]
pub name: Option<String>,
pub issuer_type: String,
#[serde(default)]
pub config: Option<Value>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct SsoAdminData {
#[serde(default)]
pub instances: BTreeMap<String, StoredInstance>,
#[serde(default)]
pub permission_sets: BTreeMap<String, StoredPermissionSet>,
#[serde(default)]
pub assignments: Vec<StoredAssignment>,
#[serde(default)]
pub aa_create_status: BTreeMap<String, StoredOpStatus>,
#[serde(default)]
pub aa_delete_status: BTreeMap<String, StoredOpStatus>,
#[serde(default)]
pub ps_provisioning: BTreeMap<String, StoredProvisioningStatus>,
#[serde(default)]
pub applications: BTreeMap<String, StoredApplication>,
#[serde(default)]
pub trusted_token_issuers: BTreeMap<String, StoredTrustedTokenIssuer>,
#[serde(default)]
pub tags: BTreeMap<String, BTreeMap<String, String>>,
}
impl AccountState for SsoAdminData {
fn new_for_account(_account_id: &str, _region: &str, _endpoint: &str) -> Self {
Self::default()
}
}
pub type SharedSsoAdminState = Arc<RwLock<MultiAccountState<SsoAdminData>>>;
#[derive(Debug, Serialize, Deserialize)]
pub struct SsoAdminSnapshot {
pub schema_version: u32,
pub accounts: MultiAccountState<SsoAdminData>,
}
pub fn ensure_default_instance(state: &SharedSsoAdminState, account_id: &str, region: &str) {
let mut guard = state.write();
let acct = guard.get_or_create(account_id);
if !acct.instances.is_empty() {
return;
}
let pad = format!("{account_id:0<16}");
let ssoins = format!("ssoins-{}", &pad[..16]);
let arn = format!("arn:aws:sso:::instance/{ssoins}");
let identity_store_id = format!("d-{}", &pad[..10]);
let ts = chrono::Utc::now().timestamp();
acct.instances.insert(
arn.clone(),
StoredInstance {
arn,
ssoins,
identity_store_id,
owner_account_id: account_id.to_string(),
name: None,
status: "ACTIVE".into(),
created_date: ts,
regions: vec![StoredRegion {
region_name: region.to_string(),
status: "ACTIVE".into(),
added_date: ts,
is_primary: true,
}],
primary_region: Some(region.to_string()),
attr_config: None,
attr_config_status: None,
},
);
}