Skip to main content

fakecloud_ram/
state.rs

1//! Account-partitioned, serializable state for AWS Resource Access Manager.
2//!
3//! Models the RAM control plane: resource shares (with their resource and
4//! principal associations and attached permissions), resource-share
5//! invitations, customer-managed permissions (with versions), and tags. AWS
6//! seeds a catalogue of managed default permissions and supported resource
7//! types; those are constant data served from [`service`](crate::service)
8//! rather than stored per-account.
9
10use std::collections::BTreeMap;
11use std::sync::Arc;
12
13use chrono::{DateTime, Utc};
14use parking_lot::RwLock;
15use serde::{Deserialize, Serialize};
16
17use fakecloud_core::multi_account::{AccountState, MultiAccountState};
18
19pub const RAM_SNAPSHOT_SCHEMA_VERSION: u32 = 1;
20
21pub type TagMap = BTreeMap<String, String>;
22
23/// A resource-share / principal association within a share.
24#[derive(Debug, Clone, Serialize, Deserialize)]
25pub struct AssociationRecord {
26    /// The associated entity: a resource ARN (RESOURCE) or a principal id
27    /// (PRINCIPAL) or a source account id (SOURCE).
28    pub associated_entity: String,
29    /// One of `RESOURCE`, `PRINCIPAL`.
30    pub association_type: String,
31    /// Progresses synthetically to `ASSOCIATED` on create.
32    pub status: String,
33    pub status_message: Option<String>,
34    pub creation_time: DateTime<Utc>,
35    pub last_updated_time: DateTime<Utc>,
36    /// True when the associated entity is an account outside the caller's org.
37    pub external: bool,
38}
39
40/// A resource share owned by (or shared with) the account.
41#[derive(Debug, Clone, Serialize, Deserialize)]
42pub struct ResourceShareRecord {
43    pub arn: String,
44    pub name: String,
45    pub owning_account_id: String,
46    pub allow_external_principals: bool,
47    pub status: String,
48    pub status_message: Option<String>,
49    pub creation_time: DateTime<Utc>,
50    pub last_updated_time: DateTime<Utc>,
51    pub feature_set: String,
52    pub tags: TagMap,
53    /// `retainSharingOnAccountLeaveOrganization` from a `ResourceShareConfiguration`.
54    pub retain_sharing: Option<bool>,
55    pub resource_associations: Vec<AssociationRecord>,
56    pub principal_associations: Vec<AssociationRecord>,
57    pub permission_arns: Vec<String>,
58}
59
60/// A single version of a customer-managed permission.
61#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct PermissionVersionRecord {
63    pub version: u32,
64    pub policy_template: String,
65    pub is_default: bool,
66    pub creation_time: DateTime<Utc>,
67    pub last_updated_time: DateTime<Utc>,
68}
69
70/// A customer-managed permission with its versions.
71#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct PermissionRecord {
73    pub arn: String,
74    pub name: String,
75    pub resource_type: String,
76    pub status: String,
77    pub feature_set: String,
78    pub creation_time: DateTime<Utc>,
79    pub last_updated_time: DateTime<Utc>,
80    pub default_version: u32,
81    pub versions: Vec<PermissionVersionRecord>,
82    pub tags: TagMap,
83}
84
85/// A resource-share invitation delivered to an external account.
86#[derive(Debug, Clone, Serialize, Deserialize)]
87pub struct InvitationRecord {
88    pub arn: String,
89    pub resource_share_arn: String,
90    pub resource_share_name: String,
91    pub sender_account_id: String,
92    pub receiver_account_id: String,
93    pub invitation_timestamp: DateTime<Utc>,
94    pub status: String,
95}
96
97/// The account-scoped RAM state for one AWS account.
98#[derive(Debug, Clone, Default, Serialize, Deserialize)]
99pub struct RamState {
100    #[serde(default)]
101    pub resource_shares: BTreeMap<String, ResourceShareRecord>,
102    #[serde(default)]
103    pub permissions: BTreeMap<String, PermissionRecord>,
104    #[serde(default)]
105    pub invitations: BTreeMap<String, InvitationRecord>,
106    /// Replace-permission-associations work items, keyed by work id, stored as
107    /// the JSON object echoed back by `ListReplacePermissionAssociationsWork`.
108    #[serde(default)]
109    pub replace_works: BTreeMap<String, serde_json::Value>,
110    /// Tags keyed by resource ARN (resource-share or permission ARN).
111    #[serde(default)]
112    pub tags: BTreeMap<String, TagMap>,
113}
114
115impl AccountState for RamState {
116    fn new_for_account(_account_id: &str, _region: &str, _endpoint: &str) -> Self {
117        Self::default()
118    }
119}
120
121pub type SharedRamState = Arc<RwLock<MultiAccountState<RamState>>>;
122
123#[derive(Debug, Serialize, Deserialize)]
124pub struct RamSnapshot {
125    pub schema_version: u32,
126    pub accounts: MultiAccountState<RamState>,
127}
128
129// ---------------------------------------------------------------------------
130// ARN builders
131// ---------------------------------------------------------------------------
132
133pub fn resource_share_arn(region: &str, account_id: &str, id: &str) -> String {
134    format!("arn:aws:ram:{region}:{account_id}:resource-share/{id}")
135}
136
137pub fn invitation_arn(region: &str, account_id: &str, id: &str) -> String {
138    format!("arn:aws:ram:{region}:{account_id}:resource-share-invitation/{id}")
139}
140
141/// ARN for a customer-managed permission.
142pub fn permission_arn(region: &str, account_id: &str, name: &str) -> String {
143    format!("arn:aws:ram:{region}:{account_id}:permission/{name}")
144}
145
146/// ARN for an AWS-managed default permission (partition-scoped, no region/account).
147pub fn managed_permission_arn(name: &str) -> String {
148    format!("arn:aws:ram::aws:permission/{name}")
149}