From 590e76d66d1909f2e847ebaa17ac848ee95b66e4 Mon Sep 17 00:00:00 2001 From: Engin Diri Date: Tue, 18 Jul 2023 10:33:49 +0200 Subject: [PATCH] Roles (#262) * feat: add role and clusterrole to chart Signed-off-by: Engin Diri * feat: add role and clusterrole to chart Signed-off-by: Engin Diri --------- Signed-off-by: Engin Diri --- charts/node-red/Chart.yaml | 4 +- charts/node-red/README.md | 9 +- charts/node-red/scripts/flow_refresh.py | 83 ++++++++++++------- charts/node-red/templates/certificates.yaml | 3 +- charts/node-red/templates/clusterrole.yaml | 20 +++++ .../templates/clusterrolebinding.yaml | 17 ++++ charts/node-red/templates/deployment.yaml | 5 +- charts/node-red/templates/ingress.yaml | 1 + charts/node-red/templates/npmrc-cm.yaml | 1 + charts/node-red/templates/pvc.yaml | 1 + charts/node-red/templates/role.yaml | 18 ++++ charts/node-red/templates/rolebinding.yaml | 15 ++++ charts/node-red/templates/service.yaml | 1 + charts/node-red/templates/serviceaccount.yaml | 1 + charts/node-red/templates/servicemonitor.yaml | 4 +- charts/node-red/templates/sidecar-cm.yaml | 1 + charts/node-red/values.yaml | 10 +++ 17 files changed, 158 insertions(+), 36 deletions(-) create mode 100644 charts/node-red/templates/clusterrole.yaml create mode 100644 charts/node-red/templates/clusterrolebinding.yaml create mode 100644 charts/node-red/templates/role.yaml create mode 100644 charts/node-red/templates/rolebinding.yaml diff --git a/charts/node-red/Chart.yaml b/charts/node-red/Chart.yaml index 8e1bca19..d781debc 100644 --- a/charts/node-red/Chart.yaml +++ b/charts/node-red/Chart.yaml @@ -9,7 +9,7 @@ icon: https://nodered.org/about/resources/media/node-red-icon-2.png type: application -version: 0.24.4 +version: 0.25.0 appVersion: 3.0.2 keywords: @@ -29,7 +29,7 @@ maintainers: annotations: artifacthub.io/containsSecurityUpdates: "false" artifacthub.io/changes: | - - add missing quotes to create valid yaml + - add role and clusterrole to chart artifacthub.io/images: | - name: node-red image: docker.io/nodered/node-red:3.0.2 diff --git a/charts/node-red/README.md b/charts/node-red/README.md index cb25ad06..d709d3b0 100644 --- a/charts/node-red/README.md +++ b/charts/node-red/README.md @@ -1,6 +1,6 @@ # node-red ⚙ -![Version: 0.24.4](https://img.shields.io/badge/Version-0.24.4-informational?style=for-the-badge) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=for-the-badge) ![AppVersion: 3.0.2](https://img.shields.io/badge/AppVersion-3.0.2-informational?style=for-the-badge) +![Version: 0.25.0](https://img.shields.io/badge/Version-0.25.0-informational?style=for-the-badge) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=for-the-badge) ![AppVersion: 3.0.2](https://img.shields.io/badge/AppVersion-3.0.2-informational?style=for-the-badge) [![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/node-red&style=for-the-badge)](https://artifacthub.io/packages/search?repo=node-red) [![SIT](https://img.shields.io/badge/SIT-awesome-blueviolet.svg?style=for-the-badge)](https://jobs.schwarz) @@ -16,7 +16,7 @@ A Helm chart for Node-Red, a low-code programming for event-driven applications To install the chart using the OCI artifact, run: ```bash -helm install node-red oci://ghcr.io/schwarzit/charts/node-red --version 0.24.4 +helm install node-red oci://ghcr.io/schwarzit/charts/node-red --version 0.25.0 ``` ## Usage @@ -32,7 +32,7 @@ helm repo update To install the chart with the release name node-red run: ```bash -helm install node-red node-red/node-red --version 0.24.4 +helm install node-red node-red/node-red --version 0.25.0 ``` After a few seconds, node-red should be running. @@ -61,6 +61,9 @@ The command removes all the Kubernetes components associated with the chart and | Key | Type | Default | Description | |-----|------|---------|-------------| | affinity | object | `{}` | The affinity constraint | +| clusterRoleRules.enabled | bool | `false` | Enable custom rules for the application controller's ClusterRole resource default: false | +| clusterRoleRules.rules | list | `[]` | List of custom rules for the application controller's ClusterRole resource default: [] | +| createClusterRole | bool | `false` | Create a ClusterRole resource for the node-red pod. default: false | | deploymentAnnotations | object | `{}` | Deployment annotations | | deploymentStrategy | string | `""` | Specifies the strategy used to replace old Pods by new ones, default: `RollingUpdate` | | env | list | `[]` | node-red env, see more environment variables in the [node-red documentation](https://nodered.org/docs/getting-started/docker) | diff --git a/charts/node-red/scripts/flow_refresh.py b/charts/node-red/scripts/flow_refresh.py index 1ba3536a..8b34349e 100644 --- a/charts/node-red/scripts/flow_refresh.py +++ b/charts/node-red/scripts/flow_refresh.py @@ -10,7 +10,8 @@ import re # SET VARIABLES FROM CONTAINER ENVIRONMENT -SLEEP_TIME_SIDECAR = 5 if os.getenv("SLEEP_TIME_SIDECAR") is None else int(re.sub("[A-z]", "", os.getenv("SLEEP_TIME_SIDECAR"))) +SLEEP_TIME_SIDECAR = 5 if os.getenv("SLEEP_TIME_SIDECAR") is None else int( + re.sub("[A-z]", "", os.getenv("SLEEP_TIME_SIDECAR"))) USERNAME = os.getenv("USERNAME") PASSWORD = os.getenv("PASSWORD") URL = os.getenv("URL") @@ -18,13 +19,16 @@ FLOW_REQ_RETRY_TOTAL = 20 if os.getenv("REQ_RETRY_TOTAL") is None else int(os.getenv("REQ_RETRY_TOTAL")) FLOW_REQ_RETRY_CONNECT = 30 if os.getenv("REQ_RETRY_CONNECT") is None else int(os.getenv("REQ_RETRY_CONNECT")) FLOW_REQ_RETRY_READ = 15 if os.getenv("REQ_RETRY_READ") is None else int(os.getenv("REQ_RETRY_READ")) -FLOW_REQ_RETRY_BACKOFF_FACTOR = 1.1 if os.getenv("REQ_RETRY_BACKOFF_FACTOR") is None else float(os.getenv("REQ_RETRY_BACKOFF_FACTOR")) +FLOW_REQ_RETRY_BACKOFF_FACTOR = 1.1 if os.getenv("REQ_RETRY_BACKOFF_FACTOR") is None else float( + os.getenv("REQ_RETRY_BACKOFF_FACTOR")) FLOW_REQ_TIMEOUT = 60 if os.getenv("REQ_TIMEOUT") is None else float(os.getenv("REQ_TIMEOUT")) FLOW_REQ_TLS_VERIFY = False if os.getenv("REQ_SKIP_TLS_VERIFY") == "true" else None -EXTRA_NODE_MODULES = None if os.path.isfile('/data/extra-node-modules.json') is False else json.load((open('/data/extra-node-modules.json', "r"))) +EXTRA_NODE_MODULES = None if os.path.isfile('/data/extra-node-modules.json') is False else json.load( + (open('/data/extra-node-modules.json', "r"))) script_errors = {} + def main(): print("----START PYTHON SIDECAR SCRIPT----") print("node-red node module install and flow refresh api call via k8s-sidecar") @@ -42,27 +46,43 @@ def main(): r.mount("http://", HTTPAdapter(max_retries=retries)) r.mount("https://", HTTPAdapter(max_retries=retries)) - # GET NODE RED BEARER TOKEN - print("----TOKEN----") - payload_token = { - "client_id": "node-red-admin", - "grant_type": "password", - "scope": "*", - "username": USERNAME, - "password": PASSWORD, - } - r_token = r.post( - "%s" % URL + "/auth/token", - data=payload_token, - timeout=FLOW_REQ_TIMEOUT, - verify=FLOW_REQ_TLS_VERIFY, + # Make the request + authenticationScheme = r.get( + "%s" % URL + "/auth/login", ) - if r_token.status_code == requests.codes.ok: - print(f"node-red bearer token successfully created - {r_token.status_code}") - token = json.loads(r_token.text)["access_token"] + + try: + data = authenticationScheme.json() + except json.JSONDecodeError: + print("Received non-JSON response.") + sys.exit(1) + + # Check if the data is an empty object + if data == {}: + print("Empty authentication scheme response.") + token = None else: - print(f"could not create bearer token.... {r_token.status_code}") - sys.exit(r_token.status_code) + # GET NODE RED BEARER TOKEN + print("----TOKEN----") + payload_token = { + "client_id": "node-red-admin", + "grant_type": "password", + "scope": "*", + "username": USERNAME, + "password": PASSWORD, + } + r_token = r.post( + "%s" % URL + "/auth/token", + data=payload_token, + timeout=FLOW_REQ_TIMEOUT, + verify=FLOW_REQ_TLS_VERIFY, + ) + if r_token.status_code == requests.codes.ok: + print(f"node-red bearer token successfully created - {r_token.status_code}") + token = json.loads(r_token.text)["access_token"] + else: + print(f"could not create bearer token.... {r_token.status_code}") + sys.exit(r_token.status_code) # NODE MODULE INSTALL VIA HELM SIDECAR EXTRA NODE MODULES CONFIG MAP print("----INSTALL EXTRA NODE MODULES----") @@ -70,9 +90,11 @@ def main(): print(f"found extra node modules in configmap - {EXTRA_NODE_MODULES}") # GET ISNTALLED NODE MODULES headers_node_module = { - "Authorization": "Bearer" + " " + token, "Accept": "application/json", } + if token: + # If token has a value, add Authorization to headers + headers_node_module["Authorization"] = "Bearer" + " " + token r_node_modules = r.get( "%s" % URL + "/nodes", headers=headers_node_module, @@ -88,9 +110,11 @@ def main(): if module not in modules_installed: payload_node_module = '{"module": "' + module + '"}' headers_node_module = { - "Authorization": "Bearer" + " " + token, "Content-type": "application/json", } + if token: + # If token has a value, add Authorization to headers + headers_node_module["Authorization"] = "Bearer" + " " + token # INSTALL NODE MODULES FROM ITERATION r_node_modules = r.post( "%s" % URL + "/nodes", @@ -115,11 +139,13 @@ def main(): print("----RELOAD FLOWS----") payload_flow_refresh = '{"flows": [{"type": "tab"}]}' headers_flow_refresh = { - "Authorization": "Bearer" + " " + token, "content-type": "application/json; charset=utf-8", "Node-RED-Deployment-Type": "reload", "Node-RED-API-Version": "v2", } + if token: + # If token has a value, add Authorization to headers + headers_flow_refresh["Authorization"] = "Bearer" + " " + token r_flow_refresh = r.post( "%s" % URL + "/flows", @@ -140,10 +166,11 @@ def main(): print("----SCRIPT EXIT----") if script_errors: print(json.dumps(script_errors, indent=4)) - sys.exit("script error") + sys.exit("script errors found...") else: - print("yeah right") + print("no script errors found...") sys.exit(0) + if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/charts/node-red/templates/certificates.yaml b/charts/node-red/templates/certificates.yaml index 8e083448..45202567 100644 --- a/charts/node-red/templates/certificates.yaml +++ b/charts/node-red/templates/certificates.yaml @@ -5,6 +5,7 @@ apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: {{ $value.certificate.name | default (printf "%s-%d" $name $index) | trunc 63 | trimSuffix "-" }} + namespace: {{ .Release.Namespace | quote }} spec: commonName: {{ index $value.hosts 0 }} dnsNames: @@ -14,4 +15,4 @@ spec: secretName: {{ $value.secretName }} --- {{- end }} -{{- end }} \ No newline at end of file +{{- end }} diff --git a/charts/node-red/templates/clusterrole.yaml b/charts/node-red/templates/clusterrole.yaml new file mode 100644 index 00000000..46f1c81f --- /dev/null +++ b/charts/node-red/templates/clusterrole.yaml @@ -0,0 +1,20 @@ +{{- if .Values.createClusterRole }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "node-red.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "node-red.labels" . | nindent 4 }} +rules: + {{- if .Values.clusterRoleRules.enabled }} + {{- toYaml .Values.clusterRoleRules.rules | nindent 2 }} + {{- else }} + - apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' + {{- end }} +{{- end }} diff --git a/charts/node-red/templates/clusterrolebinding.yaml b/charts/node-red/templates/clusterrolebinding.yaml new file mode 100644 index 00000000..7c65f8b9 --- /dev/null +++ b/charts/node-red/templates/clusterrolebinding.yaml @@ -0,0 +1,17 @@ +{{- if .Values.createClusterRole }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "node-red.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "node-red.labels" . | nindent 4 }} +subjects: + - kind: ServiceAccount + name: {{ include "node-red.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} +roleRef: + kind: ClusterRole + name: {{ include "node-red.fullname" . }} + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/charts/node-red/templates/deployment.yaml b/charts/node-red/templates/deployment.yaml index 01d20911..3f268dee 100644 --- a/charts/node-red/templates/deployment.yaml +++ b/charts/node-red/templates/deployment.yaml @@ -6,6 +6,7 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} name: {{ include "node-red.fullname" . }} + namespace: {{ .Release.Namespace | quote }} labels: {{- include "node-red.labels" . | nindent 4 }} spec: @@ -69,8 +70,10 @@ spec: {{- end }} - name: URL value: {{ printf "http://%s.%s.svc.cluster.local:%d" (include "node-red.fullname" .) .Release.Namespace (.Values.service.port | int) }} + {{ if .Values.sidecar.env.username }} - name: USERNAME - value: {{ required "please set the username for API refresh call" .Values.sidecar.env.username }} + value: {{ .Values.sidecar.env.username }} + {{- end }} {{- if or .Values.sidecar.env.password .Values.sidecar.env.passwordFromExistingSecret }} - name: PASSWORD {{- if .Values.sidecar.env.password }} diff --git a/charts/node-red/templates/ingress.yaml b/charts/node-red/templates/ingress.yaml index c657a287..90862642 100644 --- a/charts/node-red/templates/ingress.yaml +++ b/charts/node-red/templates/ingress.yaml @@ -16,6 +16,7 @@ apiVersion: extensions/v1beta1 kind: Ingress metadata: name: {{ $fullName }} + namespace: {{ .Release.Namespace | quote }} labels: {{- include "node-red.labels" . | nindent 4 }} {{- with .Values.ingress.annotations }} diff --git a/charts/node-red/templates/npmrc-cm.yaml b/charts/node-red/templates/npmrc-cm.yaml index 1a2cc0d6..4285b376 100644 --- a/charts/node-red/templates/npmrc-cm.yaml +++ b/charts/node-red/templates/npmrc-cm.yaml @@ -3,6 +3,7 @@ apiVersion: v1 kind: ConfigMap metadata: name: {{ include "node-red.configMapName" . }} + namespace: {{ .Release.Namespace | quote }} data: npmrc: | {{- if .Values.npmrc.registry }} diff --git a/charts/node-red/templates/pvc.yaml b/charts/node-red/templates/pvc.yaml index 9f0274a4..f61cac45 100644 --- a/charts/node-red/templates/pvc.yaml +++ b/charts/node-red/templates/pvc.yaml @@ -3,6 +3,7 @@ kind: PersistentVolumeClaim apiVersion: v1 metadata: name: {{ template "node-red.fullname" . }} + namespace: {{ .Release.Namespace | quote }} labels: app.kubernetes.io/name: {{ include "node-red.name" . }} helm.sh/chart: {{ include "node-red.chart" . }} diff --git a/charts/node-red/templates/role.yaml b/charts/node-red/templates/role.yaml new file mode 100644 index 00000000..605d053a --- /dev/null +++ b/charts/node-red/templates/role.yaml @@ -0,0 +1,18 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ template "node-red.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "node-red.labels" . | nindent 4 }} +rules: + - apiGroups: + - "" + resources: + - secrets + - configmaps + - services + verbs: + - get + - list + - watch diff --git a/charts/node-red/templates/rolebinding.yaml b/charts/node-red/templates/rolebinding.yaml new file mode 100644 index 00000000..f77542f7 --- /dev/null +++ b/charts/node-red/templates/rolebinding.yaml @@ -0,0 +1,15 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ template "node-red.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "node-red.labels" . | nindent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ template "node-red.fullname" . }} +subjects: + - kind: ServiceAccount + name: {{ include "node-red.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} diff --git a/charts/node-red/templates/service.yaml b/charts/node-red/templates/service.yaml index 13620174..3a4e32e0 100644 --- a/charts/node-red/templates/service.yaml +++ b/charts/node-red/templates/service.yaml @@ -2,6 +2,7 @@ apiVersion: v1 kind: Service metadata: name: {{ include "node-red.fullname" . }} + namespace: {{ .Release.Namespace | quote }} labels: {{- include "node-red.labels" . | nindent 4 }} spec: diff --git a/charts/node-red/templates/serviceaccount.yaml b/charts/node-red/templates/serviceaccount.yaml index a0504644..ce6e34c1 100644 --- a/charts/node-red/templates/serviceaccount.yaml +++ b/charts/node-red/templates/serviceaccount.yaml @@ -3,6 +3,7 @@ apiVersion: v1 kind: ServiceAccount metadata: name: {{ include "node-red.serviceAccountName" . }} + namespace: {{ .Release.Namespace | quote }} labels: {{- include "node-red.labels" . | nindent 4 }} {{- with .Values.serviceAccount.annotations }} diff --git a/charts/node-red/templates/servicemonitor.yaml b/charts/node-red/templates/servicemonitor.yaml index 0278ec27..b084145c 100644 --- a/charts/node-red/templates/servicemonitor.yaml +++ b/charts/node-red/templates/servicemonitor.yaml @@ -5,6 +5,8 @@ metadata: name: {{ template "node-red.fullname" . }} {{- if .Values.metrics.serviceMonitor.namespace }} namespace: {{ .Values.metrics.serviceMonitor.namespace }} + {{- else }} + namespace: {{ .Release.Namespace | quote }} {{- end }} labels: {{- include "node-red.labels" . | nindent 4 }} @@ -39,4 +41,4 @@ spec: selector: matchLabels: {{- include "node-red.selectorLabels" . | nindent 6 }} -{{- end }} \ No newline at end of file +{{- end }} diff --git a/charts/node-red/templates/sidecar-cm.yaml b/charts/node-red/templates/sidecar-cm.yaml index e5fceb80..90ca568d 100644 --- a/charts/node-red/templates/sidecar-cm.yaml +++ b/charts/node-red/templates/sidecar-cm.yaml @@ -10,6 +10,7 @@ data: kind: ConfigMap metadata: name: {{ include "node-red.sidecarConfigMapName" . }} + namespace: {{ .Release.Namespace | quote }} labels: {{ .Values.sidecar.env.label}}: {{ .Values.sidecar.env.label_value | quote}} {{- end }} diff --git a/charts/node-red/values.yaml b/charts/node-red/values.yaml index f4050aae..dd27ed72 100644 --- a/charts/node-red/values.yaml +++ b/charts/node-red/values.yaml @@ -232,6 +232,16 @@ extraSidecars: [] # image: busybox # command: ["/bin/sh", "-c", "echo hello from sidecar"] +# -- Create a ClusterRole resource for the node-red pod. default: false +createClusterRole: false + +## -- Enable this and set the rules: to whatever custom rules you want for the Cluster Role resource. +clusterRoleRules: + # -- Enable custom rules for the application controller's ClusterRole resource default: false + enabled: false + # -- List of custom rules for the application controller's ClusterRole resource default: [] + rules: [] + # Sidecar that collect the configmaps with specified label and stores the included files into the given folder sidecar: # -- Enable the sidecar