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_id: Option<String>,
44 pub resource_name: Option<String>,
45 pub service_account_name: Option<String>,
46 pub principal_id: Option<String>,
47 pub external_id: Option<String>,
48 pub managing_role_arn: Option<String>,
49 pub managing_account_id: Option<String>,
50}
51
52impl PermissionContext {
53 pub fn new() -> Self {
55 Self {
56 aws_account_id: None,
57 aws_region: None,
58 project_name: None,
59 project_number: None,
60 region: None,
61 subscription_id: None,
62 resource_group: None,
63 storage_account_name: None,
64 managing_project_id: None,
65 managing_subscription_id: None,
66 managing_resource_group: None,
67 stack_prefix: None,
68 stack_name: None,
69 deployment_name: None,
70 resource_id: None,
71 resource_name: None,
72 service_account_name: None,
73 principal_id: None,
74 external_id: None,
75 managing_role_arn: None,
76 managing_account_id: None,
77 }
78 }
79
80 pub fn with_aws_account_id(mut self, aws_account_id: impl Into<String>) -> Self {
82 self.aws_account_id = Some(aws_account_id.into());
83 self
84 }
85
86 pub fn with_aws_region(mut self, aws_region: impl Into<String>) -> Self {
88 self.aws_region = Some(aws_region.into());
89 self
90 }
91
92 pub fn with_project_name(mut self, project_name: impl Into<String>) -> Self {
94 self.project_name = Some(project_name.into());
95 self
96 }
97
98 pub fn with_project_number(mut self, project_number: impl Into<String>) -> Self {
100 self.project_number = Some(project_number.into());
101 self
102 }
103
104 pub fn with_region(mut self, region: impl Into<String>) -> Self {
106 self.region = Some(region.into());
107 self
108 }
109
110 pub fn with_subscription_id(mut self, subscription_id: impl Into<String>) -> Self {
112 self.subscription_id = Some(subscription_id.into());
113 self
114 }
115
116 pub fn with_resource_group(mut self, resource_group: impl Into<String>) -> Self {
118 self.resource_group = Some(resource_group.into());
119 self
120 }
121
122 pub fn with_storage_account_name(mut self, storage_account_name: impl Into<String>) -> Self {
124 self.storage_account_name = Some(storage_account_name.into());
125 self
126 }
127
128 pub fn with_managing_project_id(mut self, id: impl Into<String>) -> Self {
130 self.managing_project_id = Some(id.into());
131 self
132 }
133
134 pub fn with_managing_subscription_id(mut self, id: impl Into<String>) -> Self {
136 self.managing_subscription_id = Some(id.into());
137 self
138 }
139
140 pub fn with_managing_resource_group(mut self, rg: impl Into<String>) -> Self {
142 self.managing_resource_group = Some(rg.into());
143 self
144 }
145
146 pub fn with_stack_prefix(mut self, stack_prefix: impl Into<String>) -> Self {
148 self.stack_prefix = Some(stack_prefix.into());
149 self
150 }
151
152 pub fn with_stack_name(mut self, stack_name: impl Into<String>) -> Self {
154 self.stack_name = Some(stack_name.into());
155 self
156 }
157
158 pub fn with_deployment_name(mut self, deployment_name: impl Into<String>) -> Self {
160 self.deployment_name = Some(deployment_name.into());
161 self
162 }
163
164 pub fn with_resource_id(mut self, resource_id: impl Into<String>) -> Self {
166 self.resource_id = Some(resource_id.into());
167 self
168 }
169
170 pub fn with_resource_name(mut self, resource_name: impl Into<String>) -> Self {
172 self.resource_name = Some(resource_name.into());
173 self
174 }
175
176 pub fn with_service_account_name(mut self, service_account_name: impl Into<String>) -> Self {
178 self.service_account_name = Some(service_account_name.into());
179 self
180 }
181
182 pub fn with_principal_id(mut self, principal_id: impl Into<String>) -> Self {
184 self.principal_id = Some(principal_id.into());
185 self
186 }
187
188 pub fn with_external_id(mut self, external_id: impl Into<String>) -> Self {
190 self.external_id = Some(external_id.into());
191 self
192 }
193
194 pub fn with_managing_role_arn(mut self, managing_role_arn: impl Into<String>) -> Self {
196 self.managing_role_arn = Some(managing_role_arn.into());
197 self
198 }
199
200 pub fn with_managing_account_id(mut self, managing_account_id: impl Into<String>) -> Self {
202 self.managing_account_id = Some(managing_account_id.into());
203 self
204 }
205
206 pub fn extract_account_id_from_role_arn(role_arn: &str) -> Option<String> {
209 let parts: Vec<&str> = role_arn.split(':').collect();
210 if parts.len() >= 5 && parts[0] == "arn" && parts[2] == "iam" {
211 Some(parts[4].to_string())
212 } else {
213 None
214 }
215 }
216
217 pub fn get_variable(&self, key: &str) -> Option<&str> {
219 match key {
220 "awsAccountId" => self.aws_account_id.as_deref(),
221 "awsRegion" => self.aws_region.as_deref(),
222 "projectName" => self.project_name.as_deref(),
223 "projectNumber" => self.project_number.as_deref(),
224 "region" => self.region.as_deref(),
225 "subscriptionId" => self.subscription_id.as_deref(),
226 "resourceGroup" => self.resource_group.as_deref(),
227 "storageAccountName" => self.storage_account_name.as_deref(),
228 "stackPrefix" => self.stack_prefix.as_deref(),
229 "stackName" => self.stack_name.as_deref(),
230 "deploymentName" => self.deployment_name.as_deref(),
231 "resourceId" => self.resource_id.as_deref(),
232 "resourceName" => self.resource_name.as_deref(),
233 "serviceAccountName" => self.service_account_name.as_deref(),
234 "principalId" => self.principal_id.as_deref(),
235 "externalId" => self.external_id.as_deref(),
236 "managingRoleArn" => self.managing_role_arn.as_deref(),
237 "managingAccountId" => self.managing_account_id.as_deref(),
238 "managingProjectId" => self.managing_project_id.as_deref(),
239 "managingSubscriptionId" => self.managing_subscription_id.as_deref(),
240 "managingResourceGroup" => self.managing_resource_group.as_deref(),
241 "stackTag" => Some(ALIEN_STACK_TAG_KEY),
242 "resourceTag" => Some(ALIEN_RESOURCE_TAG_KEY),
243 "managedByTag" => Some(ALIEN_MANAGED_BY_TAG_KEY),
244 _ => None,
245 }
246 }
247}
248
249impl Default for PermissionContext {
250 fn default() -> Self {
251 Self::new()
252 }
253}
254
255#[derive(Debug, Clone, Copy, PartialEq, Eq)]
257pub enum BindingTarget {
258 Stack,
260 Resource,
262}
263
264impl std::fmt::Display for BindingTarget {
265 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
266 match self {
267 BindingTarget::Stack => write!(f, "stack"),
268 BindingTarget::Resource => write!(f, "resource"),
269 }
270 }
271}