qontract-reconcile 0.10.1rc536__py3-none-any.whl → 0.10.1rc537__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.1rc536.dist-info → qontract_reconcile-0.10.1rc537.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc536.dist-info → qontract_reconcile-0.10.1rc537.dist-info}/RECORD +8 -8
- reconcile/acs_policies.py +16 -6
- reconcile/test/test_acs_policies.py +26 -11
- reconcile/utils/acs/policies.py +10 -0
- {qontract_reconcile-0.10.1rc536.dist-info → qontract_reconcile-0.10.1rc537.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc536.dist-info → qontract_reconcile-0.10.1rc537.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc536.dist-info → qontract_reconcile-0.10.1rc537.dist-info}/top_level.txt +0 -0
{qontract_reconcile-0.10.1rc536.dist-info → qontract_reconcile-0.10.1rc537.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.1rc537
|
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.1rc536.dist-info → qontract_reconcile-0.10.1rc537.dist-info}/RECORD
RENAMED
@@ -1,5 +1,5 @@
|
|
1
1
|
reconcile/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
reconcile/acs_policies.py,sha256=
|
2
|
+
reconcile/acs_policies.py,sha256=e_kVyP4rGm3fJzq10Anr8scZoPenlmTcoS5REK0d2T0,9144
|
3
3
|
reconcile/acs_rbac.py,sha256=YoKu5wTRTtb3EGT0PV3r279LDgvw2ECb-0_0j4suScg,23032
|
4
4
|
reconcile/aws_ami_share.py,sha256=eeu0TI3M5yyUaozyAq_aW3tir-9be4YFguOXvIvKHSo,3757
|
5
5
|
reconcile/aws_ecr_image_pull_secrets.py,sha256=TGEc_0nv8oxV2HqA8VdcM4HHP-B1YqmNOOU6FPwVFTY,2328
|
@@ -375,7 +375,7 @@ reconcile/templates/jira-checkpoint-missinginfo.j2,sha256=c_Vvg-lEENsB3tgxm9B6Y9
|
|
375
375
|
reconcile/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
376
376
|
reconcile/test/conftest.py,sha256=rQousYrxUz-EwAIbsYO6bIwR1B4CrOz9y_zaUVo2lfI,4466
|
377
377
|
reconcile/test/fixtures.py,sha256=9SDWAUlSd1rCx7z3GhULHcpr-I6FyCsXxaFAZIqYQsQ,591
|
378
|
-
reconcile/test/test_acs_policies.py,sha256=
|
378
|
+
reconcile/test/test_acs_policies.py,sha256=hMnCX9KdLRKb53gYXK4JUR5yJwhczJRyyUPywDeLeLg,15716
|
379
379
|
reconcile/test/test_acs_rbac.py,sha256=lvNd8GY0-GHzcOdOn13QWdrqbBXXKzNT7EEDHNH7cjM,28272
|
380
380
|
reconcile/test/test_aggregated_list.py,sha256=iiWitQuNYC58aimWaiBoE4NROHjr1NCgQ91MnHEG_Ro,6412
|
381
381
|
reconcile/test/test_amtool.py,sha256=vxRhGieeydMBOb9UI2ziMHjJa8puMeGNsUhGhy-yMnk,1032
|
@@ -590,7 +590,7 @@ reconcile/utils/vaultsecretref.py,sha256=3Ed2uBy36TzSvL0B-l4FoWQqB2SbBKDKEuUPIO6
|
|
590
590
|
reconcile/utils/vcs.py,sha256=o1r0n_IrU2El75CED_6sjR2GZGM-exuWsj5F7jONaMU,6779
|
591
591
|
reconcile/utils/acs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
592
592
|
reconcile/utils/acs/base.py,sha256=Qih-xZ3RBJZEE291iHHlv7lUY6ShcAvSj1PA3_aTTnM,2276
|
593
|
-
reconcile/utils/acs/policies.py,sha256=
|
593
|
+
reconcile/utils/acs/policies.py,sha256=_jAz6cv8KRYtDsXjGoJgNbD8_9PUa5LSwwVlpK4A_cQ,5505
|
594
594
|
reconcile/utils/acs/rbac.py,sha256=ugsLM9Pb7FbUbdq85E3VzXGMaB9ZovXob7tdWCxwqZ8,8808
|
595
595
|
reconcile/utils/cloud_resource_best_practice/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
596
596
|
reconcile/utils/cloud_resource_best_practice/aws_rds.py,sha256=EvE6XKLsrZ531MJptKqPht2lOETrOjySTHXk6CzMgo0,2279
|
@@ -668,8 +668,8 @@ tools/test/test_app_interface_metrics_exporter.py,sha256=SX7qL3D1SIRKFo95FoQztvf
|
|
668
668
|
tools/test/test_qontract_cli.py,sha256=d18KrdhtUGqoC7_kWZU128U0-VJEj-0rjFkLVufcI6I,2755
|
669
669
|
tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
|
670
670
|
tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
|
671
|
-
qontract_reconcile-0.10.
|
672
|
-
qontract_reconcile-0.10.
|
673
|
-
qontract_reconcile-0.10.
|
674
|
-
qontract_reconcile-0.10.
|
675
|
-
qontract_reconcile-0.10.
|
671
|
+
qontract_reconcile-0.10.1rc537.dist-info/METADATA,sha256=dGXxQQQzpUMW_Kyo_ktrTXrUVvKSJ9GMS7SG5jKdMoo,2349
|
672
|
+
qontract_reconcile-0.10.1rc537.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
673
|
+
qontract_reconcile-0.10.1rc537.dist-info/entry_points.txt,sha256=rTjAv28I_CHLM8ID3OPqMI_suoQ9s7tFbim4aYjn9kk,376
|
674
|
+
qontract_reconcile-0.10.1rc537.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
|
675
|
+
qontract_reconcile-0.10.1rc537.dist-info/RECORD,,
|
reconcile/acs_policies.py
CHANGED
@@ -58,7 +58,10 @@ class AcsPoliciesIntegration(QontractReconcileIntegration[NoParams]):
|
|
58
58
|
return self.qontract_integration.replace("_", "-")
|
59
59
|
|
60
60
|
def _build_policy(
|
61
|
-
self,
|
61
|
+
self,
|
62
|
+
gql_policy: AcsPolicyV1,
|
63
|
+
notifier_name_to_id: dict[str, str],
|
64
|
+
cluster_name_to_id: dict[str, str],
|
62
65
|
) -> Policy:
|
63
66
|
conditions = [
|
64
67
|
pc for c in gql_policy.conditions if (pc := self._build_policy_condition(c))
|
@@ -72,7 +75,7 @@ class AcsPoliciesIntegration(QontractReconcileIntegration[NoParams]):
|
|
72
75
|
severity=f"{gql_policy.severity.upper()}_SEVERITY", # align with acs api severity value format
|
73
76
|
scope=sorted(
|
74
77
|
[
|
75
|
-
Scope(cluster=cs.name, namespace="")
|
78
|
+
Scope(cluster=cluster_name_to_id[cs.name], namespace="")
|
76
79
|
for cs in cast(
|
77
80
|
gql_acs_policies.AcsPolicyScopeClusterV1,
|
78
81
|
gql_policy.scope,
|
@@ -83,7 +86,9 @@ class AcsPoliciesIntegration(QontractReconcileIntegration[NoParams]):
|
|
83
86
|
if gql_policy.scope.level == "cluster"
|
84
87
|
else sorted(
|
85
88
|
[
|
86
|
-
Scope(
|
89
|
+
Scope(
|
90
|
+
cluster=cluster_name_to_id[ns.cluster.name], namespace=ns.name
|
91
|
+
)
|
87
92
|
for ns in cast(
|
88
93
|
gql_acs_policies.AcsPolicyScopeNamespaceV1,
|
89
94
|
gql_policy.scope,
|
@@ -158,7 +163,10 @@ class AcsPoliciesIntegration(QontractReconcileIntegration[NoParams]):
|
|
158
163
|
return None
|
159
164
|
|
160
165
|
def get_desired_state(
|
161
|
-
self,
|
166
|
+
self,
|
167
|
+
query_func: Callable,
|
168
|
+
notifiers: list[AcsPolicyApi.NotifierIdentifiers],
|
169
|
+
clusters: list[AcsPolicyApi.ClusterIdentifiers],
|
162
170
|
) -> list[Policy]:
|
163
171
|
"""
|
164
172
|
Get desired ACS security policies and convert to acs api policy object format
|
@@ -167,8 +175,9 @@ class AcsPoliciesIntegration(QontractReconcileIntegration[NoParams]):
|
|
167
175
|
:return: list of utils.acs.policies.Policy derived from acs-policy-1 definitions
|
168
176
|
"""
|
169
177
|
notifier_name_to_id = {n.name: n.id for n in notifiers}
|
178
|
+
cluster_name_to_id = {c.name: c.id for c in clusters}
|
170
179
|
return [
|
171
|
-
self._build_policy(gql_policy, notifier_name_to_id)
|
180
|
+
self._build_policy(gql_policy, notifier_name_to_id, cluster_name_to_id)
|
172
181
|
for gql_policy in gql_acs_policies.query(query_func=query_func).acs_policies
|
173
182
|
or []
|
174
183
|
]
|
@@ -225,7 +234,8 @@ class AcsPoliciesIntegration(QontractReconcileIntegration[NoParams]):
|
|
225
234
|
instance={"url": instance.url, "token": token[instance.credentials.field]}
|
226
235
|
) as acs_api:
|
227
236
|
notifiers = acs_api.list_notifiers()
|
228
|
-
|
237
|
+
clusters = acs_api.list_clusters()
|
238
|
+
desired = self.get_desired_state(gqlapi.query, notifiers, clusters)
|
229
239
|
current = acs_api.get_custom_policies()
|
230
240
|
self.reconcile(
|
231
241
|
desired=desired, current=current, acs=acs_api, dry_run=dry_run
|
@@ -20,6 +20,10 @@ from reconcile.gql_definitions.acs.acs_policies import (
|
|
20
20
|
)
|
21
21
|
from reconcile.utils.acs.policies import AcsPolicyApi, Policy, PolicyCondition, Scope
|
22
22
|
|
23
|
+
CLUSTER_NAME_ONE = "app-sre-stage"
|
24
|
+
CLUSTER_ID_ONE = "5211d395-5cf7-4185-a1fb-d88f41bc7542"
|
25
|
+
CLUSTER_NAME_TWO = "app-sre-prod"
|
26
|
+
CLUSTER_ID_TWO = "a217cca7-d85a-4be1-9703-f58866fdbe2d"
|
23
27
|
CUSTOM_POLICY_ONE_NAME = "app-sre-clusters-fixable-cve-7-fixable"
|
24
28
|
CUSTOM_POLICY_ONE_ID = "365d4e71-3241-4448-9f3d-eb0eed1c1820"
|
25
29
|
CUSTOM_POLICY_TWO_NAME = "app-sre-namespaces-severity-critical"
|
@@ -41,8 +45,8 @@ def query_data_desired_state() -> AcsPolicyQueryData:
|
|
41
45
|
scope=AcsPolicyScopeClusterV1(
|
42
46
|
level="cluster",
|
43
47
|
clusters=[
|
44
|
-
ClusterV1(name=
|
45
|
-
ClusterV1(name=
|
48
|
+
ClusterV1(name=CLUSTER_NAME_ONE),
|
49
|
+
ClusterV1(name=CLUSTER_NAME_TWO),
|
46
50
|
],
|
47
51
|
),
|
48
52
|
conditions=[
|
@@ -91,8 +95,8 @@ def modeled_acs_policies() -> list[Policy]:
|
|
91
95
|
notifiers=[JIRA_NOTIFIER_ID],
|
92
96
|
categories=["Vulnerability Management"],
|
93
97
|
scope=[
|
94
|
-
Scope(cluster=
|
95
|
-
Scope(cluster=
|
98
|
+
Scope(cluster=CLUSTER_ID_ONE, namespace=""),
|
99
|
+
Scope(cluster=CLUSTER_ID_TWO, namespace=""),
|
96
100
|
],
|
97
101
|
conditions=[
|
98
102
|
PolicyCondition(field_name="CVSS", values=[">=7"], negate=False),
|
@@ -106,8 +110,8 @@ def modeled_acs_policies() -> list[Policy]:
|
|
106
110
|
notifiers=[],
|
107
111
|
categories=["DevOps Best Practices", "Vulnerability Management"],
|
108
112
|
scope=[
|
109
|
-
Scope(cluster=
|
110
|
-
Scope(cluster=
|
113
|
+
Scope(cluster=CLUSTER_ID_ONE, namespace="app-interface-stage"),
|
114
|
+
Scope(cluster=CLUSTER_ID_TWO, namespace="app-interface-production"),
|
111
115
|
],
|
112
116
|
conditions=[
|
113
117
|
PolicyCondition(
|
@@ -175,8 +179,8 @@ def api_response_policies_specific() -> list[Any]:
|
|
175
179
|
"eventSource": "NOT_APPLICABLE",
|
176
180
|
"exclusions": [],
|
177
181
|
"scope": [
|
178
|
-
{"cluster":
|
179
|
-
{"cluster":
|
182
|
+
{"cluster": CLUSTER_ID_ONE, "namespace": "", "label": None},
|
183
|
+
{"cluster": CLUSTER_ID_TWO, "namespace": "", "label": None},
|
180
184
|
],
|
181
185
|
"severity": "HIGH_SEVERITY",
|
182
186
|
"enforcementActions": [],
|
@@ -216,12 +220,12 @@ def api_response_policies_specific() -> list[Any]:
|
|
216
220
|
"exclusions": [],
|
217
221
|
"scope": [
|
218
222
|
{
|
219
|
-
"cluster":
|
223
|
+
"cluster": CLUSTER_ID_ONE,
|
220
224
|
"namespace": "app-interface-stage",
|
221
225
|
"label": None,
|
222
226
|
},
|
223
227
|
{
|
224
|
-
"cluster":
|
228
|
+
"cluster": CLUSTER_ID_TWO,
|
225
229
|
"namespace": "app-interface-production",
|
226
230
|
"label": None,
|
227
231
|
},
|
@@ -257,11 +261,20 @@ def api_response_list_notifiers() -> list[AcsPolicyApi.NotifierIdentifiers]:
|
|
257
261
|
]
|
258
262
|
|
259
263
|
|
264
|
+
@pytest.fixture
|
265
|
+
def api_response_list_clusters() -> list[AcsPolicyApi.ClusterIdentifiers]:
|
266
|
+
return [
|
267
|
+
AcsPolicyApi.ClusterIdentifiers(id=CLUSTER_ID_ONE, name=CLUSTER_NAME_ONE),
|
268
|
+
AcsPolicyApi.ClusterIdentifiers(id=CLUSTER_ID_TWO, name=CLUSTER_NAME_TWO),
|
269
|
+
]
|
270
|
+
|
271
|
+
|
260
272
|
def test_get_desired_state(
|
261
273
|
mocker: MockerFixture,
|
262
274
|
query_data_desired_state: AcsPolicyQueryData,
|
263
275
|
modeled_acs_policies: list[Policy],
|
264
276
|
api_response_list_notifiers: list[AcsPolicyApi.NotifierIdentifiers],
|
277
|
+
api_response_list_clusters: list[AcsPolicyApi.ClusterIdentifiers],
|
265
278
|
) -> None:
|
266
279
|
query_func = mocker.patch(
|
267
280
|
"reconcile.gql_definitions.acs.acs_policies.query", autospec=True
|
@@ -270,7 +283,9 @@ def test_get_desired_state(
|
|
270
283
|
|
271
284
|
integration = AcsPoliciesIntegration()
|
272
285
|
result = integration.get_desired_state(
|
273
|
-
query_func=query_func,
|
286
|
+
query_func=query_func,
|
287
|
+
notifiers=api_response_list_notifiers,
|
288
|
+
clusters=api_response_list_clusters,
|
274
289
|
)
|
275
290
|
assert result == modeled_acs_policies
|
276
291
|
|
reconcile/utils/acs/policies.py
CHANGED
@@ -151,3 +151,13 @@ class AcsPolicyApi(AcsBaseApi):
|
|
151
151
|
self.NotifierIdentifiers(id=c["id"], name=c["name"])
|
152
152
|
for c in self.generic_request("/v1/notifiers", "GET").json()["notifiers"]
|
153
153
|
]
|
154
|
+
|
155
|
+
class ClusterIdentifiers(BaseModel):
|
156
|
+
id: str
|
157
|
+
name: str
|
158
|
+
|
159
|
+
def list_clusters(self) -> list[ClusterIdentifiers]:
|
160
|
+
return [
|
161
|
+
self.ClusterIdentifiers(id=c["id"], name=c["name"])
|
162
|
+
for c in self.generic_request("/v1/clusters", "GET").json()["clusters"]
|
163
|
+
]
|
File without changes
|
File without changes
|
{qontract_reconcile-0.10.1rc536.dist-info → qontract_reconcile-0.10.1rc537.dist-info}/top_level.txt
RENAMED
File without changes
|