Skip to content

Commit ea08bb1

Browse files
authored
Remove Kyverno dependency (#71)
1 parent 9b22cc6 commit ea08bb1

File tree

8 files changed

+308
-126
lines changed

8 files changed

+308
-126
lines changed

class/defaults.yml

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
parameters:
22
openshift4_console:
3+
images:
4+
oc:
5+
registry: quay.io
6+
repository: appuio/oc
7+
tag: v4.15
8+
39
namespace: openshift-console
410
namespace_annotations:
511
openshift.io/node-selector: ''

component/main.jsonnet

-44
Original file line numberDiff line numberDiff line change
@@ -172,48 +172,6 @@ local consoleRoutePatch =
172172

173173
local tls = import 'tls.libsonnet';
174174

175-
// If we deploy cert-manager Certificates, we annotate namespace
176-
// openshift-config with the `kyvernoAnnotation` defined in `tls.libsonnet`
177-
// through a ResourceLocker patch. This triggers the the Kyverno policy to
178-
// copy the cert-manager TLS secrets into namespace openshift-config.
179-
//
180-
// We add the ResourceLocker patch to ArgoCD sync-wave 5, so it's guaranteed
181-
// to be applied in the cluster after the certificate has been issued and
182-
// before the custom openshift console route config is applied.
183-
//
184-
// NOTE: Due to the current implementation of the resource locker component
185-
// library this prevents other components from also providing ResourceLocker
186-
// patches for the `openshift-config` namespace.
187-
local openshiftConfigNsAnnotationPatch =
188-
local needsPatch = hostname != null && std.length(tls.certs) > 0;
189-
if needsPatch then
190-
local target = kube.Namespace('openshift-config');
191-
local patch = {
192-
metadata: {
193-
annotations: tls.kyvernoAnnotation,
194-
},
195-
};
196-
[
197-
if obj.kind == 'Patch' then
198-
obj {
199-
metadata+: {
200-
annotations+: {
201-
// Annotate namespace openshift-config before we configure the
202-
// route certificate, see patch above
203-
'argocd.argoproj.io/sync-wave': '5',
204-
},
205-
},
206-
}
207-
else
208-
obj
209-
for obj in
210-
po.Patch(
211-
target,
212-
patch,
213-
patchstrategy='application/merge-patch+json'
214-
)
215-
];
216-
217175
{
218176
'00_namespace': kube.Namespace(params.namespace) {
219177
metadata+: {
@@ -247,6 +205,4 @@ local openshiftConfigNsAnnotationPatch =
247205
faviconRoute,
248206
[if consoleRoutePatch != null then '20_ingress_config_patch']:
249207
consoleRoutePatch,
250-
[if openshiftConfigNsAnnotationPatch != null then '20_openshift_config_ns_annotation_patch']:
251-
openshiftConfigNsAnnotationPatch,
252208
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
test -n "${SECRET_NAME:-}" || (echo "SECRET_NAME is required" && exit 1)
5+
6+
source_namespace="openshift-console"
7+
target_namespace="openshift-config"
8+
9+
# # Wait for the secret to be created before trying to get it.
10+
# # TODO: --for=create is included with OCP 4.17
11+
# kubectl -n "${source_namespace}" wait secret "${SECRET_NAME}" --for=create --timeout=30m
12+
echo "Waiting for secret ${SECRET_NAME} to be created"
13+
while test -z "$(kubectl -n "${source_namespace}" get secret "${SECRET_NAME}" --ignore-not-found -oname)" ; do
14+
printf "."
15+
sleep 1
16+
done
17+
printf "\n"
18+
19+
# When using -w flag kubectl returns the secret once on startup and then again when it changes.
20+
kubectl -n "${source_namespace}" get secret "${SECRET_NAME}" -ojson -w | jq -c --unbuffered | while read -r secret ; do
21+
echo "Syncing secret: $(printf "%s" "$secret" | jq -r '.metadata.name')"
22+
23+
kubectl -n "$target_namespace" apply --server-side -f <(printf "%s" "$secret" | jq '{"apiVersion": .apiVersion, "kind": .kind, "metadata": {"name": .metadata.name}, "type": .type, "data": .data}')
24+
done

component/tls.libsonnet

+120-33
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ local cm = import 'lib/cert-manager.libsonnet';
22
local com = import 'lib/commodore.libjsonnet';
33
local kap = import 'lib/kapitan.libjsonnet';
44
local kube = import 'lib/kube.libjsonnet';
5-
local kyverno = import 'lib/kyverno.libsonnet';
65

76
local inv = kap.inventory();
87
local params = inv.parameters.openshift4_console;
@@ -36,52 +35,141 @@ local secrets = std.filter(
3635
]
3736
);
3837

39-
local kyvernoAnnotation = {
40-
'syn.tools/openshift4-console': 'secret-target-namespace',
41-
};
42-
4338
local makeCert(c, cert) =
44-
assert
45-
std.member(inv.applications, 'kyverno') :
46-
'You need to add component `kyverno` to the cluster to be able to deploy cert-manager Certificate resources for the the openshift web console.';
39+
local sa = kube.ServiceAccount('openshift4-console-sync-' + c) {
40+
metadata+: {
41+
namespace: params.namespace,
42+
},
43+
};
44+
local sourceNsRole = kube.Role('openshift4-console-sync-' + c) {
45+
metadata+: {
46+
namespace: params.namespace,
47+
},
48+
rules: [
49+
{
50+
apiGroups: [ '' ],
51+
resources: [ 'secrets' ],
52+
verbs: [ 'get', 'list', 'watch' ],
53+
},
54+
],
55+
};
56+
local targetNsRole = kube.Role('openshift4-console-sync-' + c) {
57+
metadata+: {
58+
namespace: 'openshift-config',
59+
},
60+
rules: [
61+
{
62+
apiGroups: [ '' ],
63+
resources: [ 'secrets' ],
64+
verbs: [ 'get', 'update', 'patch' ],
65+
},
66+
],
67+
};
68+
4769
[
4870
cm.cert(c) {
4971
metadata+: {
5072
// Certificate must be deployed in the same namespace as the web
5173
// console, otherwise OpenShift won't admit the HTTP01 solver route.
52-
// We copy the resulting secret to namespace 'openshift-config' with
53-
// Kyverno, see below.
74+
// We copy the resulting secret to namespace 'openshift-config', see below.
5475
namespace: params.namespace,
5576
},
5677
spec+: {
5778
secretName: '%s' % c,
5879
},
5980
} + com.makeMergeable(cert),
60-
kyverno.ClusterPolicy('openshift4-console-sync-' + c) {
61-
spec: {
62-
rules: [
63-
{
64-
name: 'Sync "%s" certificate secret to openshift-config' % c,
65-
match: {
66-
resources: {
67-
kinds: [ 'Namespace' ],
68-
// We copy the created TLS secret into all namespaces which
69-
// have the annotation specified in `kyvernoAnnotation`.
70-
annotations: kyvernoAnnotation,
71-
},
81+
kube.ConfigMap('openshift4-console-sync-' + c) {
82+
metadata+: {
83+
namespace: params.namespace,
84+
},
85+
data: {
86+
'reconcile-console-secret.sh': (importstr 'scripts/reconcile-console-secret.sh'),
87+
},
88+
},
89+
sa,
90+
sourceNsRole,
91+
targetNsRole,
92+
kube.RoleBinding('openshift4-console-sync-' + c) {
93+
metadata+: {
94+
namespace: sourceNsRole.metadata.namespace,
95+
},
96+
subjects_: [ sa ],
97+
roleRef_: sourceNsRole,
98+
},
99+
kube.RoleBinding('openshift4-console-sync-' + c) {
100+
metadata+: {
101+
namespace: targetNsRole.metadata.namespace,
102+
},
103+
subjects_: [ sa ],
104+
roleRef_: targetNsRole,
105+
},
106+
kube.Deployment('openshift4-console-sync-' + c) {
107+
metadata+: {
108+
namespace: params.namespace,
109+
},
110+
spec+: {
111+
strategy: {
112+
type: 'Recreate',
113+
},
114+
replicas: 1,
115+
selector: {
116+
matchLabels: {
117+
app: 'openshift4-console-sync-' + c,
118+
},
119+
},
120+
template+: {
121+
metadata: {
122+
labels: {
123+
app: 'openshift4-console-sync-' + c,
72124
},
73-
generate: {
74-
kind: 'Secret',
75-
name: c,
76-
namespace: '{{request.object.metadata.name}}',
77-
synchronize: true,
78-
clone: {
79-
namespace: params.namespace,
80-
name: c,
125+
},
126+
spec+: {
127+
serviceAccountName: 'openshift4-console-sync-' + c,
128+
containers: [
129+
{
130+
name: 'sync',
131+
image: '%(registry)s/%(repository)s:%(tag)s' % params.images.oc,
132+
workingDir: '/export',
133+
env: [
134+
{
135+
name: 'SECRET_NAME',
136+
value: c,
137+
},
138+
{
139+
name: 'HOME',
140+
value: '/export',
141+
},
142+
],
143+
command: [
144+
'/scripts/reconcile-console-secret.sh',
145+
],
146+
volumeMounts: [
147+
{
148+
name: 'export',
149+
mountPath: '/export',
150+
},
151+
{
152+
name: 'scripts',
153+
mountPath: '/scripts',
154+
},
155+
],
81156
},
82-
},
157+
],
158+
volumes: [
159+
{
160+
name: 'scripts',
161+
configMap: {
162+
name: 'openshift4-console-sync-' + c,
163+
defaultMode: 365, // 365 = 0555
164+
},
165+
},
166+
{
167+
name: 'export',
168+
emptyDir: {},
169+
},
170+
],
83171
},
84-
],
172+
},
85173
},
86174
},
87175
];
@@ -104,5 +192,4 @@ local certs =
104192
{
105193
certs: certs,
106194
secrets: secrets,
107-
kyvernoAnnotation: kyvernoAnnotation,
108195
}

docs/modules/ROOT/pages/references/parameters.adoc

+1-2
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,7 @@ The dictionary values are then directly directly merged into the mostly empty `C
169169
OpenShift won't admit the route for the HTTP01 solver pod unless the `Certificate` resources are deployed in the same namespace as the web console.
170170
This behavior is caused by a security feature in the OpenShift ingress controller operator to not allow malicious actors to abuse hostnames which are already in use in other namespaces.
171171

172-
However, since OpenShift requires that custom TLS secrets for the OpenShift console are stored in namespace `openshift-config`, we deploy a Kyverno policy to clone the TLS secret created by cert-manager into namespace `openshift-config` for each `Certificate` resource.
173-
Because of that, the component requires that Kyverno is installed on the cluster via the https://hub.syn.tools/kyverno/[Commodore component `kyverno`], when `Certificate` resources are configured in the hierarchy.
172+
However, since OpenShift requires that custom TLS secrets for the OpenShift console are stored in namespace `openshift-config`, we deploy a script to clone the TLS secret created by cert-manager into namespace `openshift-config` for each `Certificate` resource.
174173

175174

176175
== Example: Custom hostname in cluster's app domain

tests/custom-route-managed-tls.yml

-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
applications:
2-
- kyverno
31
parameters:
42
kapitan:
53
dependencies:
@@ -9,9 +7,6 @@ parameters:
97
- type: https
108
source: https://raw.githubusercontent.com/projectsyn/component-patch-operator/v1.2.0/lib/patch-operator.libsonnet
119
output_path: vendor/lib/patch-operator.libsonnet
12-
- type: https
13-
source: https://raw.githubusercontent.com/projectsyn/component-kyverno/v1.4.0/lib/kyverno.libsonnet
14-
output_path: vendor/lib/kyverno.libsonnet
1510

1611
patch_operator:
1712
patch_serviceaccount:

0 commit comments

Comments
 (0)