qontract-reconcile 0.10.1rc675__py3-none-any.whl → 0.10.1rc677__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {qontract_reconcile-0.10.1rc675.dist-info → qontract_reconcile-0.10.1rc677.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc675.dist-info → qontract_reconcile-0.10.1rc677.dist-info}/RECORD +8 -8
- reconcile/aws_saml_roles/integration.py +140 -38
- reconcile/gql_definitions/aws_saml_roles/{aws_groups.py → roles.py} +34 -33
- reconcile/utils/terrascript_aws_client.py +16 -10
- {qontract_reconcile-0.10.1rc675.dist-info → qontract_reconcile-0.10.1rc677.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc675.dist-info → qontract_reconcile-0.10.1rc677.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc675.dist-info → qontract_reconcile-0.10.1rc677.dist-info}/top_level.txt +0 -0
{qontract_reconcile-0.10.1rc675.dist-info → qontract_reconcile-0.10.1rc677.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: qontract-reconcile
|
3
|
-
Version: 0.10.
|
3
|
+
Version: 0.10.1rc677
|
4
4
|
Summary: Collection of tools to reconcile services with their desired state as defined in the app-interface DB.
|
5
5
|
Home-page: https://github.com/app-sre/qontract-reconcile
|
6
6
|
Author: Red Hat App-SRE Team
|
{qontract_reconcile-0.10.1rc675.dist-info → qontract_reconcile-0.10.1rc677.dist-info}/RECORD
RENAMED
@@ -141,7 +141,7 @@ reconcile/aws_cloudwatch_log_retention/integration.py,sha256=0UcSZIrGvnGY4m9fj87
|
|
141
141
|
reconcile/aws_saml_idp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
142
142
|
reconcile/aws_saml_idp/integration.py,sha256=uqec-EnxnfGOgQtg33S-Q1wTCv0sVBHNo02aT94hXrw,4807
|
143
143
|
reconcile/aws_saml_roles/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
144
|
-
reconcile/aws_saml_roles/integration.py,sha256=
|
144
|
+
reconcile/aws_saml_roles/integration.py,sha256=kC4Rnbuy07TMvZO4rjUEcQkJev10M0Ro6r7YXcB7j_c,9530
|
145
145
|
reconcile/aws_version_sync/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
146
146
|
reconcile/aws_version_sync/integration.py,sha256=0rgFLL2usTnngjIgFXIEfVXapFsDI1A493Mftqjfbk0,17292
|
147
147
|
reconcile/aws_version_sync/utils.py,sha256=sVv-48PKi2VITlqqvmpbjnFDOPeGqfKzgkpIszlmjL0,1708
|
@@ -190,7 +190,7 @@ reconcile/gql_definitions/aws_saml_idp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JC
|
|
190
190
|
reconcile/gql_definitions/aws_saml_idp/aws_accounts.py,sha256=ZhsTyUmR-i-0eDXEEl2qZV64bIHMK25KrvlkqpzwO8Y,2652
|
191
191
|
reconcile/gql_definitions/aws_saml_roles/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
192
192
|
reconcile/gql_definitions/aws_saml_roles/aws_accounts.py,sha256=a6tHAPKyJ4cPOYKlDPcdnLyE6i0w6jewvlrNJ3be2yk,2702
|
193
|
-
reconcile/gql_definitions/aws_saml_roles/
|
193
|
+
reconcile/gql_definitions/aws_saml_roles/roles.py,sha256=2Bbk71rFZkB6x0TF5xe1B758jq9wUQ4JNe5-ym_u1so,2529
|
194
194
|
reconcile/gql_definitions/aws_version_sync/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
195
195
|
reconcile/gql_definitions/aws_version_sync/clusters.py,sha256=2TOJOFxpTkZ2HKuqAGUo6tQkzOINSfO-bYDINVpJeL0,2295
|
196
196
|
reconcile/gql_definitions/aws_version_sync/namespaces.py,sha256=eBLyXlSjWdmEE-jY9M2Ocgk7JGi2OsWisTkjHLfgU_A,4311
|
@@ -616,7 +616,7 @@ reconcile/utils/state.py,sha256=zjsprjbOb0WddzmAvh8ACqAt0fcayrX2YPfz7qceRWw,1609
|
|
616
616
|
reconcile/utils/structs.py,sha256=LcbLEg8WxfRqM6nW7NhcWN0YeqF7SQzxOgntmLs1SgY,352
|
617
617
|
reconcile/utils/template.py,sha256=wTvRU4AnAV_o042tD4Mwls2dwWMuk7MKnde3MaCjaYg,331
|
618
618
|
reconcile/utils/terraform_client.py,sha256=7L55Rvxfzj3KtJH8AD8D8YRfBnFpHiTFqSa5e2_9jtk,32092
|
619
|
-
reconcile/utils/terrascript_aws_client.py,sha256=
|
619
|
+
reconcile/utils/terrascript_aws_client.py,sha256=0kYizE48gVlcXxGdtKcdrbw5Xkb2uQ0ao1stov4lyhU,272099
|
620
620
|
reconcile/utils/three_way_diff_strategy.py,sha256=nyqeQsLCoPI6e16k2CF3b9KNgQLU-rPf5RtfdUfVMwE,4468
|
621
621
|
reconcile/utils/throughput.py,sha256=iP4UWAe2LVhDo69mPPmgo9nQ7RxHD6_GS8MZe-aSiuM,344
|
622
622
|
reconcile/utils/unleash.py,sha256=1D56CsZfE3ShDtN3IErE1T2eeIwNmxhK-yYbCotJ99E,3601
|
@@ -723,8 +723,8 @@ tools/test/test_app_interface_metrics_exporter.py,sha256=SX7qL3D1SIRKFo95FoQztvf
|
|
723
723
|
tools/test/test_qontract_cli.py,sha256=OvalpVRfY4pNmpMaWHHYqBjV68b1eGQjX8SCyTAXb1w,3501
|
724
724
|
tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
|
725
725
|
tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
|
726
|
-
qontract_reconcile-0.10.
|
727
|
-
qontract_reconcile-0.10.
|
728
|
-
qontract_reconcile-0.10.
|
729
|
-
qontract_reconcile-0.10.
|
730
|
-
qontract_reconcile-0.10.
|
726
|
+
qontract_reconcile-0.10.1rc677.dist-info/METADATA,sha256=jeb66UTo9ySLlZQEJ9PYl7pNa5qzudUnrbKuXHWuWLI,2382
|
727
|
+
qontract_reconcile-0.10.1rc677.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
728
|
+
qontract_reconcile-0.10.1rc677.dist-info/entry_points.txt,sha256=rIxI5zWtHNlfpDeq1a7pZXAPoqf7HG32KMTN3MeWK_8,429
|
729
|
+
qontract_reconcile-0.10.1rc677.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
|
730
|
+
qontract_reconcile-0.10.1rc677.dist-info/RECORD,,
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import json
|
1
2
|
import sys
|
2
3
|
from collections.abc import (
|
3
4
|
Callable,
|
@@ -7,7 +8,7 @@ from typing import (
|
|
7
8
|
Any,
|
8
9
|
)
|
9
10
|
|
10
|
-
from pydantic import validator
|
11
|
+
from pydantic import BaseModel, root_validator, validator
|
11
12
|
|
12
13
|
from reconcile.gql_definitions.aws_saml_roles.aws_accounts import (
|
13
14
|
AWSAccountV1,
|
@@ -15,15 +16,13 @@ from reconcile.gql_definitions.aws_saml_roles.aws_accounts import (
|
|
15
16
|
from reconcile.gql_definitions.aws_saml_roles.aws_accounts import (
|
16
17
|
query as aws_accounts_query,
|
17
18
|
)
|
18
|
-
from reconcile.gql_definitions.aws_saml_roles.
|
19
|
-
|
20
|
-
)
|
21
|
-
from reconcile.gql_definitions.aws_saml_roles.aws_groups import (
|
22
|
-
query as aws_groups_query,
|
19
|
+
from reconcile.gql_definitions.aws_saml_roles.roles import (
|
20
|
+
query as roles_query,
|
23
21
|
)
|
24
22
|
from reconcile.status import ExitCodes
|
25
23
|
from reconcile.utils import gql
|
26
24
|
from reconcile.utils.aws_api import AWSApi
|
25
|
+
from reconcile.utils.aws_helper import unique_sso_aws_accounts
|
27
26
|
from reconcile.utils.defer import defer
|
28
27
|
from reconcile.utils.disabled_integrations import integration_is_enabled
|
29
28
|
from reconcile.utils.runtime.integration import (
|
@@ -54,6 +53,82 @@ class AwsSamlRolesIntegrationParams(PydanticRunParams):
|
|
54
53
|
raise ValueError("max_session_duration_hours must be between 1 and 12 hours")
|
55
54
|
|
56
55
|
|
56
|
+
class CustomPolicy(BaseModel):
|
57
|
+
name: str
|
58
|
+
policy: dict[str, Any]
|
59
|
+
|
60
|
+
@validator("name")
|
61
|
+
def name_size(cls, v: str) -> str:
|
62
|
+
"""Check the policy name size.
|
63
|
+
|
64
|
+
See https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html
|
65
|
+
"""
|
66
|
+
if len(v) > 128:
|
67
|
+
raise ValueError(
|
68
|
+
f"The policy name '{v}' is too long. The AWS policy name must be 128 characters or less."
|
69
|
+
)
|
70
|
+
return v
|
71
|
+
|
72
|
+
@validator("policy")
|
73
|
+
def policy_size(cls, v: dict[str, Any]) -> dict[str, Any]:
|
74
|
+
"""Check the policy size.
|
75
|
+
|
76
|
+
See https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html
|
77
|
+
"""
|
78
|
+
if len(json.dumps(v, separators=(",", ":"))) > 6144:
|
79
|
+
raise ValueError(
|
80
|
+
f"The policy document '{v}' is too large. AWS policy documents must be 6144 characters or less (w/o white spaces)."
|
81
|
+
)
|
82
|
+
return v
|
83
|
+
|
84
|
+
|
85
|
+
class ManagedPolicy(BaseModel):
|
86
|
+
name: str
|
87
|
+
|
88
|
+
|
89
|
+
class AwsRole(BaseModel):
|
90
|
+
name: str
|
91
|
+
account: str
|
92
|
+
custom_policies: list[CustomPolicy]
|
93
|
+
managed_policies: list[ManagedPolicy]
|
94
|
+
|
95
|
+
@validator("name")
|
96
|
+
def name_size(cls, v: str) -> str:
|
97
|
+
"""Check the role name size.
|
98
|
+
|
99
|
+
See https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html
|
100
|
+
"""
|
101
|
+
if len(v) > 64:
|
102
|
+
raise ValueError(
|
103
|
+
f"The role name '{v}' is too long. The AWS role name must be 64 characters or less."
|
104
|
+
)
|
105
|
+
return v
|
106
|
+
|
107
|
+
@root_validator
|
108
|
+
def validate_policies(cls, values: dict[str, Any]) -> dict[str, Any]:
|
109
|
+
"""Check the policies.
|
110
|
+
|
111
|
+
See https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html
|
112
|
+
"""
|
113
|
+
custom_policies = values.get("custom_policies", [])
|
114
|
+
managed_policies = values.get("managed_policies", [])
|
115
|
+
if len(custom_policies) + len(managed_policies) > 20:
|
116
|
+
raise ValueError(
|
117
|
+
f"The role '{values['name']}' has too many policies. AWS roles can have at most 20 policies (via quota increase). Please consider consolidating the policies."
|
118
|
+
)
|
119
|
+
cp_names = [cp.name for cp in custom_policies]
|
120
|
+
if len(set(cp_names)) != len(cp_names):
|
121
|
+
raise ValueError(
|
122
|
+
f"The role '{values['name']}' has duplicate custom policies."
|
123
|
+
)
|
124
|
+
mp_names = [mp.name for mp in managed_policies]
|
125
|
+
if len(set(mp_names)) != len(mp_names):
|
126
|
+
raise ValueError(
|
127
|
+
f"The role '{values['name']}' has duplicate managed policies."
|
128
|
+
)
|
129
|
+
return values
|
130
|
+
|
131
|
+
|
57
132
|
class AwsSamlRolesIntegration(
|
58
133
|
QontractReconcileIntegration[AwsSamlRolesIntegrationParams]
|
59
134
|
):
|
@@ -70,7 +145,7 @@ class AwsSamlRolesIntegration(
|
|
70
145
|
if not query_func:
|
71
146
|
query_func = gql.get_api().query
|
72
147
|
return {
|
73
|
-
"
|
148
|
+
"roles": [c.dict() for c in self.get_roles(query_func)],
|
74
149
|
}
|
75
150
|
|
76
151
|
def get_aws_accounts(
|
@@ -85,40 +160,69 @@ class AwsSamlRolesIntegration(
|
|
85
160
|
and (not account_name or account.name == account_name)
|
86
161
|
]
|
87
162
|
|
88
|
-
def
|
163
|
+
def get_roles(
|
89
164
|
self, query_func: Callable, account_name: str | None = None
|
90
|
-
) -> list[
|
91
|
-
"""
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
165
|
+
) -> list[AwsRole]:
|
166
|
+
"""Return all roles with AWS account relations."""
|
167
|
+
aws_roles = []
|
168
|
+
for role in roles_query(query_func).roles or []:
|
169
|
+
if not role.aws_groups and not role.user_policies:
|
170
|
+
continue
|
171
|
+
|
172
|
+
user_policies = role.user_policies or []
|
173
|
+
aws_groups = role.aws_groups or []
|
174
|
+
for sso_aws_account in unique_sso_aws_accounts(
|
175
|
+
integration=self.name,
|
176
|
+
accounts=[i.account for i in user_policies + aws_groups],
|
177
|
+
account_name=account_name,
|
178
|
+
):
|
179
|
+
# AWS limits are checked via pydantic validators
|
180
|
+
custom_policies = [
|
181
|
+
CustomPolicy(name=user_policy.name, policy=user_policy.policy)
|
182
|
+
for user_policy in user_policies
|
183
|
+
if user_policy.account.uid == sso_aws_account.uid
|
184
|
+
]
|
185
|
+
managed_policies = [
|
186
|
+
ManagedPolicy(name=p)
|
187
|
+
for aws_group in aws_groups
|
188
|
+
if aws_group.account.uid == sso_aws_account.uid
|
189
|
+
for p in aws_group.policies or []
|
190
|
+
]
|
191
|
+
|
192
|
+
aws_roles.append(
|
193
|
+
AwsRole(
|
194
|
+
name=f"{sso_aws_account.uid}-{role.name}",
|
195
|
+
account=sso_aws_account.name,
|
196
|
+
custom_policies=custom_policies,
|
197
|
+
managed_policies=managed_policies,
|
198
|
+
)
|
199
|
+
)
|
200
|
+
|
201
|
+
return aws_roles
|
103
202
|
|
104
203
|
def populate_saml_iam_roles(
|
105
|
-
self, ts: TerrascriptClient,
|
204
|
+
self, ts: TerrascriptClient, aws_roles: Iterable[AwsRole]
|
106
205
|
) -> None:
|
107
206
|
"""Populate the SAML IAM roles."""
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
207
|
+
unique_policies = {
|
208
|
+
(role.account, custom_policy.name): custom_policy.policy
|
209
|
+
for role in aws_roles
|
210
|
+
for custom_policy in role.custom_policies
|
211
|
+
}
|
212
|
+
# User policies are unique per account
|
213
|
+
for (account, policy), policy_doc in unique_policies.items():
|
214
|
+
ts.populate_iam_policy(
|
215
|
+
account=account,
|
216
|
+
name=policy,
|
217
|
+
policy=policy_doc,
|
218
|
+
)
|
219
|
+
for role in aws_roles:
|
117
220
|
ts.populate_saml_iam_role(
|
118
|
-
account=
|
119
|
-
name=
|
221
|
+
account=role.account,
|
222
|
+
name=role.name,
|
120
223
|
saml_provider_name=self.params.saml_idp_name,
|
121
|
-
|
224
|
+
aws_managed_policies=[p.name for p in role.managed_policies],
|
225
|
+
customer_managed_policies=[p.name for p in role.custom_policies],
|
122
226
|
max_session_duration_hours=self.params.max_session_duration_hours,
|
123
227
|
)
|
124
228
|
|
@@ -130,9 +234,7 @@ class AwsSamlRolesIntegration(
|
|
130
234
|
gql_api.query, account_name=self.params.account_name
|
131
235
|
)
|
132
236
|
aws_accounts_dict = [account.dict(by_alias=True) for account in aws_accounts]
|
133
|
-
|
134
|
-
gql_api.query, account_name=self.params.account_name
|
135
|
-
)
|
237
|
+
aws_roles = self.get_roles(gql_api.query, account_name=self.params.account_name)
|
136
238
|
|
137
239
|
ts = TerrascriptClient(
|
138
240
|
self.name.replace("-", "_"),
|
@@ -141,7 +243,7 @@ class AwsSamlRolesIntegration(
|
|
141
243
|
aws_accounts_dict,
|
142
244
|
secret_reader=self.secret_reader,
|
143
245
|
)
|
144
|
-
self.populate_saml_iam_roles(ts,
|
246
|
+
self.populate_saml_iam_roles(ts, aws_roles)
|
145
247
|
working_dirs = ts.dump(print_to_file=self.params.print_to_file)
|
146
248
|
|
147
249
|
if self.params.print_to_file:
|
@@ -17,25 +17,35 @@ from pydantic import ( # noqa: F401 # pylint: disable=W0611
|
|
17
17
|
Json,
|
18
18
|
)
|
19
19
|
|
20
|
+
from reconcile.gql_definitions.fragments.aws_account_sso import AWSAccountSSO
|
21
|
+
|
20
22
|
|
21
23
|
DEFINITION = """
|
22
|
-
|
23
|
-
|
24
|
+
fragment AWSAccountSSO on AWSAccount_v1 {
|
25
|
+
name
|
26
|
+
uid
|
27
|
+
sso
|
28
|
+
disable {
|
29
|
+
integrations
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
query AwsSamlRolesQuery {
|
34
|
+
roles: roles_v1 {
|
24
35
|
name
|
25
|
-
|
36
|
+
user_policies {
|
26
37
|
name
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
integrations
|
38
|
+
policy
|
39
|
+
account {
|
40
|
+
...AWSAccountSSO
|
31
41
|
}
|
32
42
|
}
|
33
|
-
|
34
|
-
|
35
|
-
|
43
|
+
aws_groups {
|
44
|
+
account {
|
45
|
+
...AWSAccountSSO
|
36
46
|
}
|
47
|
+
policies
|
37
48
|
}
|
38
|
-
policies
|
39
49
|
}
|
40
50
|
}
|
41
51
|
"""
|
@@ -47,37 +57,28 @@ class ConfiguredBaseModel(BaseModel):
|
|
47
57
|
extra=Extra.forbid
|
48
58
|
|
49
59
|
|
50
|
-
class
|
51
|
-
integrations: Optional[list[str]] = Field(..., alias="integrations")
|
52
|
-
|
53
|
-
|
54
|
-
class AWSAccountV1(ConfiguredBaseModel):
|
60
|
+
class AWSUserPolicyV1(ConfiguredBaseModel):
|
55
61
|
name: str = Field(..., alias="name")
|
56
|
-
|
57
|
-
|
58
|
-
disable: Optional[DisableClusterAutomationsV1] = Field(..., alias="disable")
|
62
|
+
policy: Json = Field(..., alias="policy")
|
63
|
+
account: AWSAccountSSO = Field(..., alias="account")
|
59
64
|
|
60
65
|
|
61
|
-
class
|
62
|
-
|
66
|
+
class AWSGroupV1(ConfiguredBaseModel):
|
67
|
+
account: AWSAccountSSO = Field(..., alias="account")
|
68
|
+
policies: Optional[list[str]] = Field(..., alias="policies")
|
63
69
|
|
64
70
|
|
65
71
|
class RoleV1(ConfiguredBaseModel):
|
66
|
-
users: list[UserV1] = Field(..., alias="users")
|
67
|
-
|
68
|
-
|
69
|
-
class AWSGroupV1(ConfiguredBaseModel):
|
70
72
|
name: str = Field(..., alias="name")
|
71
|
-
|
72
|
-
|
73
|
-
policies: Optional[list[str]] = Field(..., alias="policies")
|
73
|
+
user_policies: Optional[list[AWSUserPolicyV1]] = Field(..., alias="user_policies")
|
74
|
+
aws_groups: Optional[list[AWSGroupV1]] = Field(..., alias="aws_groups")
|
74
75
|
|
75
76
|
|
76
|
-
class
|
77
|
-
|
77
|
+
class AwsSamlRolesQueryQueryData(ConfiguredBaseModel):
|
78
|
+
roles: Optional[list[RoleV1]] = Field(..., alias="roles")
|
78
79
|
|
79
80
|
|
80
|
-
def query(query_func: Callable, **kwargs: Any) ->
|
81
|
+
def query(query_func: Callable, **kwargs: Any) -> AwsSamlRolesQueryQueryData:
|
81
82
|
"""
|
82
83
|
This is a convenience function which queries and parses the data into
|
83
84
|
concrete types. It should be compatible with most GQL clients.
|
@@ -90,7 +91,7 @@ def query(query_func: Callable, **kwargs: Any) -> AwsSamlRolesAwsGroupQueryQuery
|
|
90
91
|
kwargs: optional arguments that will be passed to the query function
|
91
92
|
|
92
93
|
Returns:
|
93
|
-
|
94
|
+
AwsSamlRolesQueryQueryData: queried data parsed into generated classes
|
94
95
|
"""
|
95
96
|
raw_data: dict[Any, Any] = query_func(DEFINITION, **kwargs)
|
96
|
-
return
|
97
|
+
return AwsSamlRolesQueryQueryData(**raw_data)
|
@@ -843,13 +843,8 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
843
843
|
for user_policy in user_policies:
|
844
844
|
policy_name = user_policy["name"]
|
845
845
|
account_name = user_policy["account"]["name"]
|
846
|
-
account_uid = user_policy["account"]["uid"]
|
847
846
|
for user in users:
|
848
|
-
# replace known keys with values
|
849
847
|
user_name = self._get_aws_username(user)
|
850
|
-
policy = user_policy["policy"]
|
851
|
-
policy = policy.replace("${aws:username}", user_name)
|
852
|
-
policy = policy.replace("${aws:accountid}", account_uid)
|
853
848
|
|
854
849
|
# Ref: terraform aws_iam_policy
|
855
850
|
tf_iam_user = self.get_tf_iam_user(user_name)
|
@@ -857,7 +852,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
857
852
|
tf_aws_iam_policy = aws_iam_policy(
|
858
853
|
identifier,
|
859
854
|
name=identifier,
|
860
|
-
policy=policy,
|
855
|
+
policy=user_policy["policy"],
|
861
856
|
)
|
862
857
|
self.add_resource(account_name, tf_aws_iam_policy)
|
863
858
|
# Ref: terraform aws_iam_user_policy_attachment
|
@@ -2569,18 +2564,29 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
2569
2564
|
|
2570
2565
|
self.add_resources(account, tf_resources)
|
2571
2566
|
|
2567
|
+
def populate_iam_policy(self, account: str, name: str, policy: dict[str, Any]):
|
2568
|
+
tf_aws_iam_policy = aws_iam_policy(
|
2569
|
+
f"{account}-{name}", name=name, policy=json.dumps(policy)
|
2570
|
+
)
|
2571
|
+
self.add_resource(account, tf_aws_iam_policy)
|
2572
|
+
|
2572
2573
|
def populate_saml_iam_role(
|
2573
2574
|
self,
|
2574
2575
|
account: str,
|
2575
2576
|
name: str,
|
2576
2577
|
saml_provider_name: str,
|
2577
|
-
|
2578
|
+
aws_managed_policies: list[str],
|
2579
|
+
customer_managed_policies: list[str] | None = None,
|
2578
2580
|
max_session_duration_hours: int = 1,
|
2579
2581
|
) -> None:
|
2580
2582
|
"""Manage the an IAM role needed for SAML authentication."""
|
2581
2583
|
managed_policy_arns = [
|
2582
|
-
f"arn:{self._get_partition(account)}:
|
2583
|
-
for policy in
|
2584
|
+
f"arn:{self._get_partition(account)}:iam::aws:policy/{policy}"
|
2585
|
+
for policy in aws_managed_policies
|
2586
|
+
]
|
2587
|
+
managed_policy_arns += [
|
2588
|
+
f"arn:{self._get_partition(account)}:iam::{self.uids[account]}:policy/{policy}"
|
2589
|
+
for policy in customer_managed_policies or []
|
2584
2590
|
]
|
2585
2591
|
assume_role_policy = {
|
2586
2592
|
"Version": "2012-10-17",
|
@@ -2601,7 +2607,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
2601
2607
|
}
|
2602
2608
|
role_tf_resource = aws_iam_role(
|
2603
2609
|
f"{account}-{name}",
|
2604
|
-
name=
|
2610
|
+
name=name,
|
2605
2611
|
assume_role_policy=json.dumps(assume_role_policy),
|
2606
2612
|
managed_policy_arns=managed_policy_arns,
|
2607
2613
|
max_session_duration=max_session_duration_hours * 3600,
|
File without changes
|
File without changes
|
{qontract_reconcile-0.10.1rc675.dist-info → qontract_reconcile-0.10.1rc677.dist-info}/top_level.txt
RENAMED
File without changes
|