qontract-reconcile 0.10.2.dev204__py3-none-any.whl → 0.10.2.dev206__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qontract-reconcile
3
- Version: 0.10.2.dev204
3
+ Version: 0.10.2.dev206
4
4
  Summary: Collection of tools to reconcile services with their desired state as defined in the app-interface DB.
5
5
  Project-URL: homepage, https://github.com/app-sre/qontract-reconcile
6
6
  Project-URL: repository, https://github.com/app-sre/qontract-reconcile
@@ -45,7 +45,7 @@ reconcile/jenkins_roles.py,sha256=HadmoNhgOoKMFZJmCe_Gdg0_a9k_1MuOXidtr801nUU,45
45
45
  reconcile/jenkins_webhooks.py,sha256=dzMT1ywXjeAo5sHj-ittW06Ed3beAUPjnc_oCAtD-Rg,2150
46
46
  reconcile/jenkins_webhooks_cleaner.py,sha256=JsN_NVPfZJwv1JtSzZXDIHUqGiefL-DRffFnDGau9aY,1539
47
47
  reconcile/jenkins_worker_fleets.py,sha256=L2wEXpd4xuEHrXGss4iH788nG8UlLSYduZe1EY2IVw4,5377
48
- reconcile/jira_permissions_validator.py,sha256=5rc4Q2mXGL3HCZmYpZaJkjzBrpCRnlLeCY0Yl2fDOs4,14672
48
+ reconcile/jira_permissions_validator.py,sha256=nVHZg7kNn04Q-ryNM20wthMrhXos28g3O9b0ahzxAKc,14690
49
49
  reconcile/jira_watcher.py,sha256=L_UL2MKm2SoIGNsCLThm28pnqCkoFc154JWsD6bURug,3593
50
50
  reconcile/ldap_users.py,sha256=oP1CAxmgSi3zDJ3vKTPySjap6WmEX1U469FmFrov5l4,4599
51
51
  reconcile/mr_client_gateway.py,sha256=WhjMd-sIXDFCV8-rt8CEjurJ5OYB1pOD0K3o0tZRXQg,1885
@@ -72,7 +72,7 @@ reconcile/openshift_prometheus_rules.py,sha256=onowXab248zmHH8SbYDTc1W1bl7JiqRFU
72
72
  reconcile/openshift_resourcequotas.py,sha256=yUi56PiOn3inMMfq_x_FEHmaW-reGipzoorjdar372g,2415
73
73
  reconcile/openshift_resources.py,sha256=I2nO_C37mG3rfyGrd4cGwN3mVseVGuTAHAyhFzLyqF4,1518
74
74
  reconcile/openshift_resources_base.py,sha256=3HudPdM7EE0HNWUn1eu0O20Ij25fqGisaDBMVvTk1fk,41768
75
- reconcile/openshift_rhcs_certs.py,sha256=snLx33sX2cj2TPGRgrEGDV6Ofm17IougnxT0T-5FNoA,9448
75
+ reconcile/openshift_rhcs_certs.py,sha256=lP0GwKMRl8YBzxrwdbBOxrPqIPYNmu2KkZPGzWKyRVU,9859
76
76
  reconcile/openshift_rolebindings.py,sha256=9mlJ2FjWUoH-rsjtasreA_hV-K5Z_YR00qR_RR60OZM,6555
77
77
  reconcile/openshift_routes.py,sha256=fXvuPSjcjVw1X3j2EQvUAdbOepmIFdKk-M3qP8QzPiw,1075
78
78
  reconcile/openshift_saas_deploy.py,sha256=T1dvb9zajisaJNjbnR6-AZHU-itscHtr4oCqLj8KCK0,13037
@@ -223,11 +223,11 @@ reconcile/glitchtip/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
223
223
  reconcile/glitchtip/integration.py,sha256=HWc0cz3vNpZg8T5nVMPyD5QnlgsUHwLpJsGRbr_hvIM,7937
224
224
  reconcile/glitchtip/reconciler.py,sha256=nUvDv7qG1ly0cA16MmlL6NV71yl1mJYLT2mui7lmi0Y,12402
225
225
  reconcile/glitchtip_project_alerts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
226
- reconcile/glitchtip_project_alerts/integration.py,sha256=BgMx-NyV9mTuv7Sotb2OioCO-iwVrN9-HCViVLU771c,13755
226
+ reconcile/glitchtip_project_alerts/integration.py,sha256=d3PMy-mQSbSZdIGAVaZCA2UhrK9LPYlnLtUluLlXej4,13669
227
227
  reconcile/glitchtip_project_dsn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
228
228
  reconcile/glitchtip_project_dsn/integration.py,sha256=2iugub-kHYkHNK33n0v9_TeWonuxCPah_VkoTPvaajE,8077
229
229
  reconcile/gql_definitions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
230
- reconcile/gql_definitions/introspection.json,sha256=Go8Ep6qN2COkqnWsqQLfiGDS1TbQFyK_fp5TiM0ghpo,2334795
230
+ reconcile/gql_definitions/introspection.json,sha256=Oo__Q1ENvfRSNRcJbojqqWyICHq5mSE_ebhJGqtKCsw,2335890
231
231
  reconcile/gql_definitions/acs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
232
232
  reconcile/gql_definitions/acs/acs_instances.py,sha256=L91WW9LbhJbBSrECqShQpFtjoBOsmNIYLRpMbx1io5o,2181
233
233
  reconcile/gql_definitions/acs/acs_policies.py,sha256=Ygpfl2-VkYLSlJvHgp_dJBfb66K_Rwfdfpsa18w1v1s,4338
@@ -296,7 +296,7 @@ reconcile/gql_definitions/common/pipeline_providers.py,sha256=9rpsqPuvj82B4ki56x
296
296
  reconcile/gql_definitions/common/quay_instances.py,sha256=toBkdYYVTmEafezAHZKgaW-mQ29xEW6jeronzsAlNyI,1786
297
297
  reconcile/gql_definitions/common/quay_orgs.py,sha256=NhA8kqvVUDbrsryEvEL5mlIv5R3T4XNhSRXtfL_yptY,1788
298
298
  reconcile/gql_definitions/common/reserved_networks.py,sha256=yP9qSQCaSQcva-ZgTnZp09qH27ur5_qK080ToIs04MY,2560
299
- reconcile/gql_definitions/common/rhcs_provider_settings.py,sha256=x3OmYjMCr9EzfkmLmbdx9zEKzqE9IczE8lcyzf_v9JU,1969
299
+ reconcile/gql_definitions/common/rhcs_provider_settings.py,sha256=88NwWT1kmbysze_w4YT6kiOYU2StDHHP6QRQXnPlpmQ,2057
300
300
  reconcile/gql_definitions/common/saas_files.py,sha256=d1L_S5LgCMa4QuAqZGQYTWb5L_nPCOxSEjU4O__OeBU,17728
301
301
  reconcile/gql_definitions/common/saas_target_namespaces.py,sha256=4VYP2VbwY8WVwtSFk2-jsUNhSmRD3X4FWKxetOKvmd0,2835
302
302
  reconcile/gql_definitions/common/saasherder_settings.py,sha256=nqQLcMwYxLseqq0BEcVvmrpIj2eQq0h8XDSpLN6GGCw,1793
@@ -370,7 +370,7 @@ reconcile/gql_definitions/glitchtip/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQ
370
370
  reconcile/gql_definitions/glitchtip/glitchtip_instance.py,sha256=QUfLhRkdE_-SorWgLBB8LHFD6kihbFwEoVByCLax3yM,2781
371
371
  reconcile/gql_definitions/glitchtip/glitchtip_project.py,sha256=3hS6ZbWr-KMWeVHYbP3HAK7uHd2e6KsXOr87gba7Uqc,6578
372
372
  reconcile/gql_definitions/glitchtip_project_alerts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
373
- reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py,sha256=Pv6RcuIzpNmGc43eEq64nnKG0Dr7H0wjy5Xg1_oRltM,5197
373
+ reconcile/gql_definitions/glitchtip_project_alerts/glitchtip_project.py,sha256=AlnJ1AO4QqF9sU6YxUfgCqBHgcIJmb2bVuq7U_QU3wU,5206
374
374
  reconcile/gql_definitions/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
375
375
  reconcile/gql_definitions/integrations/integrations.py,sha256=IIKNzpgUCe5-lvdhoA4VFiqvtjtjzTndiR5-jKSzgrQ,11667
376
376
  reconcile/gql_definitions/jenkins_configs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -379,7 +379,7 @@ reconcile/gql_definitions/jenkins_configs/jenkins_instances.py,sha256=b3gYVzQavx
379
379
  reconcile/gql_definitions/jira/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
380
380
  reconcile/gql_definitions/jira/jira_servers.py,sha256=N7mvIdqoXT-90abkiaC2bxz2ZjW3d826qVV5OL8_TAM,2223
381
381
  reconcile/gql_definitions/jira_permissions_validator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
382
- reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py,sha256=RqIDe90sKjEfFNEIxtfBg10Bddc11M6I7ae_FqBl3To,4034
382
+ reconcile/gql_definitions/jira_permissions_validator/jira_boards_for_permissions_validator.py,sha256=54WiktlJHGOPheKDCMU_Szn1jQeYeI7vCEd_8OOQ-x8,4043
383
383
  reconcile/gql_definitions/jumphosts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
384
384
  reconcile/gql_definitions/jumphosts/jumphosts.py,sha256=gN595lx7K1XsB2AfxDQ911TBVBbCoxibVeujnsGue_Q,2371
385
385
  reconcile/gql_definitions/ldap_groups/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -663,7 +663,7 @@ reconcile/utils/quay_mirror.py,sha256=dpWCNv5lITwIk6Q9RkmqaQKHNk_JPy27UQEribJ7E-
663
663
  reconcile/utils/raw_github_api.py,sha256=2WKtE8ABYYB9UGOAh9N_kLkksBWL3320Z2_scteZddI,2805
664
664
  reconcile/utils/repo_owners.py,sha256=P0QX6F0oB8wYA08yiyzhYUiBtU57iIK_PsxbzKENbKM,6571
665
665
  reconcile/utils/rest_api_base.py,sha256=MT7tp6CQO2S5aKfVOzw_hipWg7wAGoOqkm4qurI1hEU,4342
666
- reconcile/utils/rhcsv2_certs.py,sha256=nS0NJGI7pzEvVd0F84_KQ9hsxmslz-Db7Y2Pt-1E0x8,2248
666
+ reconcile/utils/rhcsv2_certs.py,sha256=ZnlUlEI2k6UrljGarkm1ey0znMlQtjeZB7VEfCH1A64,2545
667
667
  reconcile/utils/ruamel.py,sha256=FzL4_L0FnMOUZmgThrZSMJs5MTdXwiy-E9MZWfk8bh8,397
668
668
  reconcile/utils/secret_reader.py,sha256=MaP56KZaAE35EyYbgAitdm6fUSxdzWeGFSOym9qiZkw,10206
669
669
  reconcile/utils/semver_helper.py,sha256=-WfPOMSA2v1h7hT3PwVf-Htg7wOsoKlQC1JdmDX2Ars,1268
@@ -815,7 +815,7 @@ tools/saas_promotion_state/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
815
815
  tools/saas_promotion_state/saas_promotion_state.py,sha256=UfwwRLS5Ya4_Nh1w5n1dvoYtchQvYE9yj1VANt2IKqI,3925
816
816
  tools/sre_checkpoints/__init__.py,sha256=CDaDaywJnmRCLyl_NCcvxi-Zc0hTi_3OdwKiFOyS39I,145
817
817
  tools/sre_checkpoints/util.py,sha256=zEDbGr18ZeHNQwW8pUsr2JRjuXIPz--WAGJxZo9sv_Y,894
818
- qontract_reconcile-0.10.2.dev204.dist-info/METADATA,sha256=oPtlkzclWzhdxuM8i4TJB0ykd-vcRwVOk2orPS4I_Zw,24555
819
- qontract_reconcile-0.10.2.dev204.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
820
- qontract_reconcile-0.10.2.dev204.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
821
- qontract_reconcile-0.10.2.dev204.dist-info/RECORD,,
818
+ qontract_reconcile-0.10.2.dev206.dist-info/METADATA,sha256=zOwPXiy61ZEizyYOaozdJ2Pp9IWFIAAUG3nzGRDetTo,24555
819
+ qontract_reconcile-0.10.2.dev206.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
820
+ qontract_reconcile-0.10.2.dev206.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
821
+ qontract_reconcile-0.10.2.dev206.dist-info/RECORD,,
@@ -160,9 +160,7 @@ class GlitchtipProjectAlertsIntegration(
160
160
  continue
161
161
  params = {
162
162
  "labels": alert_labels + (channels.jira_labels or []),
163
- "components": [channels.jira_component]
164
- if channels.jira_component
165
- else [],
163
+ "components": channels.jira_components or [],
166
164
  } | token_params
167
165
  if board.issue_type:
168
166
  params["issue_type"] = board.issue_type
@@ -22,8 +22,9 @@ DEFINITION = """
22
22
  query RhcsProviderSettings {
23
23
  settings: app_interface_settings_v1 {
24
24
  rhcsProvider {
25
- url
25
+ issuerUrl
26
26
  vaultBasePath
27
+ caCertUrl
27
28
  }
28
29
  }
29
30
  }
@@ -37,8 +38,9 @@ class ConfiguredBaseModel(BaseModel):
37
38
 
38
39
 
39
40
  class RhcsProviderSettingsV1(ConfiguredBaseModel):
40
- url: str = Field(..., alias="url")
41
+ issuer_url: str = Field(..., alias="issuerUrl")
41
42
  vault_base_path: str = Field(..., alias="vaultBasePath")
43
+ ca_cert_url: str = Field(..., alias="caCertUrl")
42
44
 
43
45
 
44
46
  class AppInterfaceSettingsV1(ConfiguredBaseModel):
@@ -68,7 +68,7 @@ query GlitchtipProjectsWithAlerts {
68
68
  integrations
69
69
  }
70
70
  }
71
- jiraComponent
71
+ jiraComponents
72
72
  jiraLabels
73
73
  }
74
74
  }
@@ -127,7 +127,7 @@ class JiraBoardV1(ConfiguredBaseModel):
127
127
 
128
128
  class AppEscalationPolicyChannelsV1(ConfiguredBaseModel):
129
129
  jira_board: list[JiraBoardV1] = Field(..., alias="jiraBoard")
130
- jira_component: Optional[str] = Field(..., alias="jiraComponent")
130
+ jira_components: Optional[list[str]] = Field(..., alias="jiraComponents")
131
131
  jira_labels: Optional[list[str]] = Field(..., alias="jiraLabels")
132
132
 
133
133
 
@@ -18360,13 +18360,21 @@
18360
18360
  "deprecationReason": null
18361
18361
  },
18362
18362
  {
18363
- "name": "jiraComponent",
18363
+ "name": "jiraComponents",
18364
18364
  "description": null,
18365
18365
  "args": [],
18366
18366
  "type": {
18367
- "kind": "SCALAR",
18368
- "name": "String",
18369
- "ofType": null
18367
+ "kind": "LIST",
18368
+ "name": null,
18369
+ "ofType": {
18370
+ "kind": "NON_NULL",
18371
+ "name": null,
18372
+ "ofType": {
18373
+ "kind": "SCALAR",
18374
+ "name": "String",
18375
+ "ofType": null
18376
+ }
18377
+ }
18370
18378
  },
18371
18379
  "isDeprecated": false,
18372
18380
  "deprecationReason": null
@@ -26581,7 +26589,7 @@
26581
26589
  "description": null,
26582
26590
  "fields": [
26583
26591
  {
26584
- "name": "url",
26592
+ "name": "issuerUrl",
26585
26593
  "description": null,
26586
26594
  "args": [],
26587
26595
  "type": {
@@ -26611,6 +26619,22 @@
26611
26619
  },
26612
26620
  "isDeprecated": false,
26613
26621
  "deprecationReason": null
26622
+ },
26623
+ {
26624
+ "name": "caCertUrl",
26625
+ "description": null,
26626
+ "args": [],
26627
+ "type": {
26628
+ "kind": "NON_NULL",
26629
+ "name": null,
26630
+ "ofType": {
26631
+ "kind": "SCALAR",
26632
+ "name": "String",
26633
+ "ofType": null
26634
+ }
26635
+ },
26636
+ "isDeprecated": false,
26637
+ "deprecationReason": null
26614
26638
  }
26615
26639
  ],
26616
26640
  "inputFields": null,
@@ -54,7 +54,7 @@ query JiraBoardsForPermissionValidation {
54
54
  escalationPolicies {
55
55
  name
56
56
  channels {
57
- jiraComponent
57
+ jiraComponents
58
58
  }
59
59
  }
60
60
  disable {
@@ -91,7 +91,7 @@ class JiraSeverityPriorityMappingsV1(ConfiguredBaseModel):
91
91
 
92
92
 
93
93
  class AppEscalationPolicyChannelsV1(ConfiguredBaseModel):
94
- jira_component: Optional[str] = Field(..., alias="jiraComponent")
94
+ jira_components: Optional[list[str]] = Field(..., alias="jiraComponents")
95
95
 
96
96
 
97
97
  class AppEscalationPolicyV1(ConfiguredBaseModel):
@@ -105,13 +105,13 @@ def board_is_valid(
105
105
 
106
106
  components = jira.components()
107
107
  for escalation_policy in board.escalation_policies or []:
108
- jira_component = escalation_policy.channels.jira_component
109
- if jira_component and jira_component not in components:
110
- logging.error(
111
- f"[{board.name}] escalation policy '{escalation_policy.name}' references a non existing Jira component "
112
- f"'{jira_component}'. Valid components: {components}"
113
- )
114
- error |= ValidationError.INVALID_COMPONENT
108
+ for jira_component in escalation_policy.channels.jira_components or []:
109
+ if jira_component not in components:
110
+ logging.error(
111
+ f"[{board.name}] escalation policy '{escalation_policy.name}' references a non existing Jira component "
112
+ f"'{jira_component}'. Valid components: {components}"
113
+ )
114
+ error |= ValidationError.INVALID_COMPONENT
115
115
 
116
116
  issue_type = board.issue_type or default_issue_type
117
117
  project_issue_type = jira.get_issue_type(issue_type)
@@ -6,6 +6,9 @@ from typing import Any
6
6
 
7
7
  import reconcile.openshift_base as ob
8
8
  import reconcile.openshift_resources_base as orb
9
+ from reconcile.gql_definitions.common.rhcs_provider_settings import (
10
+ RhcsProviderSettingsV1,
11
+ )
9
12
  from reconcile.gql_definitions.rhcs.certs import (
10
13
  NamespaceOpenshiftResourceRhcsCertV1,
11
14
  NamespaceV1,
@@ -13,6 +16,7 @@ from reconcile.gql_definitions.rhcs.certs import (
13
16
  from reconcile.gql_definitions.rhcs.certs import (
14
17
  query as rhcs_certs_query,
15
18
  )
19
+ from reconcile.status import ExitCodes
16
20
  from reconcile.typed_queries.app_interface_vault_settings import (
17
21
  get_app_interface_vault_settings,
18
22
  )
@@ -82,7 +86,7 @@ def construct_rhcs_cert_oc_secret(
82
86
  body: dict[str, Any] = {
83
87
  "apiVersion": "v1",
84
88
  "kind": "Secret",
85
- "type": "Opaque",
89
+ "type": "kubernetes.io/tls",
86
90
  "metadata": {"name": secret_name, "annotations": annotations},
87
91
  }
88
92
  for k, v in cert.items():
@@ -120,7 +124,7 @@ def get_vault_cert_secret(
120
124
  })
121
125
  except SecretNotFound:
122
126
  logging.info(
123
- f"No existing cert found for cluster='{ns.cluster.name}', namespace='{ns.name}', secret='{cert_resource.secret_name}', threshold='{cert_resource.auto_renew_threshold_days} days'"
127
+ f"No existing cert found for cluster='{ns.cluster.name}', namespace='{ns.name}', secret='{cert_resource.secret_name}''"
124
128
  )
125
129
  return vault_cert_secret
126
130
 
@@ -131,7 +135,8 @@ def generate_vault_cert_secret(
131
135
  cert_resource: NamespaceOpenshiftResourceRhcsCertV1,
132
136
  vault: _VaultClient,
133
137
  vault_base_path: str,
134
- cert_provider_url: str,
138
+ issuer_url: str,
139
+ ca_cert_url: str,
135
140
  ) -> dict:
136
141
  logging.info(
137
142
  f"Creating cert with service account credentials for '{cert_resource.service_account_name}'. cluster='{ns.cluster.name}', namespace='{ns.name}', secret='{cert_resource.secret_name}'"
@@ -141,14 +146,13 @@ def generate_vault_cert_secret(
141
146
  rhcs_cert = RhcsV2Cert(
142
147
  certificate="PLACEHOLDER_CERT",
143
148
  private_key="PLACEHOLDER_PRIVATE_KEY",
149
+ ca_cert="PLACEHOLDER_CA_CERT",
144
150
  expiration_timestamp=int(time.time()),
145
151
  )
146
152
  else:
147
153
  try:
148
154
  rhcs_cert = generate_cert(
149
- cert_provider_url,
150
- cert_resource.service_account_name,
151
- sa_password,
155
+ issuer_url, cert_resource.service_account_name, sa_password, ca_cert_url
152
156
  )
153
157
  except ValueError as e:
154
158
  raise Exception(
@@ -159,12 +163,12 @@ def generate_vault_cert_secret(
159
163
  )
160
164
  vault.write(
161
165
  secret={
162
- "data": rhcs_cert.dict(),
166
+ "data": rhcs_cert.dict(by_alias=True),
163
167
  "path": f"{vault_base_path}/{ns.cluster.name}/{ns.name}/{cert_resource.secret_name}",
164
168
  },
165
169
  decode_base64=False,
166
170
  )
167
- return rhcs_cert.dict()
171
+ return rhcs_cert.dict(by_alias=True)
168
172
 
169
173
 
170
174
  def fetch_openshift_resource_for_cert_resource(
@@ -172,15 +176,21 @@ def fetch_openshift_resource_for_cert_resource(
172
176
  ns: NamespaceV1,
173
177
  cert_resource: NamespaceOpenshiftResourceRhcsCertV1,
174
178
  vault: _VaultClient,
175
- vault_base_path: str,
176
- cert_provider_url: str,
179
+ rhcs_settings: RhcsProviderSettingsV1,
177
180
  ) -> OR:
181
+ vault_base_path = f"{rhcs_settings.vault_base_path}/{QONTRACT_INTEGRATION}"
178
182
  vault_cert_secret = get_vault_cert_secret(ns, cert_resource, vault, vault_base_path)
179
183
  if vault_cert_secret is None or cert_expires_within_threshold(
180
184
  ns, cert_resource, vault_cert_secret
181
185
  ):
182
186
  vault_cert_secret = generate_vault_cert_secret(
183
- dry_run, ns, cert_resource, vault, vault_base_path, cert_provider_url
187
+ dry_run,
188
+ ns,
189
+ cert_resource,
190
+ vault,
191
+ vault_base_path,
192
+ rhcs_settings.issuer_url,
193
+ rhcs_settings.ca_cert_url,
184
194
  )
185
195
 
186
196
  if not dry_run:
@@ -220,8 +230,7 @@ def fetch_desired_state(
220
230
  ns,
221
231
  cert_resource,
222
232
  vault,
223
- f"{cert_provider.vault_base_path}/{QONTRACT_INTEGRATION}",
224
- cert_provider.url,
233
+ cert_provider,
225
234
  ),
226
235
  )
227
236
 
@@ -237,6 +246,11 @@ def run(
237
246
  vault_settings = get_app_interface_vault_settings()
238
247
  secret_reader = create_secret_reader(use_vault=vault_settings.vault)
239
248
  namespaces = get_namespaces_with_rhcs_certs(gql_api.query, cluster_name)
249
+ if not namespaces:
250
+ logging.debug(
251
+ f"No rhcs-cert definitions found in app-interface for {cluster_name}"
252
+ )
253
+ sys.exit(ExitCodes.SUCCESS)
240
254
  oc_map = init_oc_map_from_namespaces(
241
255
  namespaces=namespaces,
242
256
  integration=QONTRACT_INTEGRATION,
@@ -6,16 +6,20 @@ from cryptography import x509
6
6
  from cryptography.hazmat.primitives import hashes, serialization
7
7
  from cryptography.hazmat.primitives.asymmetric import rsa
8
8
  from cryptography.x509.oid import NameOID
9
- from pydantic import BaseModel
9
+ from pydantic import BaseModel, Field
10
10
 
11
11
 
12
12
  class RhcsV2Cert(BaseModel):
13
- certificate: str
14
- private_key: str
13
+ certificate: str = Field(alias="tls.crt")
14
+ private_key: str = Field(alias="tls.key")
15
+ ca_cert: str = Field(alias="ca.crt")
15
16
  expiration_timestamp: int
16
17
 
18
+ class Config:
19
+ allow_population_by_field_name = True
17
20
 
18
- def generate_cert(url: str, uid: str, pwd: str) -> RhcsV2Cert:
21
+
22
+ def generate_cert(issuer_url: str, uid: str, pwd: str, ca_url: str) -> RhcsV2Cert:
19
23
  private_key = rsa.generate_private_key(65537, 4096)
20
24
  csr = (
21
25
  x509.CertificateSigningRequestBuilder()
@@ -35,8 +39,9 @@ def generate_cert(url: str, uid: str, pwd: str) -> RhcsV2Cert:
35
39
  "renewal": "false",
36
40
  "xmlOutput": "false",
37
41
  }
38
- response = requests.post(url, data=data, verify=False)
42
+ response = requests.post(issuer_url, data=data)
39
43
  response.raise_for_status()
44
+
40
45
  cert_pem = re.search(
41
46
  r'outputList\.outputVal="(-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----(?:\\n|\r?\n)?)";',
42
47
  response.text,
@@ -56,11 +61,16 @@ def generate_cert(url: str, uid: str, pwd: str) -> RhcsV2Cert:
56
61
  encryption_algorithm=serialization.NoEncryption(),
57
62
  ).decode()
58
63
 
64
+ response = requests.get(ca_url)
65
+ response.raise_for_status()
66
+ ca_pem = response.text
67
+
59
68
  return RhcsV2Cert(
60
69
  private_key=private_key_pem,
61
70
  certificate=cert_pem.group(1)
62
71
  .encode()
63
72
  .decode("unicode_escape")
64
73
  .replace("\\/", "/"),
74
+ ca_cert=ca_pem,
65
75
  expiration_timestamp=int(dt_expiry.timestamp()),
66
76
  )