1pub mod error;
2pub mod generators;
3pub mod initial_setup;
4pub mod registry;
5pub mod variables;
6
7use alien_core::{ALIEN_MANAGED_BY_TAG_KEY, ALIEN_RESOURCE_TAG_KEY, ALIEN_STACK_TAG_KEY};
8
9pub use error::*;
10pub use registry::{get_permission_set, has_permission_set, list_permission_set_ids};
11pub use variables::VariableInterpolator;
12
13#[derive(Debug, Clone)]
17pub struct PermissionContext {
18 pub aws_account_id: Option<String>,
20 pub aws_region: Option<String>,
21
22 pub project_name: Option<String>,
24 pub project_number: Option<String>,
25 pub region: Option<String>,
26
27 pub subscription_id: Option<String>,
29 pub resource_group: Option<String>,
30 pub storage_account_name: Option<String>,
31
32 pub managing_project_id: Option<String>,
34
35 pub managing_subscription_id: Option<String>,
37 pub managing_resource_group: Option<String>,
38
39 pub stack_prefix: Option<String>,
41 pub stack_name: Option<String>,
42 pub deployment_name: Option<String>,
43 pub resource_name: Option<String>,
44 pub service_account_name: Option<String>,
45 pub principal_id: Option<String>,
46 pub external_id: Option<String>,
47 pub managing_role_arn: Option<String>,
48 pub managing_account_id: Option<String>,
49}
50
51impl PermissionContext {
52 pub fn new() -> Self {
54 Self {
55 aws_account_id: None,
56 aws_region: None,
57 project_name: None,
58 project_number: None,
59 region: None,
60 subscription_id: None,
61 resource_group: None,
62 storage_account_name: None,
63 managing_project_id: None,
64 managing_subscription_id: None,
65 managing_resource_group: None,
66 stack_prefix: None,
67 stack_name: None,
68 deployment_name: None,
69 resource_name: None,
70 service_account_name: None,
71 principal_id: None,
72 external_id: None,
73 managing_role_arn: None,
74 managing_account_id: None,
75 }
76 }
77
78 pub fn with_aws_account_id(mut self, aws_account_id: impl Into<String>) -> Self {
80 self.aws_account_id = Some(aws_account_id.into());
81 self
82 }
83
84 pub fn with_aws_region(mut self, aws_region: impl Into<String>) -> Self {
86 self.aws_region = Some(aws_region.into());
87 self
88 }
89
90 pub fn with_project_name(mut self, project_name: impl Into<String>) -> Self {
92 self.project_name = Some(project_name.into());
93 self
94 }
95
96 pub fn with_project_number(mut self, project_number: impl Into<String>) -> Self {
98 self.project_number = Some(project_number.into());
99 self
100 }
101
102 pub fn with_region(mut self, region: impl Into<String>) -> Self {
104 self.region = Some(region.into());
105 self
106 }
107
108 pub fn with_subscription_id(mut self, subscription_id: impl Into<String>) -> Self {
110 self.subscription_id = Some(subscription_id.into());
111 self
112 }
113
114 pub fn with_resource_group(mut self, resource_group: impl Into<String>) -> Self {
116 self.resource_group = Some(resource_group.into());
117 self
118 }
119
120 pub fn with_storage_account_name(mut self, storage_account_name: impl Into<String>) -> Self {
122 self.storage_account_name = Some(storage_account_name.into());
123 self
124 }
125
126 pub fn with_managing_project_id(mut self, id: impl Into<String>) -> Self {
128 self.managing_project_id = Some(id.into());
129 self
130 }
131
132 pub fn with_managing_subscription_id(mut self, id: impl Into<String>) -> Self {
134 self.managing_subscription_id = Some(id.into());
135 self
136 }
137
138 pub fn with_managing_resource_group(mut self, rg: impl Into<String>) -> Self {
140 self.managing_resource_group = Some(rg.into());
141 self
142 }
143
144 pub fn with_stack_prefix(mut self, stack_prefix: impl Into<String>) -> Self {
146 self.stack_prefix = Some(stack_prefix.into());
147 self
148 }
149
150 pub fn with_stack_name(mut self, stack_name: impl Into<String>) -> Self {
152 self.stack_name = Some(stack_name.into());
153 self
154 }
155
156 pub fn with_deployment_name(mut self, deployment_name: impl Into<String>) -> Self {
158 self.deployment_name = Some(deployment_name.into());
159 self
160 }
161
162 pub fn with_resource_name(mut self, resource_name: impl Into<String>) -> Self {
164 self.resource_name = Some(resource_name.into());
165 self
166 }
167
168 pub fn with_service_account_name(mut self, service_account_name: impl Into<String>) -> Self {
170 self.service_account_name = Some(service_account_name.into());
171 self
172 }
173
174 pub fn with_principal_id(mut self, principal_id: impl Into<String>) -> Self {
176 self.principal_id = Some(principal_id.into());
177 self
178 }
179
180 pub fn with_external_id(mut self, external_id: impl Into<String>) -> Self {
182 self.external_id = Some(external_id.into());
183 self
184 }
185
186 pub fn with_managing_role_arn(mut self, managing_role_arn: impl Into<String>) -> Self {
188 self.managing_role_arn = Some(managing_role_arn.into());
189 self
190 }
191
192 pub fn with_managing_account_id(mut self, managing_account_id: impl Into<String>) -> Self {
194 self.managing_account_id = Some(managing_account_id.into());
195 self
196 }
197
198 pub fn extract_account_id_from_role_arn(role_arn: &str) -> Option<String> {
201 let parts: Vec<&str> = role_arn.split(':').collect();
202 if parts.len() >= 5 && parts[0] == "arn" && parts[2] == "iam" {
203 Some(parts[4].to_string())
204 } else {
205 None
206 }
207 }
208
209 pub fn get_variable(&self, key: &str) -> Option<&str> {
211 match key {
212 "awsAccountId" => self.aws_account_id.as_deref(),
213 "awsRegion" => self.aws_region.as_deref(),
214 "projectName" => self.project_name.as_deref(),
215 "projectNumber" => self.project_number.as_deref(),
216 "region" => self.region.as_deref(),
217 "subscriptionId" => self.subscription_id.as_deref(),
218 "resourceGroup" => self.resource_group.as_deref(),
219 "storageAccountName" => self.storage_account_name.as_deref(),
220 "stackPrefix" => self.stack_prefix.as_deref(),
221 "stackName" => self.stack_name.as_deref(),
222 "deploymentName" => self.deployment_name.as_deref(),
223 "resourceName" => self.resource_name.as_deref(),
224 "serviceAccountName" => self.service_account_name.as_deref(),
225 "principalId" => self.principal_id.as_deref(),
226 "externalId" => self.external_id.as_deref(),
227 "managingRoleArn" => self.managing_role_arn.as_deref(),
228 "managingAccountId" => self.managing_account_id.as_deref(),
229 "managingProjectId" => self.managing_project_id.as_deref(),
230 "managingSubscriptionId" => self.managing_subscription_id.as_deref(),
231 "managingResourceGroup" => self.managing_resource_group.as_deref(),
232 "stackTag" => Some(ALIEN_STACK_TAG_KEY),
233 "resourceTag" => Some(ALIEN_RESOURCE_TAG_KEY),
234 "managedByTag" => Some(ALIEN_MANAGED_BY_TAG_KEY),
235 _ => None,
236 }
237 }
238}
239
240impl Default for PermissionContext {
241 fn default() -> Self {
242 Self::new()
243 }
244}
245
246#[derive(Debug, Clone, Copy, PartialEq, Eq)]
248pub enum BindingTarget {
249 Stack,
251 Resource,
253}
254
255impl std::fmt::Display for BindingTarget {
256 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
257 match self {
258 BindingTarget::Stack => write!(f, "stack"),
259 BindingTarget::Resource => write!(f, "resource"),
260 }
261 }
262}