Add jwt-proxy functionality
Issue-ID: NONRTRIC-634
Change-Id: Iedb39691a1dad212f9ad69b127287291496eaaf8
Signed-off-by: ktimoney <kevin.timoney@est.tech>
diff --git a/service-exposure/Dockerfile_jwt b/service-exposure/Dockerfile_jwt
new file mode 100644
index 0000000..104d3a8
--- /dev/null
+++ b/service-exposure/Dockerfile_jwt
@@ -0,0 +1,25 @@
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+FROM golang:latest
+RUN mkdir /app
+COPY ./rapps-jwt /app
+RUN chmod +x /app/rapps-jwt
+WORKDIR /app
+ENTRYPOINT ["/app/rapps-jwt"]
diff --git a/service-exposure/Dockerfile_rhi b/service-exposure/Dockerfile_rhi
index 6332b20..1194c35 100644
--- a/service-exposure/Dockerfile_rhi
+++ b/service-exposure/Dockerfile_rhi
@@ -17,9 +17,9 @@
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=========================================================
#
-FROM golang:latest
-RUN mkdir /app
+FROM golang:latest
+RUN mkdir /app
COPY ./rapps-helm-installer /app
RUN chmod +x /app/rapps-helm-installer
-WORKDIR /app
+WORKDIR /app
ENTRYPOINT ["/app/rapps-helm-installer"]
diff --git a/service-exposure/Dockerfile_rhwi1 b/service-exposure/Dockerfile_rhwi1
new file mode 100644
index 0000000..4b5413f
--- /dev/null
+++ b/service-exposure/Dockerfile_rhwi1
@@ -0,0 +1,25 @@
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+FROM golang:latest
+RUN mkdir /app
+COPY ./rapps-rapp-helloworld-invoker1 /app
+RUN chmod +x /app/rapps-rapp-helloworld-invoker1
+WORKDIR /app
+ENTRYPOINT ["/app/rapps-rapp-helloworld-invoker1"]
diff --git a/service-exposure/Dockerfile_rhwi2 b/service-exposure/Dockerfile_rhwi2
new file mode 100644
index 0000000..dd01243
--- /dev/null
+++ b/service-exposure/Dockerfile_rhwi2
@@ -0,0 +1,25 @@
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+FROM golang:latest
+RUN mkdir /app
+COPY ./rapps-rapp-helloworld-invoker2 /app
+RUN chmod +x /app/rapps-rapp-helloworld-invoker2
+WORKDIR /app
+ENTRYPOINT ["/app/rapps-rapp-helloworld-invoker2"]
diff --git a/service-exposure/Dockerfile_rhwp b/service-exposure/Dockerfile_rhwp
new file mode 100644
index 0000000..099315a
--- /dev/null
+++ b/service-exposure/Dockerfile_rhwp
@@ -0,0 +1,25 @@
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+FROM golang:latest
+RUN mkdir /app
+COPY ./rapps-rapp-helloworld-provider /app
+RUN chmod +x /app/rapps-rapp-helloworld-provider
+WORKDIR /app
+ENTRYPOINT ["/app/rapps-rapp-helloworld-provider"]
diff --git a/service-exposure/Dockerfile_rim b/service-exposure/Dockerfile_rim
index f75d7fd..dc4c26b 100644
--- a/service-exposure/Dockerfile_rim
+++ b/service-exposure/Dockerfile_rim
@@ -17,9 +17,11 @@
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=========================================================
#
-FROM golang:latest
-RUN mkdir /app
+FROM golang:latest
+RUN mkdir /app
COPY ./rapps-istio-mgr /app
+RUN mkdir /app/templates
+ADD templates /app/templates
RUN chmod +x /app/rapps-istio-mgr
-WORKDIR /app
+WORKDIR /app
ENTRYPOINT ["/app/rapps-istio-mgr"]
diff --git a/service-exposure/Dockerfile_rkm b/service-exposure/Dockerfile_rkm
index cb4fc65..f1cd6bc 100644
--- a/service-exposure/Dockerfile_rkm
+++ b/service-exposure/Dockerfile_rkm
@@ -17,9 +17,9 @@
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=========================================================
#
-FROM golang:latest
-RUN mkdir /app
+FROM golang:latest
+RUN mkdir /app
COPY ./rapps-keycloak-mgr /app
RUN chmod +x /app/rapps-keycloak-mgr
-WORKDIR /app
+WORKDIR /app
ENTRYPOINT ["/app/rapps-keycloak-mgr"]
diff --git a/service-exposure/IstioOperator.yaml b/service-exposure/IstioOperator.yaml
new file mode 100644
index 0000000..c2c1484
--- /dev/null
+++ b/service-exposure/IstioOperator.yaml
@@ -0,0 +1,82 @@
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+apiVersion: install.istio.io/v1alpha1
+kind: IstioOperator
+spec:
+ profile: demo
+ meshConfig:
+ extensionProviders:
+ - name: "opa-default-grpc"
+ envoyExtAuthzGrpc:
+ service: "opa.default.svc.cluster.local"
+ port: "9191"
+ includeRequestBodyInCheck:
+ maxRequestBytes: 1000000
+ - name: "opa-default-http"
+ envoyExtAuthzHttp:
+ service: "opa.default.svc.cluster.local"
+ port: "8181"
+ includeRequestHeadersInCheck: ["authorization", "path"]
+ includeRequestBodyInCheck:
+ maxRequestBytes: 1000000
+ - name: "opa-local"
+ envoyExtAuthzGrpc:
+ service: "local-opa-grpc.local"
+ port: "9191"
+ accessLogEncoding: TEXT
+ accessLogFile: "/dev/stdout"
+ accessLogFormat: ""
+ outboundTrafficPolicy:
+ mode: REGISTRY_ONLY
+ values:
+ pilot:
+ jwksResolverExtraRootCA: |
+ -----BEGIN CERTIFICATE-----
+ MIIFdTCCA12gAwIBAgIUb2mMsNxZ3fpdLt0memNEwSs+yCUwDQYJKoZIhvcNAQEL
+ BQAwSjELMAkGA1UEBhMCSUUxDDAKBgNVBAsMA0VTVDERMA8GA1UEAwwIZXN0LnRl
+ Y2gxGjAYBgkqhkiG9w0BCQEWC2NhQG1haWwuY29tMB4XDTIyMDMyOTEyMjMxOVoX
+ DTMyMDMyNjEyMjMxOVowSjELMAkGA1UEBhMCSUUxDDAKBgNVBAsMA0VTVDERMA8G
+ A1UEAwwIZXN0LnRlY2gxGjAYBgkqhkiG9w0BCQEWC2NhQG1haWwuY29tMIICIjAN
+ BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAy2E9PlJyZBh64gxnqrhB7ELS59TK
+ mKRZEgyWYCyS54sOsVLt7HwrzeHxMqhccyEB3+S0jqgVFe7RQ2dEIqc9H1upG2TH
+ Cznz7+epYXFj7wRfQAXM53mEJYIVPcjJ31iFBHKURC6l/ZBLENNG+mXBN9cO7nMe
+ b99w8Sc5jVMy9VmKDZMzJildtWhyEGEDq4C69TAJq8zfvPExkOZW9iSg25FaCoip
+ IO19EYVxl6BYnjgKr48s1XyREBUnOkw6IeVLzD/2co5UpJd40yolXAG8eDxxSGzT
+ EjyVMR3tph86FQ8H053lYB5Y3u6iwCdALf9TvUpEv+ZL4BcB+I4U0RdtLQGL2iuv
+ 9NLeqVAfmtXC3st+DgukxvJA3+iGDGyssvY3EF3eCB9QnjjbDwvZ4raG4DIcBNQ3
+ FfpfpoSswXI4KU2JXgS/V28Az46NIFwwT3WvwhFT5aCUcInNPAF2vDSUfDvlHl39
+ BSSKAqsPnvJIDTnlmJoSo28uca2SkSkXL2N43vGOPV4/UYRIz+bqSFNfu48nfe1I
+ E83PKTCTDum+iOscteF1xMU3KrWLpdkBzPW1PfVK6OcAgbKZvfBGNdNOmygfMj5t
+ Slw0bc2Gpd1ISJyQK0L2DVOSMeB6+PyDdJEYUVe+Xh2uqnaGJnAS90//X/FiOJrJ
+ Y5GrgeVLAkDyOjcCAwEAAaNTMFEwHQYDVR0OBBYEFHoCuHWgHsN1cS7TRuJgk1Yv
+ deY7MB8GA1UdIwQYMBaAFHoCuHWgHsN1cS7TRuJgk1YvdeY7MA8GA1UdEwEB/wQF
+ MAMBAf8wDQYJKoZIhvcNAQELBQADggIBALp0D+Sw09OxZhq8CGw/fQn+AScY9JSE
+ E/4C+jVwSVygi7BKcJfqy8aq7cGe+O9sAEnmxDrle1oECVIXX+mhhS7cD5kRdOsb
+ WAjJBqi+B6YgNuawLfQldnHJV/opjb0FBytaGpEMWYsAj0xcoVe4Nj/x7myQ4qoD
+ Y8r8wEFriOwTk+0dICg40I2EUeq5qoJ7Q5bbdYPfe8EhJAkN4u7xJ6P6GDY6Zvoo
+ JpYSSAaKLZb9yd4SxAoDvyuEZL6YNX8vgfPEZqVi2lm5uDkeE+xqWhL2j0ECKXPN
+ PLQMFBCaVPO9RueiwV/P/l0DuChY7dSAHn9kqdS6PlSGe411OGTpxz5laD9Ho4a9
+ UOAurbtu76wAPnsxszAxMAGqEXvZgcX+zUBm4uGPpLUu5vIiWgE/DpwmIpT5jwDu
+ EV0e7C43q3kT5ieqzxDb3gvUWdQZ4Qg6qa8js7KfKH7L0ToCtZACnpdVXjxE1Mp6
+ aCKAPPo8AJm2YdS0Zyj1w8ZN6tDStZ6sfFyEkcRiLOF0pL0qJKw/aqgZd0cHCZed
+ z9p+zpuSbJgnEqax0G7fF5hGofUuCIz4F8CNiehjpZDrCHqPrbCsUveu4iP+cw2N
+ /DZsEJUr0qL+QsAll2L6Zm8z1bAGxomxfFqUAHPep+msFyKT6W2SXz3MzTClq1JK
+ CruKkw029sEv
+ -----END CERTIFICATE-----
diff --git a/service-exposure/MutatingWebhookConfiguration.yaml b/service-exposure/MutatingWebhookConfiguration.yaml
new file mode 100644
index 0000000..b0947aa
--- /dev/null
+++ b/service-exposure/MutatingWebhookConfiguration.yaml
@@ -0,0 +1,44 @@
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+apiVersion: admissionregistration.k8s.io/v1
+kind: MutatingWebhookConfiguration
+metadata:
+ name: jwt-proxy-webhook
+ namespace: default
+webhooks:
+ - name: rapps-webhook.default.svc.cluster.local
+ admissionReviewVersions:
+ - "v1beta1"
+ sideEffects: "None"
+ timeoutSeconds: 30
+ objectSelector:
+ matchLabels:
+ app.kubernetes.io/name: rapp-helloworld-invoker1
+ clientConfig:
+ service:
+ name: jwt-proxy-admission-controller
+ namespace: default
+ path: "/inject-sidecar"
+ caBundle: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURhakNDQWxLZ0F3SUJBZ0lVTlZFcUZwSUJMUEZUOGd2L3hQK245L2ZvTy80d0RRWUpLb1pJaHZjTkFRRUwKQlFBd1RURUxNQWtHQTFVRUJoTUNTVVV4RURBT0JnTlZCQWdUQjFkbFltaHZiMnN4RHpBTkJnTlZCQWNUQmtSMQpZbXhwYmpFTU1Bb0dBMVVFQ2hNRFJWTlVNUTB3Q3dZRFZRUUxFd1JQY21GdU1CNFhEVEl5TURreU1EQTRNRGN3Ck1Gb1hEVEkzTURreE9UQTRNRGN3TUZvd1RURUxNQWtHQTFVRUJoTUNTVVV4RURBT0JnTlZCQWdUQjFkbFltaHYKYjJzeER6QU5CZ05WQkFjVEJrUjFZbXhwYmpFTU1Bb0dBMVVFQ2hNRFJWTlVNUTB3Q3dZRFZRUUxFd1JQY21GdQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXArM3lhc2VHUVpOS1VCakVJcFF6CktUZFI5bEVFTDhGeitGRGIrM0YwalQ2cWtoMko5cmJYdUx0V0dWZm5RQWpXb1JpaHlUV3F3RlR6V2lMNHVtK0gKNzVYSm1ucHlqbkRJRStaUGZpcFR0SW40cHhSZ3Z3WXl5a0pjeGI4blN3a21IM2NVRkVLMHJnbEEvLzVMV0RuWgpIQkl2VkhFUzlGYktwVFBEZFlNRFJ2K3dNNGk1ZWVOM1djOCtnZ0hYZW1tc3pkRG9mc0dMTU1iNkpXQlY0MEs0ClhHRDdheEYwelBIT3RHblhlU21zL1lVTlB4R3Z5WWpmZHJqSW1kL2xKUCtDQysvMlhuaEZYYUYzSzJxbE9uQU4KUGVoOGRPNzdNZzVjU01JQkhwbll1RTVqUy95YmZ0RGRSWDcxRm9ZUmJ0MXZsOXNuVC9zNFhxTDB2bHBCRmVyMApSd0lEQVFBQm8wSXdRREFPQmdOVkhROEJBZjhFQkFNQ0FRWXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QWRCZ05WCkhRNEVGZ1FVcDQyM3B4NnUxbTYwZnhCNEJWYmFWR2gxaGwwd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFHaHYKc25jc1g0dUl2S1lZRUdCNitEYmNmdlViS1o2clQ1Ykx3OUV1aFpDSUJiS0xTOFRLMHFqV2dyM0JZWUsyRFA2UgpTcmhzOHRSbkQ2VCtPL1dMdWpPOXM4SUpBbGQvRkQzenJyZWs1YW16RndQb1JiWVZ6OXY4SG1HblRRY2JZWEFYCmlzcjg5Z1QzRFRLbkRxTHEyUTU2WnBiN2dLbFZWNXZKNjVaVFRzYUwxc2oxK1d0bDB0emcrektMNHdrckRqK0wKRzd4blYrNDY3eEUwSnora3JOaFYzaHJEYmhpOUVsRVNRTnVHeURsTUVuY2dvSEFqMmh4WnVINEVUTXJyYWxSWgphQTI3c1ZDNGlMYmJsQWZ0THRWb1YycGpVdTdDVWwrQ1pOZ2tFRGl1d05weWQvZzdlVmYvVk0vakt5TTFiODQ4Ck5nYlZmcjNhelFlOUIyc3kvQnc9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
+ rules:
+ - operations: [ "CREATE" ]
+ apiGroups: [""]
+ apiVersions: ["v1"]
+ resources: ["pods"]
diff --git a/service-exposure/README.md b/service-exposure/README.md
index 00da4d0..c6cdac3 100644
--- a/service-exposure/README.md
+++ b/service-exposure/README.md
@@ -1,6 +1,28 @@
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
This collection of files represent rapp service exposure prototyping in O-RAN.
-Prerequisites: Istio should be installed on your cluster with the demo profile (istioctl install --set profile=demo). Please refer to the istio documentation for more information.
+Prerequisites: Istio should be installed on your cluster with the demo profile.
+ istioctl install --set profile=demo
+Please refer to the istio documentation for more information.
The deployments have been implemented and tested using minikube.
+If you are not using minikube, references to "minikube ip" should be changed to the appropiate value for you host.
To replicate these tests you will need to setup the various host path referenced in the yaml files on your own machine.
chartmuseum.yaml: path: /var/chartmuseum/charts
@@ -12,30 +34,42 @@
or change them to match your own setup.
+The certs directory contains 2 shell scripts for creating the server and client certs: server_certs.sh and client_certs.sh
+Certs generated by the server_certs.sh script: rootCA.crt, tls.crt and tls.key go in the "/var/keycloak/certs" directory
+Certs generated by the client_certs.sh script: client.crt, client.key, client_pub.key and rootCA.crt go in the "/var/rapps/certs" directory
+
Create the istio-nonrtric namespace and enable it for istio injection
- kubectl create ns istio-nonrtric
+ kubectl create ns istio-nonrtric
kubectl label namespace istio-nonrtric istio-injection=enabled
All go programs need to be built prior to running the Dockerfiles
- go build rapps-helm-installer.go
- go build rapps-keycloak-mgr.go
- go build rapps-istio-mgr.go
+ go build rapps-helm-installer.go
+ go build rapps-keycloak-mgr.go
+ go build rapps-istio-mgr.go
go build rapps-rapp-provider.go
go build rapps-rapp-invoker.go
+ go build rapps-webhook.go
+ go build rapps-jwt.go
+ go build rapps-rapp-helloworld-provider.go
+ go build rapps-rapp-helloworld-invoker1.go
+ go build rapps-rapp-helloworld-invoker2.go
Once the go programs have been compile you then need to build a docker image for each of them.
docker build -f Dockerfile_rim . -t <tag prefix>/rapps-istio-mgr
docker build -f Dockerfile_rkm . -t <tag prefix>/rapps-keycloak-mgr
docker build -f Dockerfile_rhi . -t <tag prefix>/rapps-helm-installer
- docker build -f Dockerfile_rri . -t <tag prefix>/rapps-rapp-invoker
- docker build -f Dockerfile_rrp . -t <tag prefix>/rapps-rapp-provider
+ docker build -f Dockerfile_wh . -t <tag prefix>/rapps-webhook
+ docker build -f Dockerfile_jwt . -t <tag prefix>/rapps-jwt
+ docker build -f Dockerfile_rhwp . -t <tag prefix>/rapps-rapp-helloworld-provider
+ docker build -f Dockerfile_rhwi1 . -t <tag prefix>/rapps-rapp-helloworld-invoker1
+ docker build -f Dockerfile_rhwi2 . -t <tag prefix>/rapps-rapp-helloworld-invoker2
-Image references in the yaml files/helm charts should be changed to match your own tagged images.
+Image references in the yaml files/helm charts should be changed to match your own tagged images.
You will need to package your rapp charts and copy them to the /var/chartmuseum/charts directory before starting.
@@ -51,20 +85,21 @@
istioctl kube-inject -f postgres.yaml | kubectl apply -f -
istioctl kube-inject -f keycloak.yaml | kubectl apply -f -
+or use the keycloak.sh deploy script
-To start the management pods run:
+To start the management pods run:
start_pods.sh
-Run:
- kubectl get pods to ensure all managements pods are up and running
- NAME READY STATUS RESTARTS AGE
- chartmuseum-deployment-7b8cd4c9d4-tpmhl 1/1 Running 0 8s
- keycloak-bc6f78f88-zmxlt 2/2 Running 0 2m20s
- postgres-6fb4cc8db6-bbhg9 2/2 Running 0 2m34s
- rapps-helm-installer-deployment-67476694-sxb2d 1/1 Running 0 6s
- rapps-istio-mgr-deployment-67c67647b6-scmqc 1/1 Running 0 7s
- rapps-keycloak-mgr-deployment-7464f87575-trvmx 1/1 Running 0 7s
+Once all pods have been started a list of running pods is displayed at the end of the script:
+NAME READY STATUS RESTARTS AGE
+chartmuseum-deployment-7b8cd4c9d4-nd7dk 1/1 Running 0 9s
+jwt-proxy-admission-controller-deployment-66797fb6df-mlk8t 1/1 Running 0 8s
+keycloak-846ff979bc-ndvdf 2/2 Running 0 2m16s
+postgres-78b4b9d95-nqjkj 2/2 Running 0 2m29s
+rapps-helm-installer-deployment-67476694-n5r24 1/1 Running 0 8s
+rapps-istio-mgr-deployment-67c67647b6-p5s2k 1/1 Running 0 8s
+rapps-keycloak-mgr-deployment-7464f87575-54h9x 1/1 Running 0 8s
Get the node port for the helm installer that corresponds to port 80
@@ -72,13 +107,17 @@
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
rapps-helm-installer NodePort 10.96.58.211 <none> 80:31570/TCP 8m9s
-Once these pods are up and running run:
- curl http://<minikube ip>:<helm installer node port>/install?chart=<rapp chart name>
+Once these pods are up and running run:
+ curl http://<minikube ip>:<helm installer node port>/install?chart=<rapp chart name>
to install your rapp
- e.g. curl http://192.168.49.2:31570/install?chart=rapp-provider
+ e.g. curl http://192.168.49.2:31570/install?chart=rapp-hello-world-provider
Successfully installed release: rapp-provider
+ Alternativley use the deploy_rapp.sh script
+ e.g. ./deploy_rapp.sh rapp-helloworld-provider
+ Note: The line export host= should be changed to the appropaite ip for the host you are running on.
+
This will setup keycloak realm + client, istio policies and deploy your chart.
You should install both the provider and the invoker to see the pods communicating.
@@ -91,14 +130,19 @@
If you want to test using the rp_test.sh file, the client_secret field needs be changed to match the secret for you keycloak client.
You can find this in the keycloak-mgr log.
-To uninstall run:
+To uninstall run:
curl http://<minikube ip>:<helm installer node port>/uninstall?chart=<rapp chart name>
e.g. curl http://192.168.49.2:31570/uninstall?chart=rapp-invoker
Successfully uninstalled release: rapp-invoker
-To stop the management pods run:
+ Alternativley use the undeploy_rapp.sh script
+ e.g. ./undeploy_rapp.sh rapp-helloworld-provider
+
+To stop the management pods and provider/invoker pods at the same time run:
stop_pods.sh
Remove postgres and keycloak with the following commands:
kubectl delete -f keycloak.yaml
kubectl delete -f postgres.yaml
+
+ or use ./keycloak.sh undeploy
diff --git a/service-exposure/chartmuseum.yaml b/service-exposure/chartmuseum.yaml
index 30aa4e6..987075d 100644
--- a/service-exposure/chartmuseum.yaml
+++ b/service-exposure/chartmuseum.yaml
@@ -23,26 +23,26 @@
name: chartmuseum-deployment
namespace: default
labels:
- app: chartmuseum
+ app: chartmuseum
spec:
selector:
matchLabels:
- app: chartmuseum
+ app: chartmuseum
template:
metadata:
labels:
- app: chartmuseum
+ app: chartmuseum
version: v1
spec:
containers:
- - name: chartmuseum
- image: chartmuseum/chartmuseum:latest
+ - name: chartmuseum
+ image: chartmuseum/chartmuseum:latest
imagePullPolicy: IfNotPresent
env:
- - name: STORAGE
- value: local
- - name: STORAGE_LOCAL_ROOTDIR
- value: /charts
+ - name: STORAGE
+ value: local
+ - name: STORAGE_LOCAL_ROOTDIR
+ value: /charts
ports:
- name: http
containerPort: 8080
@@ -58,24 +58,24 @@
mountPath: /charts
readOnly: true
volumes:
- - name: chartdir
+ - name: chartdir
hostPath:
# Ensure the file directory is created.
- path: /var/chartmuseum/charts
+ path: /var/chartmuseum/charts
type: DirectoryOrCreate
- replicas: 1
+ replicas: 1
---
apiVersion: v1
kind: Service
metadata:
- name: chartmuseum
+ name: chartmuseum
namespace: default
spec:
selector:
- app: chartmuseum
+ app: chartmuseum
ports:
- name: http
port: 8080
targetPort: 8080
- nodePort: 31580
- type: LoadBalancer
+ nodePort: 31581
+ type: NodePort
diff --git a/service-exposure/charts/rapp-helloworld-invoker1/.helmignore b/service-exposure/charts/rapp-helloworld-invoker1/.helmignore
new file mode 100644
index 0000000..0e8a0eb
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker1/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/service-exposure/charts/rapp-helloworld-invoker1/Chart.yaml b/service-exposure/charts/rapp-helloworld-invoker1/Chart.yaml
new file mode 100644
index 0000000..400203d
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker1/Chart.yaml
@@ -0,0 +1,43 @@
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+apiVersion: v2
+name: rapp-helloworld-invoker1
+description: A Helm chart for Kubernetes
+
+# A chart can be either an 'application' or a 'library' chart.
+#
+# Application charts are a collection of templates that can be packaged into versioned archives
+# to be deployed.
+#
+# Library charts provide useful utilities or functions for the chart developer. They're included as
+# a dependency of application charts to inject those utilities and functions into the rendering
+# pipeline. Library charts do not define any templates and therefore cannot be deployed.
+type: application
+
+# This is the chart version. This version number should be incremented each time you make changes
+# to the chart and its templates, including the app version.
+# Versions are expected to follow Semantic Versioning (https://semver.org/)
+version: 0.1.0
+
+# This is the version number of the application being deployed. This version number should be
+# incremented each time you make changes to the application. Versions are not expected to
+# follow Semantic Versioning. They should reflect the version the application is using.
+# It is recommended to use it with quotes.
+appVersion: "1.16.0"
diff --git a/service-exposure/charts/rapp-helloworld-invoker1/templates/NOTES.txt b/service-exposure/charts/rapp-helloworld-invoker1/templates/NOTES.txt
new file mode 100644
index 0000000..939a074
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker1/templates/NOTES.txt
@@ -0,0 +1,43 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+1. Get the application URL by running these commands:
+{{- if .Values.ingress.enabled }}
+{{- range $host := .Values.ingress.hosts }}
+ {{- range .paths }}
+ http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
+ {{- end }}
+{{- end }}
+{{- else if contains "NodePort" .Values.service.type }}
+ export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "rapp-helloworld-invoker1.fullname" . }})
+ export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+ echo http://$NODE_IP:$NODE_PORT
+{{- else if contains "LoadBalancer" .Values.service.type }}
+ NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+ You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "rapp-helloworld-invoker1.fullname" . }}'
+ export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "rapp-helloworld-invoker1.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
+ echo http://$SERVICE_IP:{{ .Values.service.port }}
+{{- else if contains "ClusterIP" .Values.service.type }}
+ export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "rapp-helloworld-invoker1.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
+ export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
+ echo "Visit http://127.0.0.1:8080 to use your application"
+ kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
+{{- end }}
diff --git a/service-exposure/charts/rapp-helloworld-invoker1/templates/_helpers.tpl b/service-exposure/charts/rapp-helloworld-invoker1/templates/_helpers.tpl
new file mode 100644
index 0000000..fbac7d3
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker1/templates/_helpers.tpl
@@ -0,0 +1,62 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "rapp-helloworld-invoker1.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "rapp-helloworld-invoker1.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "rapp-helloworld-invoker1.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "rapp-helloworld-invoker1.labels" -}}
+helm.sh/chart: {{ include "rapp-helloworld-invoker1.chart" . }}
+{{ include "rapp-helloworld-invoker1.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "rapp-helloworld-invoker1.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "rapp-helloworld-invoker1.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "rapp-helloworld-invoker1.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "rapp-helloworld-invoker1.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
diff --git a/service-exposure/charts/rapp-helloworld-invoker1/templates/clusterrole.yaml b/service-exposure/charts/rapp-helloworld-invoker1/templates/clusterrole.yaml
new file mode 100644
index 0000000..f713ac9
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker1/templates/clusterrole.yaml
@@ -0,0 +1,41 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+{{- if .Values.rbac.create -}}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ labels:
+ app: {{ template "rapp-helloworld-invoker1.name" .}}
+ chart: {{ .Chart.Name }}-{{ .Chart.Version }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ name: {{ template "rapp-helloworld-invoker1.fullname" . }}
+ namespace: {{ .Release.Namespace }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: cluster-admin
+subjects:
+- kind: ServiceAccount
+ name: {{ template "rapp-helloworld-invoker1.fullname" . }}
+ namespace: {{ .Release.Namespace }}
+{{- end -}}
diff --git a/service-exposure/charts/rapp-helloworld-invoker1/templates/deployment.yaml b/service-exposure/charts/rapp-helloworld-invoker1/templates/deployment.yaml
new file mode 100644
index 0000000..d989b0e
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker1/templates/deployment.yaml
@@ -0,0 +1,91 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ include "rapp-helloworld-invoker1.fullname" . }}
+ labels:
+ {{- include "rapp-helloworld-invoker1.labels" . | nindent 4 }}
+spec:
+ {{- if not .Values.autoscaling.enabled }}
+ replicas: {{ .Values.replicaCount }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "rapp-helloworld-invoker1.selectorLabels" . | nindent 6 }}
+ template:
+ metadata:
+ {{- with .Values.podAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ labels:
+ {{- include "rapp-helloworld-invoker1.selectorLabels" . | nindent 8 }}
+ spec:
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ include "rapp-helloworld-invoker1.serviceAccountName" . }}
+ securityContext:
+ {{- toYaml .Values.podSecurityContext | nindent 8 }}
+ containers:
+ - name: {{ .Chart.Name }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 12 }}
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ command: ["/app/rapps-rapp-helloworld-invoker1"]
+ args: [
+ "-securityEnabled", "{{ .Values.rapp.securityEnabled }}",
+ "-rapp", "{{ with index .Values.rapp.apps 0 }}{{ .prefix }}{{ end }}",
+ "-methods", "{{- range .Values.rapp.apps }}{{ join "," .methods }}{{- end }}"
+ ]
+ ports:
+ - name: http
+ containerPort: 9000
+ protocol: TCP
+ livenessProbe:
+ httpGet:
+ path: /health
+ port: 9000
+ initialDelaySeconds: 5
+ periodSeconds: 60
+ readinessProbe:
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ exec:
+ command: ["stat", "init.txt"]
+ resources:
+ {{- toYaml .Values.resources | nindent 12 }}
+ {{- with .Values.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
diff --git a/service-exposure/charts/rapp-helloworld-invoker1/templates/hpa.yaml b/service-exposure/charts/rapp-helloworld-invoker1/templates/hpa.yaml
new file mode 100644
index 0000000..5754224
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker1/templates/hpa.yaml
@@ -0,0 +1,49 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+{{- if .Values.autoscaling.enabled }}
+apiVersion: autoscaling/v2beta1
+kind: HorizontalPodAutoscaler
+metadata:
+ name: {{ include "rapp-helloworld-invoker1.fullname" . }}
+ labels:
+ {{- include "rapp-helloworld-invoker1.labels" . | nindent 4 }}
+spec:
+ scaleTargetRef:
+ apiVersion: apps/v1
+ kind: Deployment
+ name: {{ include "rapp-helloworld-invoker1.fullname" . }}
+ minReplicas: {{ .Values.autoscaling.minReplicas }}
+ maxReplicas: {{ .Values.autoscaling.maxReplicas }}
+ metrics:
+ {{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
+ - type: Resource
+ resource:
+ name: cpu
+ targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
+ {{- end }}
+ {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
+ - type: Resource
+ resource:
+ name: memory
+ targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
+ {{- end }}
+{{- end }}
diff --git a/service-exposure/charts/rapp-helloworld-invoker1/templates/ingress.yaml b/service-exposure/charts/rapp-helloworld-invoker1/templates/ingress.yaml
new file mode 100644
index 0000000..141e67b
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker1/templates/ingress.yaml
@@ -0,0 +1,62 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+{{- if .Values.ingress.enabled -}}
+{{- $fullName := include "rapp-helloworld-invoker1.fullname" . -}}
+{{- $svcPort := .Values.service.port -}}
+{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1beta1
+{{- else -}}
+apiVersion: extensions/v1beta1
+{{- end }}
+kind: Ingress
+metadata:
+ name: {{ $fullName }}
+ labels:
+ {{- include "rapp-helloworld-invoker1.labels" . | nindent 4 }}
+ {{- with .Values.ingress.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ {{- if .Values.ingress.tls }}
+ tls:
+ {{- range .Values.ingress.tls }}
+ - hosts:
+ {{- range .hosts }}
+ - {{ . | quote }}
+ {{- end }}
+ secretName: {{ .secretName }}
+ {{- end }}
+ {{- end }}
+ rules:
+ {{- range .Values.ingress.hosts }}
+ - host: {{ .host | quote }}
+ http:
+ paths:
+ {{- range .paths }}
+ - path: {{ .path }}
+ backend:
+ serviceName: {{ $fullName }}
+ servicePort: {{ $svcPort }}
+ {{- end }}
+ {{- end }}
+ {{- end }}
diff --git a/service-exposure/charts/rapp-helloworld-invoker1/templates/service.yaml b/service-exposure/charts/rapp-helloworld-invoker1/templates/service.yaml
new file mode 100644
index 0000000..d2df6eb
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker1/templates/service.yaml
@@ -0,0 +1,36 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "rapp-helloworld-invoker1.fullname" . }}
+ labels:
+ {{- include "rapp-helloworld-invoker1.labels" . | nindent 4 }}
+spec:
+ type: {{ .Values.service.type }}
+ ports:
+ - port: {{ .Values.service.port }}
+ targetPort: http
+ protocol: TCP
+ name: http
+ selector:
+ {{- include "rapp-helloworld-invoker1.selectorLabels" . | nindent 4 }}
diff --git a/service-exposure/charts/rapp-helloworld-invoker1/templates/serviceaccount.yaml b/service-exposure/charts/rapp-helloworld-invoker1/templates/serviceaccount.yaml
new file mode 100644
index 0000000..40d1cc4
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker1/templates/serviceaccount.yaml
@@ -0,0 +1,33 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "rapp-helloworld-invoker1.serviceAccountName" . }}
+ labels:
+ {{- include "rapp-helloworld-invoker1.labels" . | nindent 4 }}
+ {{- with .Values.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/service-exposure/charts/rapp-helloworld-invoker1/templates/tests/test-connection.yaml b/service-exposure/charts/rapp-helloworld-invoker1/templates/tests/test-connection.yaml
new file mode 100644
index 0000000..ed38ea7
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker1/templates/tests/test-connection.yaml
@@ -0,0 +1,36 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+apiVersion: v1
+kind: Pod
+metadata:
+ name: "{{ include "rapp-helloworld-invoker1.fullname" . }}-test-connection"
+ labels:
+ {{- include "rapp-helloworld-invoker1.labels" . | nindent 4 }}
+ annotations:
+ "helm.sh/hook": test
+spec:
+ containers:
+ - name: wget
+ image: busybox
+ command: ['wget']
+ args: ['{{ include "rapp-helloworld-invoker1.fullname" . }}:{{ .Values.service.port }}']
+ restartPolicy: Never
diff --git a/service-exposure/charts/rapp-helloworld-invoker1/values.yaml b/service-exposure/charts/rapp-helloworld-invoker1/values.yaml
new file mode 100644
index 0000000..8e89cff
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker1/values.yaml
@@ -0,0 +1,123 @@
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+
+# Default values for rapp-helloworld-invoker1.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+replicaCount: 1
+
+image:
+ repository: ktimoney/rapps-rapp-helloworld-invoker1
+ pullPolicy: IfNotPresent
+ # Overrides the image tag whose default is the chart appVersion.
+ tag: "latest"
+
+imagePullSecrets: []
+nameOverride: ""
+fullnameOverride: ""
+
+serviceAccount:
+ # Specifies whether a service account should be created
+ create: true
+ # Annotations to add to the service account
+ annotations: {}
+ # The name of the service account to use.
+ # If not set and create is true, a name is generated using the fullname template
+ name: "rapp-helloworld-invoker1"
+
+rbac:
+ # Specifies whether rbac is enabled
+ create: true
+
+podAnnotations: {}
+
+podSecurityContext: {}
+ # fsGroup: 2000
+
+securityContext: {}
+ # capabilities:
+ # drop:
+ # - ALL
+ # readOnlyRootFilesystem: true
+ # runAsNonRoot: true
+ # runAsUser: 1000
+
+service:
+ type: ClusterIP
+ port: 80
+
+ingress:
+ enabled: false
+ annotations: {}
+ # kubernetes.io/ingress.class: nginx
+ # kubernetes.io/tls-acme: "true"
+ hosts:
+ - host: rapp-helloworld-invoker1
+ paths:
+ - path: /
+ backend:
+ serviceName: rapp-helloworld-invoker1
+ servicePort: 80
+ tls: []
+ # - secretName: chart-example-tls
+ # hosts:
+ # - chart-example.local
+
+resources: {}
+ # We usually recommend not to specify default resources and to leave this as a conscious
+ # choice for the user. This also increases chances charts run on environments with little
+ # resources, such as Minikube. If you do want to specify resources, uncomment the following
+ # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 128Mi
+
+autoscaling:
+ enabled: false
+ minReplicas: 1
+ maxReplicas: 100
+ targetCPUUtilizationPercentage: 80
+ # targetMemoryUtilizationPercentage: 80
+
+nodeSelector: {}
+
+tolerations: []
+
+affinity: {}
+
+
+rapp:
+ securityEnabled: true
+ type: invoker
+ realm: demo
+ client: demoprovider-cli
+ authenticator: client-jwt
+ roles:
+ - role : provider-viewer
+ grants:
+ - GET
+ apps:
+ - prefix: rapp-helloworld-provider
+ methods:
+ - GET
diff --git a/service-exposure/charts/rapp-helloworld-invoker2/.helmignore b/service-exposure/charts/rapp-helloworld-invoker2/.helmignore
new file mode 100644
index 0000000..0e8a0eb
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker2/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/service-exposure/charts/rapp-helloworld-invoker2/Chart.yaml b/service-exposure/charts/rapp-helloworld-invoker2/Chart.yaml
new file mode 100644
index 0000000..3a7db7a
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker2/Chart.yaml
@@ -0,0 +1,44 @@
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+
+apiVersion: v2
+name: rapp-helloworld-invoker2
+description: A Helm chart for Kubernetes
+
+# A chart can be either an 'application' or a 'library' chart.
+#
+# Application charts are a collection of templates that can be packaged into versioned archives
+# to be deployed.
+#
+# Library charts provide useful utilities or functions for the chart developer. They're included as
+# a dependency of application charts to inject those utilities and functions into the rendering
+# pipeline. Library charts do not define any templates and therefore cannot be deployed.
+type: application
+
+# This is the chart version. This version number should be incremented each time you make changes
+# to the chart and its templates, including the app version.
+# Versions are expected to follow Semantic Versioning (https://semver.org/)
+version: 0.1.0
+
+# This is the version number of the application being deployed. This version number should be
+# incremented each time you make changes to the application. Versions are not expected to
+# follow Semantic Versioning. They should reflect the version the application is using.
+# It is recommended to use it with quotes.
+appVersion: "1.16.0"
diff --git a/service-exposure/charts/rapp-helloworld-invoker2/templates/NOTES.txt b/service-exposure/charts/rapp-helloworld-invoker2/templates/NOTES.txt
new file mode 100644
index 0000000..9e38caa
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker2/templates/NOTES.txt
@@ -0,0 +1,43 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+1. Get the application URL by running these commands:
+{{- if .Values.ingress.enabled }}
+{{- range $host := .Values.ingress.hosts }}
+ {{- range .paths }}
+ http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
+ {{- end }}
+{{- end }}
+{{- else if contains "NodePort" .Values.service.type }}
+ export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "rapp-helloworld-invoker2.fullname" . }})
+ export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+ echo http://$NODE_IP:$NODE_PORT
+{{- else if contains "LoadBalancer" .Values.service.type }}
+ NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+ You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "rapp-helloworld-invoker2.fullname" . }}'
+ export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "rapp-helloworld-invoker2.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
+ echo http://$SERVICE_IP:{{ .Values.service.port }}
+{{- else if contains "ClusterIP" .Values.service.type }}
+ export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "rapp-helloworld-invoker2.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
+ export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
+ echo "Visit http://127.0.0.1:8080 to use your application"
+ kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
+{{- end }}
diff --git a/service-exposure/charts/rapp-helloworld-invoker2/templates/_helpers.tpl b/service-exposure/charts/rapp-helloworld-invoker2/templates/_helpers.tpl
new file mode 100644
index 0000000..0999f45
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker2/templates/_helpers.tpl
@@ -0,0 +1,62 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "rapp-helloworld-invoker2.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "rapp-helloworld-invoker2.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "rapp-helloworld-invoker2.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "rapp-helloworld-invoker2.labels" -}}
+helm.sh/chart: {{ include "rapp-helloworld-invoker2.chart" . }}
+{{ include "rapp-helloworld-invoker2.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "rapp-helloworld-invoker2.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "rapp-helloworld-invoker2.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "rapp-helloworld-invoker2.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "rapp-helloworld-invoker2.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
diff --git a/service-exposure/charts/rapp-helloworld-invoker2/templates/clusterrole.yaml b/service-exposure/charts/rapp-helloworld-invoker2/templates/clusterrole.yaml
new file mode 100644
index 0000000..55cb399
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker2/templates/clusterrole.yaml
@@ -0,0 +1,41 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+{{- if .Values.rbac.create -}}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ labels:
+ app: {{ template "rapp-helloworld-invoker2.name" .}}
+ chart: {{ .Chart.Name }}-{{ .Chart.Version }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ name: {{ template "rapp-helloworld-invoker2.fullname" . }}
+ namespace: {{ .Release.Namespace }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: cluster-admin
+subjects:
+- kind: ServiceAccount
+ name: {{ template "rapp-helloworld-invoker2.fullname" . }}
+ namespace: {{ .Release.Namespace }}
+{{- end -}}
diff --git a/service-exposure/charts/rapp-helloworld-invoker2/templates/deployment.yaml b/service-exposure/charts/rapp-helloworld-invoker2/templates/deployment.yaml
new file mode 100644
index 0000000..3333721
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker2/templates/deployment.yaml
@@ -0,0 +1,91 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ include "rapp-helloworld-invoker2.fullname" . }}
+ labels:
+ {{- include "rapp-helloworld-invoker2.labels" . | nindent 4 }}
+spec:
+ {{- if not .Values.autoscaling.enabled }}
+ replicas: {{ .Values.replicaCount }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "rapp-helloworld-invoker2.selectorLabels" . | nindent 6 }}
+ template:
+ metadata:
+ {{- with .Values.podAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ labels:
+ {{- include "rapp-helloworld-invoker2.selectorLabels" . | nindent 8 }}
+ spec:
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ include "rapp-helloworld-invoker2.serviceAccountName" . }}
+ securityContext:
+ {{- toYaml .Values.podSecurityContext | nindent 8 }}
+ containers:
+ - name: {{ .Chart.Name }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 12 }}
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ command: ["/app/rapps-rapp-helloworld-invoker2"]
+ args: [
+ "-securityEnabled", "{{ .Values.rapp.securityEnabled }}",
+ "-rapp", "{{ with index .Values.rapp.apps 0 }}{{ .prefix }}{{ end }}",
+ "-methods", "{{- range .Values.rapp.apps }}{{ join "," .methods }}{{- end }}"
+ ]
+ ports:
+ - name: http
+ containerPort: 9000
+ protocol: TCP
+ livenessProbe:
+ httpGet:
+ path: /health
+ port: 9000
+ initialDelaySeconds: 5
+ periodSeconds: 60
+ readinessProbe:
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ exec:
+ command: ["stat", "init.txt"]
+ resources:
+ {{- toYaml .Values.resources | nindent 12 }}
+ {{- with .Values.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
diff --git a/service-exposure/charts/rapp-helloworld-invoker2/templates/hpa.yaml b/service-exposure/charts/rapp-helloworld-invoker2/templates/hpa.yaml
new file mode 100644
index 0000000..2fcc1a8
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker2/templates/hpa.yaml
@@ -0,0 +1,49 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+{{- if .Values.autoscaling.enabled }}
+apiVersion: autoscaling/v2beta1
+kind: HorizontalPodAutoscaler
+metadata:
+ name: {{ include "rapp-helloworld-invoker2.fullname" . }}
+ labels:
+ {{- include "rapp-helloworld-invoker2.labels" . | nindent 4 }}
+spec:
+ scaleTargetRef:
+ apiVersion: apps/v1
+ kind: Deployment
+ name: {{ include "rapp-helloworld-invoker2.fullname" . }}
+ minReplicas: {{ .Values.autoscaling.minReplicas }}
+ maxReplicas: {{ .Values.autoscaling.maxReplicas }}
+ metrics:
+ {{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
+ - type: Resource
+ resource:
+ name: cpu
+ targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
+ {{- end }}
+ {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
+ - type: Resource
+ resource:
+ name: memory
+ targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
+ {{- end }}
+{{- end }}
diff --git a/service-exposure/charts/rapp-helloworld-invoker2/templates/ingress.yaml b/service-exposure/charts/rapp-helloworld-invoker2/templates/ingress.yaml
new file mode 100644
index 0000000..cfd3538
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker2/templates/ingress.yaml
@@ -0,0 +1,62 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+{{- if .Values.ingress.enabled -}}
+{{- $fullName := include "rapp-helloworld-invoker2.fullname" . -}}
+{{- $svcPort := .Values.service.port -}}
+{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1beta1
+{{- else -}}
+apiVersion: extensions/v1beta1
+{{- end }}
+kind: Ingress
+metadata:
+ name: {{ $fullName }}
+ labels:
+ {{- include "rapp-helloworld-invoker2.labels" . | nindent 4 }}
+ {{- with .Values.ingress.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ {{- if .Values.ingress.tls }}
+ tls:
+ {{- range .Values.ingress.tls }}
+ - hosts:
+ {{- range .hosts }}
+ - {{ . | quote }}
+ {{- end }}
+ secretName: {{ .secretName }}
+ {{- end }}
+ {{- end }}
+ rules:
+ {{- range .Values.ingress.hosts }}
+ - host: {{ .host | quote }}
+ http:
+ paths:
+ {{- range .paths }}
+ - path: {{ .path }}
+ backend:
+ serviceName: {{ $fullName }}
+ servicePort: {{ $svcPort }}
+ {{- end }}
+ {{- end }}
+ {{- end }}
diff --git a/service-exposure/charts/rapp-helloworld-invoker2/templates/service.yaml b/service-exposure/charts/rapp-helloworld-invoker2/templates/service.yaml
new file mode 100644
index 0000000..cadc200
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker2/templates/service.yaml
@@ -0,0 +1,36 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "rapp-helloworld-invoker2.fullname" . }}
+ labels:
+ {{- include "rapp-helloworld-invoker2.labels" . | nindent 4 }}
+spec:
+ type: {{ .Values.service.type }}
+ ports:
+ - port: {{ .Values.service.port }}
+ targetPort: http
+ protocol: TCP
+ name: http
+ selector:
+ {{- include "rapp-helloworld-invoker2.selectorLabels" . | nindent 4 }}
diff --git a/service-exposure/charts/rapp-helloworld-invoker2/templates/serviceaccount.yaml b/service-exposure/charts/rapp-helloworld-invoker2/templates/serviceaccount.yaml
new file mode 100644
index 0000000..a92848e
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker2/templates/serviceaccount.yaml
@@ -0,0 +1,33 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "rapp-helloworld-invoker2.serviceAccountName" . }}
+ labels:
+ {{- include "rapp-helloworld-invoker2.labels" . | nindent 4 }}
+ {{- with .Values.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/service-exposure/charts/rapp-helloworld-invoker2/templates/tests/test-connection.yaml b/service-exposure/charts/rapp-helloworld-invoker2/templates/tests/test-connection.yaml
new file mode 100644
index 0000000..1f2e296
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker2/templates/tests/test-connection.yaml
@@ -0,0 +1,36 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+apiVersion: v1
+kind: Pod
+metadata:
+ name: "{{ include "rapp-helloworld-invoker2.fullname" . }}-test-connection"
+ labels:
+ {{- include "rapp-helloworld-invoker2.labels" . | nindent 4 }}
+ annotations:
+ "helm.sh/hook": test
+spec:
+ containers:
+ - name: wget
+ image: busybox
+ command: ['wget']
+ args: ['{{ include "rapp-helloworld-invoker2.fullname" . }}:{{ .Values.service.port }}']
+ restartPolicy: Never
diff --git a/service-exposure/charts/rapp-helloworld-invoker2/values.yaml b/service-exposure/charts/rapp-helloworld-invoker2/values.yaml
new file mode 100644
index 0000000..bd6f5ab
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-invoker2/values.yaml
@@ -0,0 +1,123 @@
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+
+# Default values for rapp-helloworld-invoker2.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+replicaCount: 1
+
+image:
+ repository: ktimoney/rapps-rapp-helloworld-invoker2
+ pullPolicy: IfNotPresent
+ # Overrides the image tag whose default is the chart appVersion.
+ tag: "latest"
+
+imagePullSecrets: []
+nameOverride: ""
+fullnameOverride: ""
+
+serviceAccount:
+ # Specifies whether a service account should be created
+ create: true
+ # Annotations to add to the service account
+ annotations: {}
+ # The name of the service account to use.
+ # If not set and create is true, a name is generated using the fullname template
+ name: "rapp-helloworld-invoker2"
+
+rbac:
+ # Specifies whether rbac is enabled
+ create: true
+
+podAnnotations: {}
+
+podSecurityContext: {}
+ # fsGroup: 2000
+
+securityContext: {}
+ # capabilities:
+ # drop:
+ # - ALL
+ # readOnlyRootFilesystem: true
+ # runAsNonRoot: true
+ # runAsUser: 1000
+
+service:
+ type: ClusterIP
+ port: 80
+
+ingress:
+ enabled: false
+ annotations: {}
+ # kubernetes.io/ingress.class: nginx
+ # kubernetes.io/tls-acme: "true"
+ hosts:
+ - host: rapp-helloworld-invoker2
+ paths:
+ - path: /
+ backend:
+ serviceName: rapp-helloworld-invoker2
+ servicePort: 80
+ tls: []
+ # - secretName: chart-example-tls
+ # hosts:
+ # - chart-example.local
+
+resources: {}
+ # We usually recommend not to specify default resources and to leave this as a conscious
+ # choice for the user. This also increases chances charts run on environments with little
+ # resources, such as Minikube. If you do want to specify resources, uncomment the following
+ # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 128Mi
+
+autoscaling:
+ enabled: false
+ minReplicas: 1
+ maxReplicas: 100
+ targetCPUUtilizationPercentage: 80
+ # targetMemoryUtilizationPercentage: 80
+
+nodeSelector: {}
+
+tolerations: []
+
+affinity: {}
+
+
+rapp:
+ securityEnabled: true
+ type: invoker
+ realm: demo
+ client: demoprovider-cli
+ authenticator: client-jwt
+ roles:
+ - role : provider-viewer
+ grants:
+ - GET
+ apps:
+ - prefix: rapp-helloworld-provider
+ methods:
+ - GET
diff --git a/service-exposure/charts/rapp-helloworld-provider/.helmignore b/service-exposure/charts/rapp-helloworld-provider/.helmignore
new file mode 100644
index 0000000..0e8a0eb
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-provider/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/service-exposure/charts/rapp-helloworld-provider/Chart.yaml b/service-exposure/charts/rapp-helloworld-provider/Chart.yaml
new file mode 100644
index 0000000..2978a4c
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-provider/Chart.yaml
@@ -0,0 +1,44 @@
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+
+apiVersion: v2
+name: rapp-helloworld-provider
+description: A Helm chart for Kubernetes
+
+# A chart can be either an 'application' or a 'library' chart.
+#
+# Application charts are a collection of templates that can be packaged into versioned archives
+# to be deployed.
+#
+# Library charts provide useful utilities or functions for the chart developer. They're included as
+# a dependency of application charts to inject those utilities and functions into the rendering
+# pipeline. Library charts do not define any templates and therefore cannot be deployed.
+type: application
+
+# This is the chart version. This version number should be incremented each time you make changes
+# to the chart and its templates, including the app version.
+# Versions are expected to follow Semantic Versioning (https://semver.org/)
+version: 0.1.0
+
+# This is the version number of the application being deployed. This version number should be
+# incremented each time you make changes to the application. Versions are not expected to
+# follow Semantic Versioning. They should reflect the version the application is using.
+# It is recommended to use it with quotes.
+appVersion: "1.16.0"
diff --git a/service-exposure/charts/rapp-helloworld-provider/templates/NOTES.txt b/service-exposure/charts/rapp-helloworld-provider/templates/NOTES.txt
new file mode 100644
index 0000000..a4ad913
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-provider/templates/NOTES.txt
@@ -0,0 +1,43 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+1. Get the application URL by running these commands:
+{{- if .Values.ingress.enabled }}
+{{- range $host := .Values.ingress.hosts }}
+ {{- range .paths }}
+ http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
+ {{- end }}
+{{- end }}
+{{- else if contains "NodePort" .Values.service.type }}
+ export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "rapp-helloworld-provider.fullname" . }})
+ export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+ echo http://$NODE_IP:$NODE_PORT
+{{- else if contains "LoadBalancer" .Values.service.type }}
+ NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+ You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "rapp-helloworld-provider.fullname" . }}'
+ export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "rapp-helloworld-provider.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
+ echo http://$SERVICE_IP:{{ .Values.service.port }}
+{{- else if contains "ClusterIP" .Values.service.type }}
+ export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "rapp-helloworld-provider.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
+ export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
+ echo "Visit http://127.0.0.1:8080 to use your application"
+ kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
+{{- end }}
diff --git a/service-exposure/charts/rapp-helloworld-provider/templates/_helpers.tpl b/service-exposure/charts/rapp-helloworld-provider/templates/_helpers.tpl
new file mode 100644
index 0000000..08fd72b
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-provider/templates/_helpers.tpl
@@ -0,0 +1,62 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "rapp-helloworld-provider.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "rapp-helloworld-provider.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "rapp-helloworld-provider.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "rapp-helloworld-provider.labels" -}}
+helm.sh/chart: {{ include "rapp-helloworld-provider.chart" . }}
+{{ include "rapp-helloworld-provider.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "rapp-helloworld-provider.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "rapp-helloworld-provider.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "rapp-helloworld-provider.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "rapp-helloworld-provider.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
diff --git a/service-exposure/charts/rapp-helloworld-provider/templates/clusterrole.yaml b/service-exposure/charts/rapp-helloworld-provider/templates/clusterrole.yaml
new file mode 100644
index 0000000..7e78328
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-provider/templates/clusterrole.yaml
@@ -0,0 +1,41 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+{{- if .Values.rbac.create -}}
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ labels:
+ app: {{ template "rapp-helloworld-provider.name" .}}
+ chart: {{ .Chart.Name }}-{{ .Chart.Version }}
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ name: {{ template "rapp-helloworld-provider.fullname" . }}
+ namespace: {{ .Release.Namespace }}
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: cluster-admin
+subjects:
+- kind: ServiceAccount
+ name: {{ template "rapp-helloworld-provider.fullname" . }}
+ namespace: {{ .Release.Namespace }}
+{{- end -}}
diff --git a/service-exposure/charts/rapp-helloworld-provider/templates/deployment.yaml b/service-exposure/charts/rapp-helloworld-provider/templates/deployment.yaml
new file mode 100644
index 0000000..6ca7348
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-provider/templates/deployment.yaml
@@ -0,0 +1,82 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ include "rapp-helloworld-provider.fullname" . }}
+ labels:
+ {{- include "rapp-helloworld-provider.labels" . | nindent 4 }}
+spec:
+ {{- if not .Values.autoscaling.enabled }}
+ replicas: {{ .Values.replicaCount }}
+ {{- end }}
+ selector:
+ matchLabels:
+ {{- include "rapp-helloworld-provider.selectorLabels" . | nindent 6 }}
+ template:
+ metadata:
+ {{- with .Values.podAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ labels:
+ {{- include "rapp-helloworld-provider.selectorLabels" . | nindent 8 }}
+ spec:
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ include "rapp-helloworld-provider.serviceAccountName" . }}
+ securityContext:
+ {{- toYaml .Values.podSecurityContext | nindent 8 }}
+ containers:
+ - name: {{ .Chart.Name }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 12 }}
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ ports:
+ - name: http
+ containerPort: 9000
+ protocol: TCP
+ livenessProbe:
+ httpGet:
+ path: /
+ port: http
+ readinessProbe:
+ httpGet:
+ path: /
+ port: http
+ resources:
+ {{- toYaml .Values.resources | nindent 12 }}
+ {{- with .Values.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
diff --git a/service-exposure/charts/rapp-helloworld-provider/templates/hpa.yaml b/service-exposure/charts/rapp-helloworld-provider/templates/hpa.yaml
new file mode 100644
index 0000000..3a69608
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-provider/templates/hpa.yaml
@@ -0,0 +1,49 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+{{- if .Values.autoscaling.enabled }}
+apiVersion: autoscaling/v2beta1
+kind: HorizontalPodAutoscaler
+metadata:
+ name: {{ include "rapp-helloworld-provider.fullname" . }}
+ labels:
+ {{- include "rapp-helloworld-provider.labels" . | nindent 4 }}
+spec:
+ scaleTargetRef:
+ apiVersion: apps/v1
+ kind: Deployment
+ name: {{ include "rapp-helloworld-provider.fullname" . }}
+ minReplicas: {{ .Values.autoscaling.minReplicas }}
+ maxReplicas: {{ .Values.autoscaling.maxReplicas }}
+ metrics:
+ {{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
+ - type: Resource
+ resource:
+ name: cpu
+ targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
+ {{- end }}
+ {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
+ - type: Resource
+ resource:
+ name: memory
+ targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
+ {{- end }}
+{{- end }}
diff --git a/service-exposure/charts/rapp-helloworld-provider/templates/ingress.yaml b/service-exposure/charts/rapp-helloworld-provider/templates/ingress.yaml
new file mode 100644
index 0000000..80992c2
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-provider/templates/ingress.yaml
@@ -0,0 +1,62 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+{{- if .Values.ingress.enabled -}}
+{{- $fullName := include "rapp-helloworld-provider.fullname" . -}}
+{{- $svcPort := .Values.service.port -}}
+{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1beta1
+{{- else -}}
+apiVersion: extensions/v1beta1
+{{- end }}
+kind: Ingress
+metadata:
+ name: {{ $fullName }}
+ labels:
+ {{- include "rapp-helloworld-provider.labels" . | nindent 4 }}
+ {{- with .Values.ingress.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ {{- if .Values.ingress.tls }}
+ tls:
+ {{- range .Values.ingress.tls }}
+ - hosts:
+ {{- range .hosts }}
+ - {{ . | quote }}
+ {{- end }}
+ secretName: {{ .secretName }}
+ {{- end }}
+ {{- end }}
+ rules:
+ {{- range .Values.ingress.hosts }}
+ - host: {{ .host | quote }}
+ http:
+ paths:
+ {{- range .paths }}
+ - path: {{ .path }}
+ backend:
+ serviceName: {{ $fullName }}
+ servicePort: {{ $svcPort }}
+ {{- end }}
+ {{- end }}
+ {{- end }}
diff --git a/service-exposure/charts/rapp-helloworld-provider/templates/service.yaml b/service-exposure/charts/rapp-helloworld-provider/templates/service.yaml
new file mode 100644
index 0000000..1adda51
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-provider/templates/service.yaml
@@ -0,0 +1,36 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "rapp-helloworld-provider.fullname" . }}
+ labels:
+ {{- include "rapp-helloworld-provider.labels" . | nindent 4 }}
+spec:
+ type: {{ .Values.service.type }}
+ ports:
+ - port: {{ .Values.service.port }}
+ targetPort: http
+ protocol: TCP
+ name: http
+ selector:
+ {{- include "rapp-helloworld-provider.selectorLabels" . | nindent 4 }}
diff --git a/service-exposure/charts/rapp-helloworld-provider/templates/serviceaccount.yaml b/service-exposure/charts/rapp-helloworld-provider/templates/serviceaccount.yaml
new file mode 100644
index 0000000..23ca505
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-provider/templates/serviceaccount.yaml
@@ -0,0 +1,33 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "rapp-helloworld-provider.serviceAccountName" . }}
+ labels:
+ {{- include "rapp-helloworld-provider.labels" . | nindent 4 }}
+ {{- with .Values.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/service-exposure/charts/rapp-helloworld-provider/templates/tests/test-connection.yaml b/service-exposure/charts/rapp-helloworld-provider/templates/tests/test-connection.yaml
new file mode 100644
index 0000000..7d295f6
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-provider/templates/tests/test-connection.yaml
@@ -0,0 +1,36 @@
+{{/*
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+*/}}
+apiVersion: v1
+kind: Pod
+metadata:
+ name: "{{ include "rapp-helloworld-provider.fullname" . }}-test-connection"
+ labels:
+ {{- include "rapp-helloworld-provider.labels" . | nindent 4 }}
+ annotations:
+ "helm.sh/hook": test
+spec:
+ containers:
+ - name: wget
+ image: busybox
+ command: ['wget']
+ args: ['{{ include "rapp-helloworld-provider.fullname" . }}:{{ .Values.service.port }}']
+ restartPolicy: Never
diff --git a/service-exposure/charts/rapp-helloworld-provider/values.yaml b/service-exposure/charts/rapp-helloworld-provider/values.yaml
new file mode 100644
index 0000000..bb6ef19
--- /dev/null
+++ b/service-exposure/charts/rapp-helloworld-provider/values.yaml
@@ -0,0 +1,125 @@
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+
+# Default values for rapp-helloworld-provider.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+replicaCount: 1
+
+image:
+ repository: ktimoney/rapps-rapp-helloworld-provider
+ pullPolicy: IfNotPresent
+ # Overrides the image tag whose default is the chart appVersion.
+ tag: "latest"
+
+imagePullSecrets: []
+nameOverride: ""
+fullnameOverride: ""
+
+serviceAccount:
+ # Specifies whether a service account should be created
+ create: true
+ # Annotations to add to the service account
+ annotations: {}
+ # The name of the service account to use.
+ # If not set and create is true, a name is generated using the fullname template
+ name: "rapp-helloworld-provider"
+
+rbac:
+ # Specifies whether rbac should be enabled
+ create: true
+
+podAnnotations: {}
+
+podSecurityContext: {}
+ # fsGroup: 2000
+
+securityContext: {}
+ # capabilities:
+ # drop:
+ # - ALL
+ # readOnlyRootFilesystem: true
+ # runAsNonRoot: true
+ # runAsUser: 1000
+
+service:
+ type: ClusterIP
+ port: 80
+
+ingress:
+ enabled: false
+ annotations: {}
+ # kubernetes.io/ingress.class: nginx
+ # kubernetes.io/tls-acme: "true"
+ hosts:
+ - host: rapp-helloworld-provider
+ paths:
+ - path: /
+ backend:
+ serviceName: rapp-helloworld-provider
+ servicePort: 80
+ tls: []
+ # - secretName: chart-example-tls
+ # hosts:
+ # - chart-example.local
+
+resources: {}
+ # We usually recommend not to specify default resources and to leave this as a conscious
+ # choice for the user. This also increases chances charts run on environments with little
+ # resources, such as Minikube. If you do want to specify resources, uncomment the following
+ # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 128Mi
+
+autoscaling:
+ enabled: false
+ minReplicas: 1
+ maxReplicas: 100
+ targetCPUUtilizationPercentage: 80
+ # targetMemoryUtilizationPercentage: 80
+
+nodeSelector: {}
+
+tolerations: []
+
+affinity: {}
+
+rapp:
+ securityEnabled: true
+ type: provider
+ realm: demo
+ client: demoprovider-cli
+ authenticator: client-jwt
+ roles:
+ - role : provider-viewer
+ grants:
+ - GET
+ - role : provider-admin
+ grants:
+ - GET
+ - POST
+ - PUT
+ - DELETE
+
diff --git a/service-exposure/deploy_rapp.sh b/service-exposure/deploy_rapp.sh
new file mode 100644
index 0000000..4d77350
--- /dev/null
+++ b/service-exposure/deploy_rapp.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+export host=$(minikube ip)
+
+if [ -z "$1" ]
+ then
+ echo "No argument supplied"
+ exit 1
+fi
+
+rapp=$1
+
+echo "Deploying application..."
+echo "------------------------"
+curl http://$host:31570/install?chart=$rapp
+
+echo "\n"
+echo "Waiting for pod to start..."
+echo "---------------------------"
+kubectl wait deployment -n istio-nonrtric $rapp --for=condition=available --timeout=90s
+
+echo ""
+echo "Checking pod status..."
+echo "----------------------"
+kubectl get pods -n istio-nonrtric
+#kubectl get pods --show-labels -n istio-nonrtric
+
+#if [ "$rapp" == "rapp-helloworld-invoker1" ] || [ "$rapp" == "rapp-helloworld-invoker2" ]; then
+if [ "$rapp" != "rapp-helloworld-provider" ]; then
+ echo ""
+ echo "Inspect the log for $rapp..."
+ echo "-----------------------------------------------"
+ kubectl logs -l app.kubernetes.io/name=$rapp -n istio-nonrtric
+fi
+if [ "$rapp" = "rapp-helloworld-invoker1" ]; then
+ echo ""
+ echo "Inspect the log for $rapp jwt sidecar..."
+ echo "-----------------------------------------------------------"
+ kubectl logs -l app.kubernetes.io/name=$rapp -c jwt-proxy -n istio-nonrtric
+fi
diff --git a/service-exposure/keycloak.sh b/service-exposure/keycloak.sh
new file mode 100644
index 0000000..8338b43
--- /dev/null
+++ b/service-exposure/keycloak.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+
+if [ -z "$1" ]
+ then
+ echo "No argument supplied"
+ exit 1
+fi
+
+OPERATION=$1
+
+if [ "$OPERATION" == "deploy" ]; then
+ echo "Deploying applications..."
+ echo "-------------------------"
+ istioctl kube-inject -f postgres.yaml | kubectl apply -f -
+ sleep 10
+ istioctl kube-inject -f keycloak.yaml | kubectl apply -f -
+ echo ""
+ echo "Waiting for pods to start..."
+ echo "----------------------------"
+ kubectl wait deployment -n default postgres --for=condition=available --timeout=90s
+ kubectl wait deployment -n default keycloak --for=condition=available --timeout=300s
+ echo ""
+ echo "Checking pod status..."
+ echo "----------------------"
+ kubectl get pods -n default
+elif [ "$OPERATION" == "undeploy" ]; then
+ echo "Undeploying applications..."
+ echo "---------------------------"
+ kubectl delete -f keycloak.yaml
+ kubectl delete -f postgres.yaml
+else
+ echo "Unrecogized operation ${OPERATION}"
+ exit 1
+fi
+
+exit 0
diff --git a/service-exposure/keycloak.yaml b/service-exposure/keycloak.yaml
index d611c6d..c8c4a63 100644
--- a/service-exposure/keycloak.yaml
+++ b/service-exposure/keycloak.yaml
@@ -20,7 +20,7 @@
apiVersion: v1
kind: ServiceAccount
metadata:
- name: keycloak
+ name: keycloak
namespace: default
---
apiVersion: v1
@@ -31,12 +31,12 @@
app: keycloak
spec:
type: ExternalName
- externalName: keycloak.local
+ externalName: keycloak.local
ports:
- name: http
port: 8080
targetPort: 8080
- nodePort: 31560
+ nodePort: 31560
- name: https
port: 8443
targetPort: 8443
@@ -65,20 +65,20 @@
initContainers:
- name: init-postgres
image: busybox
- imagePullPolicy: IfNotPresent
+ imagePullPolicy: IfNotPresent
command: ['sh', '-c', 'until nc -vz postgres 5432; do echo waiting for postgres db; sleep 2; done;']
- serviceAccountName: keycloak
+ serviceAccountName: keycloak
containers:
- name: keycloak
- image: quay.io/keycloak/keycloak:latest
- imagePullPolicy: IfNotPresent
+ image: quay.io/keycloak/keycloak:16.1.1
+ imagePullPolicy: IfNotPresent
env:
- name: KEYCLOAK_USER
value: "admin"
- name: KEYCLOAK_PASSWORD
value: "admin"
- name: KEYCLOAK_HTTPS_PORT
- value: "8443"
+ value: "8443"
- name: PROXY_ADDRESS_FORWARDING
value: "true"
- name: MANAGEMENT_USER
@@ -89,18 +89,18 @@
value: "false"
- name: DB_VENDOR
value: "postgres"
- - name: DB_ADDR
+ - name: DB_ADDR
value: "postgres"
- - name: DB_PORT
+ - name: DB_PORT
value: "5432"
- name: DB_DATABASE
value: "keycloak"
- name: DB_USER
- value: "keycloak"
+ value: "keycloak"
- name : DB_PASSWORD
- value: "keycloak"
- - name : X509_CA_BUNDLE
- value: /etc/x509/https/rootCA.crt
+ value: "keycloak"
+ - name : X509_CA_BUNDLE
+ value: /etc/x509/https/rootCA.crt
ports:
- name: http
containerPort: 8080
@@ -111,12 +111,12 @@
path: /auth/realms/master
port: 8080
volumeMounts:
- - name: keycloak-certs
- mountPath: /etc/x509/https
+ - name: keycloak-certs
+ mountPath: /etc/x509/https
volumes:
- - name: keycloak-certs
+ - name: keycloak-certs
hostPath:
- path: /var/keycloak/certs
+ path: /var/keycloak/certs
type: Directory
---
apiVersion: networking.istio.io/v1alpha3
@@ -134,7 +134,7 @@
tls:
mode: PASSTHROUGH
hosts:
- - keycloak.est.tech
+ - keycloak.oran.org
- port:
number: 80
name: http
@@ -148,14 +148,14 @@
name: keycloak-tls-vs
spec:
hosts:
- - keycloak.est.tech
+ - keycloak.oran.org
gateways:
- kcgateway
tls:
- match:
- port: 443
sniHosts:
- - keycloak.est.tech
+ - keycloak.oran.org
route:
- destination:
host: keycloak.default.svc.cluster.local
@@ -170,7 +170,7 @@
hosts:
- "*"
gateways:
- - kcgateway
+ - kcgateway
http:
- name: "keycloak-routes"
match:
diff --git a/service-exposure/postgres.yaml b/service-exposure/postgres.yaml
index 588dd8e..d0e71c5 100644
--- a/service-exposure/postgres.yaml
+++ b/service-exposure/postgres.yaml
@@ -60,7 +60,7 @@
DO $$
BEGIN
IF NOT EXISTS (SELECT FROM pg_user WHERE usename = 'capif') THEN
- CREATE USER capif WITH PASSWORD 'capif';
+ CREATE USER capif WITH PASSWORD 'capif';
GRANT ALL PRIVILEGES ON DATABASE capif TO capif;
END IF;
END
@@ -77,11 +77,11 @@
app: postgres
ports:
- protocol: TCP
- port: 5432
+ port: 5432
nodePort: 30032
- targetPort: 5432
+ targetPort: 5432
---
-apiVersion: apps/v1
+apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
@@ -101,17 +101,17 @@
containers:
- image: nexus3.onap.org:10001/postgres
name: postgres
- imagePullPolicy: IfNotPresent
+ imagePullPolicy: IfNotPresent
env:
- name: POSTGRES_DB
- value: keycloak
+ value: keycloak
- name: POSTGRES_USER
- value: keycloak
+ value: keycloak
- name: POSTGRES_PASSWORD
- value: keycloak
+ value: keycloak
- name: PGDATA
- value: /var/lib/pgsql/data
- lifecycle:
+ value: /var/lib/pgsql/data
+ lifecycle:
postStart:
exec:
command: [ "/bin/sh", "-c", "sleep 10 && psql -U $POSTGRES_USER -f /init.sql" ]
@@ -130,16 +130,16 @@
initialDelaySeconds: 15
timeoutSeconds: 2
ports:
- - containerPort: 5432
+ - containerPort: 5432
name: postgres
volumeMounts:
- name: postgres-persistent-storage
- mountPath: /var/lib/pgsql/data
- - name : tmp-dir
+ mountPath: /var/lib/pgsql/data
+ - name : tmp-dir
mountPath: /tmp
- name: db-init
- mountPath: /init.sql
- subPath: init.sql
+ mountPath: /init.sql
+ subPath: init.sql
volumes:
- name: postgres-persistent-storage
persistentVolumeClaim:
@@ -147,7 +147,7 @@
- name: tmp-dir
hostPath:
path: /tmp
- type: Directory
+ type: Directory
- name: db-init
configMap:
name: db-init
diff --git a/service-exposure/rapps-helm-installer.go b/service-exposure/rapps-helm-installer.go
index dc92fc7..0dc9341 100644
--- a/service-exposure/rapps-helm-installer.go
+++ b/service-exposure/rapps-helm-installer.go
@@ -17,7 +17,6 @@
// limitations under the License.
// ========================LICENSE_END===================================
//
-
package main
import (
@@ -70,6 +69,7 @@
SecurityEnabled bool
Realm string
Client string
+ Authenticator string
Roles []struct {
Role string
Grants []string
@@ -113,30 +113,10 @@
if err != nil {
msg = err.Error()
} else {
- if rapp.SecurityEnabled && rapp.Type == "provider" {
- // keycloak client setup
- fmt.Println("Setting up keycloak")
- _, err = http.Get("http://rapps-keycloak-mgr.default/create?realm=" + rapp.Realm + "&name=" + rapp.Client + "&role=" + rapp.Roles[0].Role)
- if err != nil {
- msg = err.Error()
- } else {
- fmt.Println("Setting up istio")
- _, err := http.Get("http://rapps-istio-mgr.default/create?name=" + chartName + "&realm=" + rapp.Realm + "&role=" + rapp.Roles[0].Role + "&method=" + rapp.Roles[0].Grants[0])
- if err != nil {
- msg = err.Error()
- } else {
- // Install chart
- fmt.Printf("Installing chart %s to %s namespace\n", chartName, namespace)
- chart, err = installHelmChart(install)
- if err != nil {
- msg = "Error occurred during installation " + err.Error()
- } else {
- msg = "Successfully installed release: " + chart
- }
- }
- }
+ err := installSecurity(rapp)
+ if err != nil {
+ msg = err.Error()
} else {
- // Install chart
fmt.Printf("Installing chart %s to %s namespace\n", chartName, namespace)
chart, err = installHelmChart(install)
if err != nil {
@@ -144,8 +124,8 @@
} else {
msg = "Successfully installed release: " + chart
}
- }
+ }
}
}
registrerRapp(chartName, rapp.Type)
@@ -159,6 +139,54 @@
res.Write(data)
}
+func installSecurity(rapp Rapp) error {
+ var url string
+ var params string
+ role := rapp.Roles[0].Role
+ grants := rapp.Roles[0].Grants[0]
+ realm := rapp.Realm
+ client := rapp.Client
+ authenticator := rapp.Authenticator
+
+ if !rapp.SecurityEnabled {
+ return nil
+ }
+ // Different security requirements depending on the rapp type
+ if rapp.Type == "provider" {
+ // keycloak client setup
+ fmt.Println("Setting up keycloak")
+ url = "http://rapps-keycloak-mgr.default/create?"
+ params = "realm=" + realm + "&name=" + client + "&role=" + role + "&authType=" + authenticator
+ url += params
+ _, err := http.Get(url)
+ if err != nil {
+ return err
+ } else {
+ fmt.Println("Setting up istio")
+ url = "http://rapps-istio-mgr.default/create-policy?"
+ params = "name=" + chartName + "&realm=" + realm + "&role=" + role + "&method=" + grants
+ url += params
+
+ _, err := http.Get(url)
+ if err != nil {
+ return err
+ }
+ }
+ } else {
+ fmt.Println("Setting up istio")
+ url = "http://rapps-istio-mgr.default/create-filter?"
+ params = "name=" + chartName + "&realm=" + realm + "&client=" + client + "&authType=" + authenticator
+ url += params
+ _, err := http.Get(url)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+
+}
+
func runUninstall(res http.ResponseWriter, req *http.Request) {
query := req.URL.Query()
chartName = query.Get("chart")
@@ -178,19 +206,9 @@
} else {
msg = "Successfully uninstalled release: " + chart
}
- if rapp.SecurityEnabled && rapp.Type == "provider" {
- // Remove istio objects for rapp
- fmt.Println("Removing istio services")
- _, err := http.Get("http://rapps-istio-mgr.default/remove?name=" + chartName)
- if err != nil {
- msg = err.Error()
- }
- // remove keycloak client
- fmt.Println("Removing keycloak client")
- _, err = http.Get("http://rapps-keycloak-mgr.default/remove?realm=" + rapp.Realm + "&name=" + rapp.Client + "&role=" + rapp.Roles[0].Role)
- if err != nil {
- msg = err.Error()
- }
+ err := uninstallSecurity(rapp, chartName)
+ if err != nil {
+ msg = err.Error()
}
}
unregistrerRapp(chartName, rapp.Type)
@@ -204,6 +222,45 @@
res.Write(data)
}
+func uninstallSecurity(rapp Rapp, chartName string) error {
+ var url string
+ var params string
+ role := rapp.Roles[0].Role
+ realm := rapp.Realm
+ client := rapp.Client
+ authenticator := rapp.Authenticator
+
+ if !rapp.SecurityEnabled {
+ return nil
+ }
+ if rapp.Type == "provider" {
+ // Remove istio objects for rapp
+ fmt.Println("Removing istio services")
+ _, err := http.Get("http://rapps-istio-mgr.default/remove-policy?name=" + chartName)
+ if err != nil {
+ return err
+ }
+ // remove keycloak client
+ fmt.Println("Removing keycloak client")
+ url = "http://rapps-keycloak-mgr.default/remove?"
+ params = "name=" + client + "&realm=" + realm + "&role=" + role + "&authType=" + authenticator
+ url += params
+ _, err = http.Get(url)
+ if err != nil {
+ return err
+ }
+ }
+ if rapp.Type == "invoker" {
+ // Remove istio objects for rapp
+ fmt.Println("Removing istio services")
+ _, err := http.Get("http://rapps-istio-mgr.default/remove-filter?name=" + chartName)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
func runList(res http.ResponseWriter, req *http.Request) {
chartInfo := list()
// create response binary data
@@ -480,7 +537,7 @@
id serial PRIMARY KEY,
name VARCHAR ( 50 ) UNIQUE NOT NULL,
type VARCHAR ( 50 ) NOT NULL,
- created_on TIMESTAMP DEFAULT NOW()
+ created_on TIMESTAMP DEFAULT NOW()
);`
_, err = db.Exec(createStmt)
if err != nil {
diff --git a/service-exposure/rapps-helm-installer.yaml b/service-exposure/rapps-helm-installer.yaml
index 19969db..e5cb1ea 100644
--- a/service-exposure/rapps-helm-installer.yaml
+++ b/service-exposure/rapps-helm-installer.yaml
@@ -50,7 +50,7 @@
template:
metadata:
labels:
- app: rapps-helm-installer
+ app: rapps-helm-installer
version: v1
spec:
containers:
@@ -58,7 +58,7 @@
image: ktimoney/rapps-helm-installer
imagePullPolicy: IfNotPresent
ports:
- - containerPort: 9000
+ - containerPort: 9000
resources:
limits:
memory: 256Mi
@@ -67,7 +67,7 @@
memory: 128Mi
cpu: "80m"
serviceAccountName: helm-app
- replicas: 1
+ replicas: 1
---
apiVersion: v1
kind: Service
@@ -79,7 +79,7 @@
app: rapps-helm-installer
ports:
- protocol: TCP
- port: 80
- targetPort: 9000
- nodePort: 31570
+ port: 80
+ targetPort: 9000
+ nodePort: 31570
type: NodePort
diff --git a/service-exposure/rapps-istio-mgr.go b/service-exposure/rapps-istio-mgr.go
index 5a0761b..fb584bd 100644
--- a/service-exposure/rapps-istio-mgr.go
+++ b/service-exposure/rapps-istio-mgr.go
@@ -17,7 +17,6 @@
// limitations under the License.
// ========================LICENSE_END===================================
//
-
package main
import (
@@ -25,6 +24,7 @@
"context"
"fmt"
netv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1"
+ netv1alpha3 "istio.io/client-go/pkg/apis/networking/v1alpha3"
secv1beta1 "istio.io/client-go/pkg/apis/security/v1beta1"
versioned "istio.io/client-go/pkg/clientset/versioned"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -35,102 +35,27 @@
"net/http"
"os"
"path/filepath"
- "strings"
+ "text/template"
)
const (
NAMESPACE = "istio-nonrtric"
)
-var gatewayManifest = `
-apiVersion: networking.istio.io/v1beta1
-kind: Gateway
-metadata:
- name: nonrtric-istio-RAPP-NAME-gateway
- namespace: RAPP-NS
-spec:
- selector:
- istio: ingressgateway # use Istio gateway implementation
- servers:
- - port:
- number: 80
- name: http
- protocol: HTTP
- hosts:
- - "*"
-`
+type TemplateConfig struct {
+ Name string
+ Namespace string
+ Realm string
+ Client string
+ Authenticator string
+ Role string
+ Method string
+}
-var virtualServiceManifest = `
-apiVersion: networking.istio.io/v1beta1
-kind: VirtualService
-metadata:
- name: nonrtric-istio-RAPP-NAME-vs
- namespace: RAPP-NS
-spec:
- hosts:
- - "*"
- gateways:
- - nonrtric-istio-RAPP-NAME-gateway
- http:
- - name: "RAPP-NAME-routes"
- match:
- - uri:
- prefix: "/RAPP-NAME"
- route:
- - destination:
- port:
- number: 80
- host: RAPP-NAME.RAPP-NS.svc.cluster.local
-`
+var inputs TemplateConfig
+var appName string
-var requestAuthenticationManifest = `
-apiVersion: security.istio.io/v1beta1
-kind: RequestAuthentication
-metadata:
- name: "jwt-RAPP-NAME"
- namespace: RAPP-NS
-spec:
- selector:
- matchLabels:
- app.kubernetes.io/instance: RAPP-NAME
- jwtRules:
- - issuer: "http://192.168.49.2:31560/auth/realms/REALM-NAME"
- jwksUri: "http://192.168.49.2:31560/auth/realms/REALM-NAME/protocol/openid-connect/certs"
- - issuer: "http://keycloak.default:8080/auth/realms/REALM-NAME"
- jwksUri: "http://keycloak.default:8080/auth/realms/REALM-NAME/protocol/openid-connect/certs"
- - issuer: "https://192.168.49.2:31561/auth/realms/REALM-NAME"
- jwksUri: "https://192.168.49.2:31561/auth/realms/REALM-NAME/protocol/openid-connect/certs"
- - issuer: "https://keycloak.default:8443/auth/realms/REALM-NAME"
- jwksUri: "https://keycloak.default:8443/auth/realms/REALM-NAME/protocol/openid-connect/certs"
- - issuer: "https://keycloak.est.tech:443/auth/realms/REALM-NAME"
- jwksUri: "https://keycloak.default:8443/auth/realms/REALM-NAME/protocol/openid-connect/certs"
- - issuer: "http://istio-ingressgateway.istio-system:80/auth/realms/REALM-NAME"
- jwksUri: "http://keycloak.default:8080/auth/realms/REALM-NAME/protocol/openid-connect/certs"
-`
-
-var authorizationPolicyManifest = `
-apiVersion: "security.istio.io/v1beta1"
-kind: "AuthorizationPolicy"
-metadata:
- name: "RAPP-NAME-policy"
- namespace: RAPP-NS
-spec:
- selector:
- matchLabels:
- app.kubernetes.io/instance: RAPP-NAME
- action: ALLOW
- rules:
- - from:
- - source:
- requestPrincipals: ["http://192.168.49.2:31560/auth/realms/REALM-NAME/", "http://keycloak.default:8080/auth/realms/REALM-NAME/", "https://192.168.49.2:31561/auth/realms/REALM-NAME/", "https://keycloak.default:8443/auth/realms/REALM-NAME/", "https://keycloak.est.tech:443/auth/realms/REALM-NAME/", "http://istio-ingressgateway.istio-system:80/auth/realms/REALM-NAME/"]
- - to:
- - operation:
- methods: ["METHOD-NAME"]
- paths: ["/RAPP-NAME"]
- when:
- - key: request.auth.claims[clientRole]
- values: ["ROLE-NAME"]
-`
+var config *template.Template
func connectToK8s() *versioned.Clientset {
config, err := rest.InClusterConfig()
@@ -159,13 +84,17 @@
return ic
}
-func createGateway(clientset *versioned.Clientset, appName string) (string, error) {
+func createGateway(clientset *versioned.Clientset) (string, error) {
gtClient := clientset.NetworkingV1beta1().Gateways(NAMESPACE)
- manifest := strings.Replace(gatewayManifest, "RAPP-NAME", appName, -1)
- manifest = strings.Replace(manifest, "RAPP-NS", NAMESPACE, -1)
+ config = template.Must(template.ParseFiles("./templates/Gateway-template.txt"))
+ var manifest bytes.Buffer
+ err := config.Execute(&manifest, inputs)
+ if err != nil {
+ return "", err
+ }
gt := &netv1beta1.Gateway{}
- dec := k8Yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(manifest)), 1000)
+ dec := k8Yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(manifest.String())), 1000)
if err := dec.Decode(>); err != nil {
return "", err
@@ -181,13 +110,17 @@
return result.GetName(), nil
}
-func createVirtualService(clientset *versioned.Clientset, appName string) (string, error) {
+func createVirtualService(clientset *versioned.Clientset) (string, error) {
vsClient := clientset.NetworkingV1beta1().VirtualServices(NAMESPACE)
- manifest := strings.Replace(virtualServiceManifest, "RAPP-NAME", appName, -1)
- manifest = strings.Replace(manifest, "RAPP-NS", NAMESPACE, -1)
+ config = template.Must(template.ParseFiles("./templates/VirtualService-template.txt"))
+ var manifest bytes.Buffer
+ err := config.Execute(&manifest, inputs)
+ if err != nil {
+ return "", err
+ }
vs := &netv1beta1.VirtualService{}
- dec := k8Yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(manifest)), 1000)
+ dec := k8Yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(manifest.String())), 1000)
if err := dec.Decode(&vs); err != nil {
return "", err
@@ -203,14 +136,17 @@
return result.GetName(), nil
}
-func createRequestAuthentication(clientset *versioned.Clientset, appName, realmName string) (string, error) {
+func createRequestAuthentication(clientset *versioned.Clientset) (string, error) {
raClient := clientset.SecurityV1beta1().RequestAuthentications(NAMESPACE)
- manifest := strings.Replace(requestAuthenticationManifest, "RAPP-NAME", appName, -1)
- manifest = strings.Replace(manifest, "REALM-NAME", realmName, -1)
- manifest = strings.Replace(manifest, "RAPP-NS", NAMESPACE, -1)
+ config = template.Must(template.ParseFiles("./templates/RequestAuthentication-template.txt"))
+ var manifest bytes.Buffer
+ err := config.Execute(&manifest, inputs)
+ if err != nil {
+ return "", err
+ }
ra := &secv1beta1.RequestAuthentication{}
- dec := k8Yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(manifest)), 1000)
+ dec := k8Yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(manifest.String())), 1000)
if err := dec.Decode(&ra); err != nil {
return "", err
@@ -226,16 +162,17 @@
return result.GetName(), nil
}
-func createAuthorizationPolicy(clientset *versioned.Clientset, appName, realmName, roleName, methodName string) (string, error) {
+func createAuthorizationPolicy(clientset *versioned.Clientset) (string, error) {
apClient := clientset.SecurityV1beta1().AuthorizationPolicies(NAMESPACE)
- manifest := strings.Replace(authorizationPolicyManifest, "RAPP-NAME", appName, -1)
- manifest = strings.Replace(manifest, "REALM-NAME", realmName, -1)
- manifest = strings.Replace(manifest, "ROLE-NAME", roleName, -1)
- manifest = strings.Replace(manifest, "METHOD-NAME", methodName, -1)
- manifest = strings.Replace(manifest, "RAPP-NS", NAMESPACE, -1)
+ config = template.Must(template.ParseFiles("./templates/AuthorizationPolicy-template.txt"))
+ var manifest bytes.Buffer
+ err := config.Execute(&manifest, inputs)
+ if err != nil {
+ return "", err
+ }
ap := &secv1beta1.AuthorizationPolicy{}
- dec := k8Yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(manifest)), 1000)
+ dec := k8Yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(manifest.String())), 1000)
if err := dec.Decode(&ap); err != nil {
return "", err
@@ -251,7 +188,33 @@
return result.GetName(), nil
}
-func removeGateway(clientset *versioned.Clientset, appName string) {
+func createEnvoyFilter(clientset *versioned.Clientset) (string, error) {
+ efClient := clientset.NetworkingV1alpha3().EnvoyFilters(NAMESPACE)
+ config = template.Must(template.ParseFiles("./templates/EnvoyFilter-template.txt"))
+ var manifest bytes.Buffer
+ err := config.Execute(&manifest, inputs)
+ if err != nil {
+ return "", err
+ }
+
+ ef := &netv1alpha3.EnvoyFilter{}
+ dec := k8Yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(manifest.String())), 1000)
+
+ if err = dec.Decode(&ef); err != nil {
+ return "", err
+ }
+
+ result, err := efClient.Create(context.TODO(), ef, metav1.CreateOptions{})
+
+ if err != nil {
+ return "", err
+ }
+
+ fmt.Printf("Create Envoy Filter %s \n", result.GetName())
+ return result.GetName(), nil
+}
+
+func removeGateway(clientset *versioned.Clientset) {
gtClient := clientset.NetworkingV1beta1().Gateways(NAMESPACE)
err := gtClient.Delete(context.TODO(), "nonrtric-istio-"+appName+"-gateway", metav1.DeleteOptions{})
if err != nil {
@@ -261,7 +224,7 @@
}
}
-func removeVirtualService(clientset *versioned.Clientset, appName string) {
+func removeVirtualService(clientset *versioned.Clientset) {
vsClient := clientset.NetworkingV1beta1().VirtualServices(NAMESPACE)
err := vsClient.Delete(context.TODO(), "nonrtric-istio-"+appName+"-vs", metav1.DeleteOptions{})
if err != nil {
@@ -271,7 +234,7 @@
}
}
-func removeRequestAuthentication(clientset *versioned.Clientset, appName string) {
+func removeRequestAuthentication(clientset *versioned.Clientset) {
raClient := clientset.SecurityV1beta1().RequestAuthentications(NAMESPACE)
err := raClient.Delete(context.TODO(), "jwt-"+appName, metav1.DeleteOptions{})
if err != nil {
@@ -281,7 +244,7 @@
}
}
-func removeAuthorizationPolicy(clientset *versioned.Clientset, appName string) {
+func removeAuthorizationPolicy(clientset *versioned.Clientset) {
apClient := clientset.SecurityV1beta1().AuthorizationPolicies(NAMESPACE)
err := apClient.Delete(context.TODO(), appName+"-policy", metav1.DeleteOptions{})
if err != nil {
@@ -291,30 +254,41 @@
}
}
+func removeEnvoyFilter(clientset *versioned.Clientset) {
+ efClient := clientset.NetworkingV1alpha3().EnvoyFilters(NAMESPACE)
+ err := efClient.Delete(context.TODO(), appName+"-outbound-filter", metav1.DeleteOptions{})
+ if err != nil {
+ fmt.Println(err)
+ } else {
+ fmt.Println("Deleted EnvoyFilter " + appName + "-outbound-filter")
+ }
+}
+
func createIstioPolicy(res http.ResponseWriter, req *http.Request) {
query := req.URL.Query()
realmName := query.Get("realm")
appName := query.Get("name")
roleName := query.Get("role")
methodName := query.Get("method")
+ inputs = TemplateConfig{Name: appName, Namespace: NAMESPACE, Realm: realmName, Role: roleName, Method: methodName }
var msg string
clientset := connectToK8s()
- _, err := createGateway(clientset, appName)
+ _, err := createGateway(clientset)
if err != nil {
msg = err.Error()
fmt.Println(err.Error())
} else {
- _, err := createVirtualService(clientset, appName)
+ _, err := createVirtualService(clientset)
if err != nil {
msg = err.Error()
fmt.Println(err.Error())
} else {
- _, err := createRequestAuthentication(clientset, appName, realmName)
+ _, err := createRequestAuthentication(clientset)
if err != nil {
msg = err.Error()
fmt.Println(err.Error())
} else {
- _, err := createAuthorizationPolicy(clientset, appName, realmName, roleName, methodName)
+ _, err := createAuthorizationPolicy(clientset)
if err != nil {
msg = err.Error()
fmt.Println(err.Error())
@@ -331,20 +305,51 @@
res.Write(data)
}
+func createIstioFilter(res http.ResponseWriter, req *http.Request) {
+ query := req.URL.Query()
+ realmName := query.Get("realm")
+ clientId := query.Get("client")
+ appName := query.Get("name")
+ authType := query.Get("authType")
+ inputs = TemplateConfig{Name: appName, Namespace: NAMESPACE, Realm: realmName, Client: clientId, Authenticator: authType}
+ var msg string
+ clientset := connectToK8s()
+ _, err := createEnvoyFilter(clientset)
+ if err != nil {
+ msg = err.Error()
+ fmt.Println(err.Error())
+ }
+ // create response binary data
+ data := []byte(msg) // slice of bytes
+ // write `data` to response
+ res.Write(data)
+}
+
func removeIstioPolicy(res http.ResponseWriter, req *http.Request) {
query := req.URL.Query()
- appName := query.Get("name")
+ appName = query.Get("name")
clientset := connectToK8s()
- removeAuthorizationPolicy(clientset, appName)
- removeRequestAuthentication(clientset, appName)
- removeVirtualService(clientset, appName)
- removeGateway(clientset, appName)
+ removeAuthorizationPolicy(clientset)
+ removeRequestAuthentication(clientset)
+ removeVirtualService(clientset)
+ removeGateway(clientset)
+}
+
+func removeIstioFilter(res http.ResponseWriter, req *http.Request) {
+ query := req.URL.Query()
+ appName = query.Get("name")
+ clientset := connectToK8s()
+ removeEnvoyFilter(clientset)
}
func main() {
- createIstioHandler := http.HandlerFunc(createIstioPolicy)
- http.Handle("/create", createIstioHandler)
- removeIstioHandler := http.HandlerFunc(removeIstioPolicy)
- http.Handle("/remove", removeIstioHandler)
+ createIstioPolicyHandler := http.HandlerFunc(createIstioPolicy)
+ http.Handle("/create-policy", createIstioPolicyHandler)
+ removeIstioPolicyHandler := http.HandlerFunc(removeIstioPolicy)
+ http.Handle("/remove-policy", removeIstioPolicyHandler)
+ createIstioFilterHandler := http.HandlerFunc(createIstioFilter)
+ http.Handle("/create-filter", createIstioFilterHandler)
+ removeIstioFilterHandler := http.HandlerFunc(removeIstioFilter)
+ http.Handle("/remove-filter", removeIstioFilterHandler)
http.ListenAndServe(":9000", nil)
}
diff --git a/service-exposure/rapps-istio-mgr.yaml b/service-exposure/rapps-istio-mgr.yaml
index 6003bb5..92d3f3a 100644
--- a/service-exposure/rapps-istio-mgr.yaml
+++ b/service-exposure/rapps-istio-mgr.yaml
@@ -31,7 +31,7 @@
template:
metadata:
labels:
- app: rapps-istio-mgr
+ app: rapps-istio-mgr
version: v1
spec:
containers:
@@ -39,7 +39,7 @@
image: ktimoney/rapps-istio-mgr
imagePullPolicy: IfNotPresent
ports:
- - containerPort: 9000
+ - containerPort: 9000
resources:
limits:
memory: 256Mi
@@ -48,7 +48,7 @@
memory: 128Mi
cpu: "80m"
serviceAccountName: helm-app
- replicas: 1
+ replicas: 1
---
apiVersion: v1
kind: Service
@@ -60,7 +60,7 @@
app: rapps-istio-mgr
ports:
- protocol: TCP
- port: 80
- targetPort: 9000
- nodePort: 31590
+ port: 80
+ targetPort: 9000
+ nodePort: 31551
type: NodePort
diff --git a/service-exposure/rapps-jwt.go b/service-exposure/rapps-jwt.go
new file mode 100644
index 0000000..d220458
--- /dev/null
+++ b/service-exposure/rapps-jwt.go
@@ -0,0 +1,227 @@
+// -
+// ========================LICENSE_START=================================
+// O-RAN-SC
+// %%
+// Copyright (C) 2022: Nordix Foundation
+// %%
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ========================LICENSE_END===================================
+//
+package main
+
+import (
+ "crypto/tls"
+ "crypto/x509"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "io/ioutil"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ kubernetes "k8s.io/client-go/kubernetes"
+ "k8s.io/client-go/rest"
+ "net/http"
+ "net/url"
+ "rapps/utils/generatejwt"
+ "context"
+ "net"
+ "time"
+)
+
+type Jwttoken struct {
+ Access_token string
+ Expires_in int
+ Refresh_expires_in int
+ Refresh_token string
+ Token_type string
+ Not_before_policy int
+ Session_state string
+ Scope string
+}
+
+var keycloakHost string
+var keycloakPort string
+var keycloakAlias string
+var realmName string
+var clientId string
+var namespace string
+var authenticator string
+var healthy bool = true
+var jwt Jwttoken
+
+const (
+ scope = "email"
+ client_assertion_type = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
+)
+
+func getToken(res http.ResponseWriter, req *http.Request) {
+ var resp = &http.Response{}
+ var err error
+ authenticator = req.Header.Get("authenticator")
+ clientId = req.Header.Get("client")
+ realmName = req.Header.Get("realm")
+ namespace = req.Header.Get("ns")
+ keycloakUrl := "http://" + keycloakHost + ":" + keycloakPort + "/auth/realms/" + realmName + "/protocol/openid-connect/token"
+ fmt.Printf("Making token request to %s\n", keycloakUrl)
+ res.Header().Set("Content-type", "application/json")
+ res.Header().Set("Authorization", "")
+
+ if authenticator == "client-jwt" {
+ resp, err = getJwtToken(keycloakUrl, clientId)
+ } else if authenticator == "client-x509" {
+ resp, err = getx509Token(keycloakUrl, clientId)
+ } else {
+ resp, err = getSecretToken(keycloakUrl, clientId)
+ }
+
+ if err != nil {
+ fmt.Println(err)
+ res.WriteHeader(http.StatusInternalServerError)
+ res.Write([]byte(err.Error()))
+ panic("Something wrong with the credentials or url ")
+ }
+
+ defer resp.Body.Close()
+ body, err := ioutil.ReadAll(resp.Body)
+ json.Unmarshal([]byte(body), &jwt)
+ fmt.Printf("Token: %s\n", jwt.Access_token)
+
+ res.Header().Set("Authorization", "Bearer "+jwt.Access_token)
+ res.WriteHeader(http.StatusOK)
+ res.Write([]byte("Successfully retrieved JWT access token"))
+}
+
+func getJwtToken(keycloakUrl, clientId string) (*http.Response, error) {
+ var resp = &http.Response{}
+ var err error
+ client_assertion := getClientAssertion()
+
+ if jwt.Refresh_token != "" {
+ resp, err = http.PostForm(keycloakUrl, url.Values{"client_assertion_type": {client_assertion_type},
+ "client_assertion": {client_assertion}, "grant_type": {"refresh_token"},
+ "refresh_token": {jwt.Refresh_token}, "client_id": {clientId}, "scope": {scope}})
+ } else {
+ resp, err = http.PostForm(keycloakUrl, url.Values{"client_assertion_type": {client_assertion_type},
+ "client_assertion": {client_assertion}, "grant_type": {"client_credentials"},
+ "client_id": {clientId}, "scope": {scope}})
+ }
+
+ return resp, err
+}
+
+func getClientAssertion() string {
+ realm := "http://" + keycloakHost + ":" + keycloakPort + "/auth/realms/" + realmName
+ clientAssertion := generatejwt.CreateJWT("/certs/client.key", "", clientId, realm)
+ return clientAssertion
+}
+
+func getx509Token(keycloakUrl, clientId string) (*http.Response, error) {
+ var resp = &http.Response{}
+ var err error
+
+ client := getClient()
+ resp, err = client.PostForm(keycloakUrl, url.Values{"username": {""}, "password": {""}, "grant_type": {"password"}, "client_id": {clientId}, "scope": {scope}})
+
+ return resp, err
+}
+
+func getClient() *http.Client {
+ caCert, _ := ioutil.ReadFile("/certs/rootCA.crt")
+ caCertPool := x509.NewCertPool()
+ caCertPool.AppendCertsFromPEM(caCert)
+
+ cert, _ := tls.LoadX509KeyPair("/certs/client.crt", "/certs/client.key")
+
+ dialer := &net.Dialer{
+ Timeout: 30 * time.Second,
+ KeepAlive: 30 * time.Second,
+ DualStack: true,
+ }
+
+ client := &http.Client{
+ Transport: &http.Transport{
+ DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
+ fmt.Println("address original =", addr)
+ if addr == keycloakAlias+":"+keycloakPort {
+ addr = keycloakHost + ":" + keycloakPort
+ fmt.Println("address modified =", addr)
+ }
+ return dialer.DialContext(ctx, network, addr)
+ },
+ TLSClientConfig: &tls.Config{
+ RootCAs: caCertPool,
+ Certificates: []tls.Certificate{cert},
+ },
+ },
+ }
+ return client
+}
+
+func getSecretToken(keycloakUrl, clientId string) (*http.Response, error) {
+ var resp = &http.Response{}
+ var err error
+
+ secretName := clientId + "-secret"
+ clientSecret := getSecret(secretName)
+ resp, err = http.PostForm(keycloakUrl,
+ url.Values{"client_secret": {clientSecret}, "grant_type": {"client_credentials"}, "client_id": {clientId}})
+
+ return resp, err
+}
+
+func getSecret(secretName string) string {
+ clientset := connectToK8s()
+ res, err := clientset.CoreV1().Secrets(namespace).Get(context.TODO(), secretName, metav1.GetOptions{})
+ if err != nil {
+ fmt.Println(err.Error())
+ }
+ return string(res.Data["client_secret"])
+}
+
+func connectToK8s() *kubernetes.Clientset {
+ config, err := rest.InClusterConfig()
+ if err != nil {
+ fmt.Println("failed to create K8s config")
+ }
+
+ clientset, err := kubernetes.NewForConfig(config)
+ if err != nil {
+ fmt.Println("Failed to create K8s clientset")
+ }
+
+ return clientset
+}
+
+func health(res http.ResponseWriter, req *http.Request) {
+ if healthy {
+ res.WriteHeader(http.StatusOK)
+ res.Write([]byte("healthy"))
+ } else {
+ res.WriteHeader(http.StatusInternalServerError)
+ res.Write([]byte("unhealthy"))
+ }
+}
+
+func main() {
+ flag.StringVar(&keycloakHost, "keycloakHost", "istio-ingressgateway.istio-system", "Keycloak Host")
+ flag.StringVar(&keycloakPort, "keycloakPort", "80", "Keycloak Port")
+ flag.StringVar(&keycloakAlias, "keycloakAlias", "keycloak.oran.org", "Keycloak URL Alias")
+ flag.Parse()
+
+ healthHandler := http.HandlerFunc(health)
+ http.Handle("/health", healthHandler)
+ tokenHandler := http.HandlerFunc(getToken)
+ http.Handle("/token", tokenHandler)
+ http.ListenAndServe(":8888", nil)
+
+ ioutil.WriteFile("init.txt", []byte("Initialization done."), 0644)
+}
diff --git a/service-exposure/rapps-keycloak-mgr.go b/service-exposure/rapps-keycloak-mgr.go
index 5fc92f4..35e503d 100644
--- a/service-exposure/rapps-keycloak-mgr.go
+++ b/service-exposure/rapps-keycloak-mgr.go
@@ -17,7 +17,6 @@
// limitations under the License.
// ========================LICENSE_END===================================
//
-
package main
import (
@@ -29,7 +28,6 @@
kubernetes "k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"net/http"
- "strings"
"rapps/utils/pemtojwks"
)
@@ -42,12 +40,13 @@
realmName := query.Get("realm")
clientName := query.Get("name")
role := query.Get("role")
+ authType := query.Get("authType")
var msg string
- msg, err := create(realmName, clientName, role)
+ msg, err := create(realmName, clientName, role, authType)
if err != nil {
msg = err.Error()
}
- if realmName != "x509" && realmName != "jwt" {
+ if authType == "client-secret" {
createSecret(msg, clientName, realmName, role, namespace)
}
// create response binary data
@@ -61,12 +60,13 @@
realmName := query.Get("realm")
clientName := query.Get("name")
role := query.Get("role")
+ authType := query.Get("authType")
var msg string = "Removed keycloak " + clientName + " from " + realmName + " realm"
remove(realmName, clientName)
- if realmName != "x509" && realmName != "jwt" {
- removeSecret(namespace, role)
- }
+ if authType == "client-secret" {
+ removeSecret(namespace, role)
+ }
// create response binary data
data := []byte(msg) // slice of bytes
// write `data` to response
@@ -81,7 +81,7 @@
http.ListenAndServe(":9000", nil)
}
-func create(realmName, clientName, clientRoleName string) (string, error) {
+func create(realmName, clientName, clientRoleName, authType string) (string, error) {
client := gocloak.NewClient("http://keycloak.default:8080")
ctx := context.Background()
token, err := client.LoginAdmin(ctx, "admin", "admin", "master")
@@ -122,7 +122,7 @@
fmt.Println("Retrieved AuthenticationFlow id", flowId)
}
- newClient1 := gocloak.Client{
+ secretClient := gocloak.Client{
ClientID: gocloak.StringP(clientName),
Enabled: gocloak.BoolP(true),
DirectAccessGrantsEnabled: gocloak.BoolP(true),
@@ -135,7 +135,7 @@
"client_credentials.use_refresh_token": "true"},
}
- newClient2 := gocloak.Client{
+ x509Client := gocloak.Client{
ClientID: gocloak.StringP(clientName),
Enabled: gocloak.BoolP(true),
DirectAccessGrantsEnabled: gocloak.BoolP(true),
@@ -151,32 +151,32 @@
AuthenticationFlowBindingOverrides: &map[string]string{"direct_grant": flowId},
}
- jwksString := pemtojwks.CreateJWKS("/certs/client_pub.key", "public", "/certs/client.crt")
- newClient3 := gocloak.Client{
- ClientID: gocloak.StringP(clientName),
- Enabled: gocloak.BoolP(true),
- DirectAccessGrantsEnabled: gocloak.BoolP(true),
- BearerOnly: gocloak.BoolP(false),
- PublicClient: gocloak.BoolP(false),
- ServiceAccountsEnabled: gocloak.BoolP(true),
- ClientAuthenticatorType: gocloak.StringP("client-jwt"),
- DefaultClientScopes: &[]string{"email"},
- Attributes: &map[string]string{"token.endpoint.auth.signing.alg": "RS256",
- "use.jwks.string": "true",
- "jwks.string": jwksString,
- "use.refresh.tokens": "true",
- "client_credentials.use_refresh_token": "true",
+ jwksString := pemtojwks.CreateJWKS("/certs/client.crt")
+ jwtClient := gocloak.Client{
+ ClientID: gocloak.StringP(clientName),
+ Enabled: gocloak.BoolP(true),
+ DirectAccessGrantsEnabled: gocloak.BoolP(true),
+ BearerOnly: gocloak.BoolP(false),
+ PublicClient: gocloak.BoolP(false),
+ ServiceAccountsEnabled: gocloak.BoolP(true),
+ ClientAuthenticatorType: gocloak.StringP("client-jwt"),
+ DefaultClientScopes: &[]string{"email"},
+ Attributes: &map[string]string{"token.endpoint.auth.signing.alg": "RS256",
+ "use.jwks.string": "true",
+ "jwks.string": jwksString,
+ "use.refresh.tokens": "true",
+ "client_credentials.use_refresh_token": "true",
},
- }
+ }
var newClient gocloak.Client
- if strings.HasPrefix(clientName, "x509") {
- newClient = newClient2
- } else if strings.HasPrefix(clientName, "jwt") {
- newClient = newClient3
+ if authType == "client-x509" {
+ newClient = x509Client
+ } else if authType == "client-jwt" {
+ newClient = jwtClient
} else {
- newClient = newClient1
- }
+ newClient = secretClient
+ }
clientId, err := client.CreateClient(ctx, token.AccessToken, realmName, newClient)
if err != nil {
@@ -204,7 +204,7 @@
fmt.Println("Service Account user", *user.Username)
}
- if strings.HasPrefix(clientName, "x509") {
+ if authType == "client-x509" {
newUser := gocloak.User{
ID: gocloak.StringP(realmName + "user"),
Username: gocloak.StringP(realmName + "user"),
@@ -262,7 +262,7 @@
fmt.Println("Client rolemapper added to client")
}
- if strings.HasPrefix(clientName, "x509") {
+ if authType == "client-x509" {
clientRole := *newClient.ClientID + "." + clientRoleName
clientroleMapper := gocloak.ProtocolMapperRepresentation{
@@ -336,7 +336,7 @@
}
func remove(realmName, clientName string) {
- adminClient := gocloak.NewClient("http://192.168.49.2:31560")
+ adminClient := gocloak.NewClient("http://keycloak.default:8080")
ctx := context.Background()
token, err := adminClient.LoginAdmin(ctx, "admin", "admin", "master")
if err != nil {
diff --git a/service-exposure/rapps-keycloak-mgr.yaml b/service-exposure/rapps-keycloak-mgr.yaml
index c2f14da..6774746 100644
--- a/service-exposure/rapps-keycloak-mgr.yaml
+++ b/service-exposure/rapps-keycloak-mgr.yaml
@@ -31,7 +31,7 @@
template:
metadata:
labels:
- app: rapps-keycloak-mgr
+ app: rapps-keycloak-mgr
version: v1
spec:
containers:
@@ -39,7 +39,7 @@
image: ktimoney/rapps-keycloak-mgr
imagePullPolicy: IfNotPresent
ports:
- - containerPort: 9000
+ - containerPort: 9000
resources:
limits:
memory: 256Mi
@@ -58,7 +58,7 @@
path: /var/rapps/certs
type: DirectoryOrCreate
serviceAccountName: helm-app
- replicas: 1
+ replicas: 1
---
apiVersion: v1
kind: Service
@@ -70,7 +70,7 @@
app: rapps-keycloak-mgr
ports:
- protocol: TCP
- port: 80
- targetPort: 9000
+ port: 80
+ targetPort: 9000
nodePort: 31600
type: NodePort
diff --git a/service-exposure/rapps-rapp-helloworld-invoker1.go b/service-exposure/rapps-rapp-helloworld-invoker1.go
new file mode 100644
index 0000000..bfa5afa
--- /dev/null
+++ b/service-exposure/rapps-rapp-helloworld-invoker1.go
@@ -0,0 +1,163 @@
+// -
+// ========================LICENSE_START=================================
+// O-RAN-SC
+// %%
+// Copyright (C) 2022: Nordix Foundation
+// %%
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ========================LICENSE_END===================================
+//
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/client_golang/prometheus/promhttp"
+ "io/ioutil"
+ "net/http"
+ "strings"
+ "time"
+)
+
+
+var gatewayHost string
+var gatewayPort string
+var securityEnabled string
+var useGateway string
+var rapp string
+var methods string
+var healthy bool = true
+var ttime time.Time
+
+const (
+ namespace = "istio-nonrtric"
+ scope = "email"
+ client_assertion_type = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
+)
+
+var (
+ reqDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{
+ Name: "rapp_http_request_duration_seconds",
+ Help: "Duration of the last request call.",
+ Buckets: []float64{0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10},
+ }, []string{"app", "func", "handler", "method", "code"})
+ reqBytes = prometheus.NewSummaryVec(prometheus.SummaryOpts{
+ Name: "rapp_bytes_summary",
+ Help: "Summary of bytes transferred over http",
+ }, []string{"app", "func", "handler", "method", "code"})
+)
+
+
+func MakeRequest(client *http.Client, prefix string, method string, ch chan string) {
+ var service = strings.Split(prefix, "/")[1]
+ var gatewayUrl = "http://" + gatewayHost + ":" + gatewayPort
+ var jsonValue []byte = []byte{}
+ var restUrl string = ""
+
+ if securityEnabled != "true" {
+ gatewayUrl = "http://" + service + "." + namespace + ":80"
+ prefix = ""
+ }
+
+ restUrl = gatewayUrl + prefix
+ resp := &http.Response{}
+
+ timer := prometheus.NewTimer(prometheus.ObserverFunc(func(v float64) {
+ reqDuration.WithLabelValues("rapp-helloworld-invoker1", "MakeRequest", resp.Request.URL.Path, resp.Request.Method,
+ resp.Status).Observe(v)
+ }))
+ defer timer.ObserveDuration()
+ fmt.Printf("Making get request to %s\n", restUrl)
+ req, err := http.NewRequest(method, restUrl, bytes.NewBuffer(jsonValue))
+ if err != nil {
+ fmt.Printf("Got error %s", err.Error())
+ }
+ req.Header.Set("Content-type", "application/json")
+
+ resp, err = client.Do(req)
+ if err != nil {
+ fmt.Printf("Got error %s", err.Error())
+ }
+
+ defer resp.Body.Close()
+ body, _ := ioutil.ReadAll(resp.Body)
+ reqBytes.WithLabelValues("rapp-helloworld-invoker1", "MakeRequest", req.URL.Path, req.Method,
+ resp.Status).Observe(float64(resp.ContentLength))
+
+ respString := string(body[:])
+ if respString == "RBAC: access denied" {
+ respString += " for " + service + " " + strings.ToLower(method) + " request"
+ }
+ fmt.Printf("Received response for %s %s request - %s\n", service, strings.ToLower(method), respString)
+ ch <- prefix + "," + method
+}
+
+func health(res http.ResponseWriter, req *http.Request) {
+ if healthy {
+ res.WriteHeader(http.StatusOK)
+ res.Write([]byte("healthy"))
+ } else {
+ res.WriteHeader(http.StatusInternalServerError)
+ res.Write([]byte("unhealthy"))
+ }
+}
+
+func main() {
+ ttime = time.Now()
+ time.Sleep(3 * time.Second)
+ prometheus.Register(reqDuration)
+ prometheus.Register(reqBytes)
+
+ flag.StringVar(&gatewayHost, "gatewayHost", "istio-ingressgateway.istio-system", "Gateway Host")
+ flag.StringVar(&gatewayPort, "gatewayPort", "80", "Gateway Port")
+ flag.StringVar(&useGateway, "useGateway", "Y", "Connect to services through API gateway")
+ flag.StringVar(&securityEnabled, "securityEnabled", "true", "Security is required to use this application")
+ flag.StringVar(&rapp, "rapp", "rapp-helloworld-provider", "Name of rapp to invoke")
+ flag.StringVar(&methods, "methods", "GET", "Methods to access application")
+ flag.Parse()
+
+ healthHandler := http.HandlerFunc(health)
+ http.Handle("/health", healthHandler)
+ http.Handle("/metrics", promhttp.Handler())
+ go func() {
+ http.ListenAndServe(":9000", nil)
+ }()
+
+ ioutil.WriteFile("init.txt", []byte("Initialization done."), 0644)
+
+ client := &http.Client{
+ Timeout: time.Second * 10,
+ }
+
+ ch := make(chan string)
+ var prefixArray []string = []string{"/" + rapp}
+ var methodArray []string = []string{methods}
+ for _, prefix := range prefixArray {
+ for _, method := range methodArray {
+ go MakeRequest(client, prefix, method, ch)
+ }
+ }
+
+
+ for r := range ch {
+ go func(resp string) {
+ time.Sleep(10 * time.Second)
+ elements := strings.Split(resp, ",")
+ prefix := elements[0]
+ method := elements[1]
+ MakeRequest(client, prefix, method, ch)
+ }(r)
+ }
+}
diff --git a/service-exposure/rapps-rapp-helloworld-invoker2.go b/service-exposure/rapps-rapp-helloworld-invoker2.go
new file mode 100644
index 0000000..93c6981
--- /dev/null
+++ b/service-exposure/rapps-rapp-helloworld-invoker2.go
@@ -0,0 +1,163 @@
+// -
+// ========================LICENSE_START=================================
+// O-RAN-SC
+// %%
+// Copyright (C) 2022: Nordix Foundation
+// %%
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ========================LICENSE_END===================================
+//
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "github.com/prometheus/client_golang/prometheus"
+ "github.com/prometheus/client_golang/prometheus/promhttp"
+ "io/ioutil"
+ "net/http"
+ "strings"
+ "time"
+)
+
+
+var gatewayHost string
+var gatewayPort string
+var securityEnabled string
+var useGateway string
+var rapp string
+var methods string
+var healthy bool = true
+var ttime time.Time
+
+const (
+ namespace = "istio-nonrtric"
+ scope = "email"
+ client_assertion_type = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
+)
+
+var (
+ reqDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{
+ Name: "rapp_http_request_duration_seconds",
+ Help: "Duration of the last request call.",
+ Buckets: []float64{0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10},
+ }, []string{"app", "func", "handler", "method", "code"})
+ reqBytes = prometheus.NewSummaryVec(prometheus.SummaryOpts{
+ Name: "rapp_bytes_summary",
+ Help: "Summary of bytes transferred over http",
+ }, []string{"app", "func", "handler", "method", "code"})
+)
+
+
+func MakeRequest(client *http.Client, prefix string, method string, ch chan string) {
+ var service = strings.Split(prefix, "/")[1]
+ var gatewayUrl = "http://" + gatewayHost + ":" + gatewayPort
+ var jsonValue []byte = []byte{}
+ var restUrl string = ""
+
+ if securityEnabled != "true" {
+ gatewayUrl = "http://" + service + "." + namespace + ":80"
+ prefix = ""
+ }
+
+ restUrl = gatewayUrl + prefix
+ resp := &http.Response{}
+
+ timer := prometheus.NewTimer(prometheus.ObserverFunc(func(v float64) {
+ reqDuration.WithLabelValues("rapp-helloworld-invoker2", "MakeRequest", resp.Request.URL.Path, resp.Request.Method,
+ resp.Status).Observe(v)
+ }))
+ defer timer.ObserveDuration()
+ fmt.Printf("Making get request to %s\n", restUrl)
+ req, err := http.NewRequest(method, restUrl, bytes.NewBuffer(jsonValue))
+ if err != nil {
+ fmt.Printf("Got error %s", err.Error())
+ }
+ req.Header.Set("Content-type", "application/json")
+
+ resp, err = client.Do(req)
+ if err != nil {
+ fmt.Printf("Got error %s", err.Error())
+ }
+
+ defer resp.Body.Close()
+ body, _ := ioutil.ReadAll(resp.Body)
+ reqBytes.WithLabelValues("rapp-helloworld-invoker2", "MakeRequest", req.URL.Path, req.Method,
+ resp.Status).Observe(float64(resp.ContentLength))
+
+ respString := string(body[:])
+ if respString == "RBAC: access denied" {
+ respString += " for " + service + " " + strings.ToLower(method) + " request"
+ }
+ fmt.Printf("Received response for %s %s request - %s\n", service, strings.ToLower(method), respString)
+ ch <- prefix + "," + method
+}
+
+func health(res http.ResponseWriter, req *http.Request) {
+ if healthy {
+ res.WriteHeader(http.StatusOK)
+ res.Write([]byte("healthy"))
+ } else {
+ res.WriteHeader(http.StatusInternalServerError)
+ res.Write([]byte("unhealthy"))
+ }
+}
+
+func main() {
+ ttime = time.Now()
+ time.Sleep(4 * time.Second)
+ prometheus.Register(reqDuration)
+ prometheus.Register(reqBytes)
+
+ flag.StringVar(&gatewayHost, "gatewayHost", "istio-ingressgateway.istio-system", "Gateway Host")
+ flag.StringVar(&gatewayPort, "gatewayPort", "80", "Gateway Port")
+ flag.StringVar(&useGateway, "useGateway", "Y", "Connect to services through API gateway")
+ flag.StringVar(&securityEnabled, "securityEnabled", "true", "Security is required to use this application")
+ flag.StringVar(&rapp, "rapp", "rapp-helloworld-provider", "Name of rapp to invoke")
+ flag.StringVar(&methods, "methods", "GET", "Methods to access application")
+ flag.Parse()
+
+ healthHandler := http.HandlerFunc(health)
+ http.Handle("/health", healthHandler)
+ http.Handle("/metrics", promhttp.Handler())
+ go func() {
+ http.ListenAndServe(":9000", nil)
+ }()
+
+ ioutil.WriteFile("init.txt", []byte("Initialization done."), 0644)
+
+ client := &http.Client{
+ Timeout: time.Second * 10,
+ }
+
+ ch := make(chan string)
+ var prefixArray []string = []string{"/" + rapp}
+ var methodArray []string = []string{methods}
+ for _, prefix := range prefixArray {
+ for _, method := range methodArray {
+ go MakeRequest(client, prefix, method, ch)
+ }
+ }
+
+
+ for r := range ch {
+ go func(resp string) {
+ time.Sleep(10 * time.Second)
+ elements := strings.Split(resp, ",")
+ prefix := elements[0]
+ method := elements[1]
+ MakeRequest(client, prefix, method, ch)
+ }(r)
+ }
+}
diff --git a/service-exposure/rapps-rapp-helloworld-provider.go b/service-exposure/rapps-rapp-helloworld-provider.go
new file mode 100644
index 0000000..63d6493
--- /dev/null
+++ b/service-exposure/rapps-rapp-helloworld-provider.go
@@ -0,0 +1,42 @@
+// -
+// ========================LICENSE_START=================================
+// O-RAN-SC
+// %%
+// Copyright (C) 2022: Nordix Foundation
+// %%
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ========================LICENSE_END===================================
+//
+package main
+
+import (
+ "net/http"
+)
+
+// create a handler struct
+type HttpHandler struct{}
+
+// implement `ServeHTTP` method on `HttpHandler` struct
+func (h HttpHandler) ServeHTTP(res http.ResponseWriter, req *http.Request) {
+ // create response binary data
+ data := []byte("Hello World Demo!") // slice of bytes
+ // write `data` to response
+ res.Write(data)
+}
+
+func main() {
+ // create a new handler
+ handler := HttpHandler{}
+ // listen and serve
+ http.ListenAndServe(":9000", handler)
+}
diff --git a/service-exposure/rapps-rapp-invoker.go b/service-exposure/rapps-rapp-invoker.go
index 4dc7359..21c72c0 100644
--- a/service-exposure/rapps-rapp-invoker.go
+++ b/service-exposure/rapps-rapp-invoker.go
@@ -17,7 +17,6 @@
// limitations under the License.
// ========================LICENSE_END===================================
//
-
package main
import (
@@ -57,7 +56,7 @@
var rapp string
var methods string
var healthy bool = true
-var ttime time.Time
+var ttime time.Time
var jwt Jwttoken
const (
@@ -80,7 +79,7 @@
ttime = time.Now()
ttime = ttime.Add(time.Second * time.Duration(jwt.Expires_in))
}
- return jwt.Access_token
+ return jwt.Access_token
}
func getSecret(secretName string) (string, string, string) {
diff --git a/service-exposure/rapps-rapp-provider.go b/service-exposure/rapps-rapp-provider.go
index 227f85e..4b5efd7 100644
--- a/service-exposure/rapps-rapp-provider.go
+++ b/service-exposure/rapps-rapp-provider.go
@@ -17,7 +17,6 @@
// limitations under the License.
// ========================LICENSE_END===================================
//
-
package main
import (
diff --git a/service-exposure/rapps-webhook.go b/service-exposure/rapps-webhook.go
new file mode 100644
index 0000000..242d622
--- /dev/null
+++ b/service-exposure/rapps-webhook.go
@@ -0,0 +1,185 @@
+// -
+// ========================LICENSE_START=================================
+// O-RAN-SC
+// %%
+// Copyright (C) 2022: Nordix Foundation
+// %%
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ========================LICENSE_END===================================
+//
+package main
+
+import (
+ "encoding/json"
+ "errors"
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "k8s.io/api/admission/v1beta1"
+ v1 "k8s.io/api/core/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/serializer"
+ "log"
+ "net/http"
+)
+
+type ServerParameters struct {
+ port string // webhook server port
+ certFile string // path to the x509 cert
+ keyFile string // path to the x509 private key
+ hostPath string // path to the x509 private key
+}
+
+type patchOperation struct {
+ Op string `json:"op"`
+ Path string `json:"path"`
+ Value interface{} `json:"value,omitempty"`
+}
+
+var parameters ServerParameters
+
+var (
+ universalDeserializer = serializer.NewCodecFactory(runtime.NewScheme()).UniversalDeserializer()
+)
+
+func main() {
+ flag.StringVar(¶meters.port, "port", "8443", "Webhook server port.")
+ flag.StringVar(¶meters.certFile, "tlsCertFile", "/certs/tls.crt", "File containing the x509 certificate")
+ flag.StringVar(¶meters.keyFile, "tlsKeyFile", "/certs/tls.key", "File containing the x509 private key")
+ flag.StringVar(¶meters.hostPath, "hostPath", "/var/rapps/certs", "Host Path containing rapp cert files")
+ flag.Parse()
+
+ http.HandleFunc("/inject-sidecar", HandleSideCarInjection)
+ log.Fatal(http.ListenAndServeTLS(":"+parameters.port, parameters.certFile, parameters.keyFile, nil))
+}
+
+func HandleSideCarInjection(w http.ResponseWriter, r *http.Request) {
+
+ body, err := ioutil.ReadAll(r.Body)
+ err = ioutil.WriteFile("/tmp/request", body, 0644)
+ if err != nil {
+ panic(err.Error())
+ }
+
+ var admissionReviewReq v1beta1.AdmissionReview
+
+ if _, _, err := universalDeserializer.Decode(body, nil, &admissionReviewReq); err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ fmt.Errorf("Could not deserialize request: %v", err)
+ } else if admissionReviewReq.Request == nil {
+ w.WriteHeader(http.StatusBadRequest)
+ errors.New("Malformed admission review - request is empty")
+ }
+
+ fmt.Printf("Received Admission Review Request - Type: %v \t Event: %v \t Name: %v \n",
+ admissionReviewReq.Request.Kind,
+ admissionReviewReq.Request.Operation,
+ admissionReviewReq.Request.Name,
+ )
+
+ var pod v1.Pod
+
+ err = json.Unmarshal(admissionReviewReq.Request.Object.Raw, &pod)
+
+ if err != nil {
+ fmt.Errorf("Could not unmarshal pod from admission request: %v", err)
+ }
+
+ var patches []patchOperation
+
+ labels := pod.ObjectMeta.Labels
+ labels["sidecar-injection-webhook"] = "jwt-proxy"
+
+ patches = append(patches, patchOperation{
+ Op: "add",
+ Path: "/metadata/labels",
+ Value: labels,
+ })
+
+ var containers []v1.Container
+ containers = append(containers, pod.Spec.Containers...)
+ container := v1.Container{
+ Name: "jwt-proxy",
+ Image: "ktimoney/rapps-jwt",
+ ImagePullPolicy: v1.PullIfNotPresent,
+ Ports: []v1.ContainerPort{
+ {
+ Name: "http",
+ Protocol: v1.ProtocolTCP,
+ ContainerPort: 8888,
+ },
+ },
+ VolumeMounts: []v1.VolumeMount{
+ {
+ Name: "certsdir",
+ MountPath: "/certs",
+ ReadOnly: true,
+ },
+ },
+ }
+
+ containers = append(containers, container)
+ fmt.Println(containers)
+
+ patches = append(patches, patchOperation{
+ Op: "add",
+ Path: "/spec/containers",
+ Value: containers,
+ })
+
+ pathType := v1.HostPathDirectoryOrCreate
+ pathTypePtr := &pathType
+ var volumes []v1.Volume
+ volumes = append(volumes, pod.Spec.Volumes...)
+ volume := v1.Volume{
+ Name: "certsdir",
+ VolumeSource: v1.VolumeSource{
+ HostPath: &v1.HostPathVolumeSource{
+ Path: parameters.hostPath,
+ Type: pathTypePtr,
+ },
+ },
+ }
+ volumes = append(volumes, volume)
+ fmt.Println(volumes)
+
+ patches = append(patches, patchOperation{
+ Op: "add",
+ Path: "/spec/volumes",
+ Value: volumes,
+ })
+ fmt.Println(patches)
+
+ patchBytes, err := json.Marshal(patches)
+
+ if err != nil {
+ fmt.Errorf("Error occurred when trying to marshal JSON patch: %v", err)
+ }
+
+ admissionReviewResponse := v1beta1.AdmissionReview{
+ Response: &v1beta1.AdmissionResponse{
+ UID: admissionReviewReq.Request.UID,
+ Allowed: true,
+ },
+ }
+
+ admissionReviewResponse.Response.Patch = patchBytes
+
+ bytes, err := json.Marshal(&admissionReviewResponse)
+ if err != nil {
+ fmt.Errorf("Error occurred when trying to marshal Aadmission Review response: %v", err)
+ }
+
+ w.Write(bytes)
+
+}
diff --git a/service-exposure/rapps-webhook.yaml b/service-exposure/rapps-webhook.yaml
new file mode 100644
index 0000000..1b51317
--- /dev/null
+++ b/service-exposure/rapps-webhook.yaml
@@ -0,0 +1,115 @@
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+---
+############################################################
+# TLS certificate for OPA admission controller.
+############################################################
+apiVersion: v1
+kind: Secret
+metadata:
+ name: webhook-cert
+ namespace: default
+type: Opaque
+data:
+ tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVMekNDQXhlZ0F3SUJBZ0lVUTZFV1pIK3RQdTk0WmEzeWp6STFFbGNBcTdrd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1RURUxNQWtHQTFVRUJoTUNTVVV4RURBT0JnTlZCQWdUQjFkbFltaHZiMnN4RHpBTkJnTlZCQWNUQmtSMQpZbXhwYmpFTU1Bb0dBMVVFQ2hNRFJWTlVNUTB3Q3dZRFZRUUxFd1JQY21GdU1CNFhEVEl5TURreU1EQTRNRGt3Ck1Gb1hEVFF5TURreE5UQTRNRGt3TUZvd1RURUxNQWtHQTFVRUJoTUNTVVV4RURBT0JnTlZCQWdUQjFkbFltaHYKYjJzeER6QU5CZ05WQkFjVEJrUjFZbXhwYmpFTU1Bb0dBMVVFQ2hNRFJWTlVNUTB3Q3dZRFZRUUxFd1JQY21GdQpNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQW0zdUdEYnVwQkhjV3lockZ1TjdrCkFRN3hZeW05NGVjcjJZOE5mbHFtTDU2NG9YTzlic09uaG85czVtLzdiNUFTUlZ4aTJlUFltTGg4ZmlxL3hZaDgKZEo5M3ErWm8vZU9zUElER3BFTlBCQjhqL3AwNHkyckJwN2IwZk5PdTQ2dFB1YUNMRzR6ZEZoSkgyWU5FbGxnbQpqYWtvTThPcTBCZGYrejJlSWlBYWYxQTN1bTY0czJaR1pnR2hSdnhkYW1zVFhLNm1hNFd4OXBhMHlkdC93dnJtCm1SUThWOUlDNDhOS2QveTBpUmh3M2pRNzZUb05NWWFiUk9LTE1jNjMwVXZtL2NuV0dZNjZNeFVoeEhLUWY4SE4KTGp3U1VGRzlWYmVBYXQwcktoSkw2L21Eb3dpbzFRaXhoK25lazRXdm41cGFiZzlLakRWUnRja0NXS0toeUhFTAovUUlEQVFBQm80SUJCVENDQVFFd0RnWURWUjBQQVFIL0JBUURBZ1dnTUIwR0ExVWRKUVFXTUJRR0NDc0dBUVVGCkJ3TUJCZ2dyQmdFRkJRY0RBakFNQmdOVkhSTUJBZjhFQWpBQU1CMEdBMVVkRGdRV0JCVGFTU1luVDA3L3ZDMmsKTDk0NmhmRVFzemN6b1RDQm9nWURWUjBSQklHYU1JR1hnaDVxZDNRdGNISnZlSGt0WVdSdGFYTnphVzl1TFdOdgpiblJ5YjJ4c1pYS0NPR3AzZEMxd2NtOTRlUzFoWkcxcGMzTnBiMjR0WTI5dWRISnZiR3hsY2k1a1pXWmhkV3gwCkxuTjJZeTVqYkhWemRHVnlMbXh2WTJGc2dpcHFkM1F0Y0hKdmVIa3RZV1J0YVhOemFXOXVMV052Ym5SeWIyeHMKWlhJdVpHVm1ZWFZzZEM1emRtT0NDV3h2WTJGc2FHOXpkSWNFZndBQUFUQU5CZ2txaGtpRzl3MEJBUXNGQUFPQwpBUUVBU0EzV1VmbG9Ia0NIaU1TZ2VQSkVaUXdHN0tZSnJUQjByS25tYmFFSzloZnNveWlXcWs2WTl5RjFsMFVFCjBvQTdiRUZBRWh6S0VkcGxXOHRrQ1ZwaGxQZ0FBbktPU0dhYlVUam9KYURsWDBDRS9oNE5RaTlmOHVKT0ZkaVEKc3JRcXZCZWthUzNOd2ZIVHBTdFRnSEs1bEovMjUxenJ1VVZ0VTBERWpIQ1BYUks2S09uUmlNYktCSFBDNmoybQpmV29zdC9NYWJhbUlvOHlIdjZXaHNTbXhDODlEZ1BXa3RXM01QOXFEUjlTVWQzWk5BdWZKU0hEeDkxWEN6L2JpClRFZjRrRE1GRnVsMW5UUzBXTlhVUEV1MnR0SWxmMDBsZS91VHVNVUxOZ3V3Umlmc2tPSmFJcUVBc2NxWmtxdEMKQW5EMGdnV01QMEpCL1k1eGZTM1ZPLzBPVVE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
+ tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb2dJQkFBS0NBUUVBbTN1R0RidXBCSGNXeWhyRnVON2tBUTd4WXltOTRlY3IyWThOZmxxbUw1NjRvWE85CmJzT25obzlzNW0vN2I1QVNSVnhpMmVQWW1MaDhmaXEveFloOGRKOTNxK1pvL2VPc1BJREdwRU5QQkI4ai9wMDQKeTJyQnA3YjBmTk91NDZ0UHVhQ0xHNHpkRmhKSDJZTkVsbGdtamFrb004T3EwQmRmK3oyZUlpQWFmMUEzdW02NApzMlpHWmdHaFJ2eGRhbXNUWEs2bWE0V3g5cGEweWR0L3d2cm1tUlE4VjlJQzQ4TktkL3kwaVJodzNqUTc2VG9OCk1ZYWJST0tMTWM2MzBVdm0vY25XR1k2Nk14VWh4SEtRZjhITkxqd1NVRkc5VmJlQWF0MHJLaEpMNi9tRG93aW8KMVFpeGgrbmVrNFd2bjVwYWJnOUtqRFZSdGNrQ1dLS2h5SEVML1FJREFRQUJBb0lCQUFhWm9jRW5mQzlDVnVkUgpaNTlIWnVwY2xnYWRtUC9qN2txWDlmeXRJR3paRWdGWWhtd1RSaU5DSjE5STFhV1F1aFhUckNhUHMzd1lLTUM2ClU5V3d5NGV2MVVhb3kwQXJ6LzNwZ1lVcmpra2dnVWlucCtlS3FwblIvR0xvSVg1c29UL0IvdVcyZnhRV3hwSUgKTG53clZjZWhyS0UxNXlSYU9hclNuTW5hRHdYa2N1ZlF4enFLR1E2aFZZUGFGSk9JUXJQWmZXei84b2ZpWThBbwprSlZjSG1uOTZNLzZxRWhTbVZHcmc5M1BtYjJkUmNyc2hDblRCY2g5dDNuNnV4WGxKcmx0dG9lR1piTDB3Y3M0Ck9Wc2NDY043NEx3OGozSkdXeDg2QmVLT3ZORlJKajh3ajdxcGhsTW5hNjUxTmd6UE41eXlIR1IzWVhXU1lxSFcKMW9BRFFva0NnWUVBekN5ZlJjRTdMMEtsVGY4VmQ5cjZpRjhwcktBV0xSeXRZQTJjUUdSYWZHZlZYenJ4TnNBRwpGVlZlL2RabzVRa0I5NjlkKzRudDV5OUQzMWhYUGRNa0w0UWlWaHBuSE5zSzg4RVpuVXkxTkRBVCtJdEorY0VmCi9UaHRKa2Z4VGVXb1p6cmhIU1kxb2theFpzMWJ6bFpUNzFMTnBRTUs3bDBzc2hCVUdreklCME1DZ1lFQXd2TGcKcHhlWEtMMHVxNExWQVdMVEtyb2ttdmdIOG80QWpiekZLUnVTUTdlL3pVdXNVbVlZdFdMMEVqcGZXSTdNdXhrUwpjZUJiRmduakl5S3lGbDZTQ1BPaCs0N09EdlRNMDBpTGdoTnpOalVJbkE5RGJCV2ZURFVYd3ZHSDdhUGJ1OEVuCjFFUW1Wc2l5bC80SG1nK055WWJ5Q29WU1ZPZEJrQit1d0VYeFM3OENnWUFGOE9wMWlpamh1Q3U5T0VYMHBkK1MKWmtwOUptOWV3cTNjMUtpT1N4MUM3M2FLL2RrVkFjTnJqWDlsSFg4UjR4QTJsOWpCUUFNM0xlM29xdFpuQ3lUTAphU25pbllRUWwrTWFzcXkvSWdOSDBIcFVTaUZON2l1ekg1ZzFlL1J1a3RjeW9jajVJeXArWFZZK0tvMllWSFMrCnl3Y0czUzdOUHRMVkg1cUM1V2NRcHdLQmdBYUp5c3NQMlh2K1RGQm9ST2lVL2V3UzdpTmNhamZTVjJacGpGdEMKbDNjNTlHN1lPT0ZTbDBXT0dnMTZjN1F1cGVNb2hodlhvSFp1d25WdE5uZlZtQ1JBdDVBT1RBN29XdTVESXBxcwpPRkw3R0Z6VGpqbFR5Rkh2L2VvRjI3ODJuYW9BWW11V0ZZc1hsQlhRNlVSYmZTL2pITDhKbGFkUFVqMlpNbTAwCmExRlZBb0dBVlRReHNXNDJXWkRIQVExZC8vSzNXYTBQS0dWWmhHbkYxNFQzUlB3VDVDcGVKbmhhQ0QvVzh1VFQKSHBUUi8ySTY2RFQ5UjI2SlZReERoemNaa3dmR3krQVNoQ3BSb2FJZERGdjI1TS9EVGoxT2dUMUZpNm91ZjlzMgpVdFdkSEo1NlJ3cUhuRlptcnB2T3V4bGgwUWdQUHo3ZTg3dzBJMlpJQi9tRzY0Y2NHMlk9Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: webhook-app
+ namespace: default
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: webhook-app
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: cluster-admin
+subjects:
+ - kind: ServiceAccount
+ name: webhook-app
+ namespace: default
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: jwt-proxy-admission-controller-deployment
+ namespace: default
+ labels:
+ app: jwt-proxy-admission-controller
+spec:
+ selector:
+ matchLabels:
+ app: jwt-proxy-admission-controller
+ template:
+ metadata:
+ labels:
+ app: jwt-proxy-admission-controller
+ version: v1
+ spec:
+ serviceAccountName: webhook-app
+ containers:
+ - name: jwt-proxy-admission-controller
+ image: ktimoney/rapps-webhook
+ imagePullPolicy: IfNotPresent
+ command: ["/app/rapps-webhook"]
+ args: [
+ "-port", "8443",
+ "-tlsCertFile", "/certs/tls.crt",
+ "-tlsKeyFile", "/certs/tls.key",
+ "-hostPath", "/var/rapps/certs"
+ ]
+ ports:
+ - containerPort: 8443
+ resources:
+ limits:
+ memory: 256Mi
+ cpu: "250m"
+ requests:
+ memory: 128Mi
+ cpu: "80m"
+ volumeMounts:
+ - readOnly: true
+ mountPath: /certs
+ name: webhook-cert
+ volumes:
+ - name: webhook-cert
+ secret:
+ secretName: webhook-cert
+ replicas: 1
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: jwt-proxy-admission-controller
+ namespace: default
+spec:
+ selector:
+ app: jwt-proxy-admission-controller
+ ports:
+ - protocol: TCP
+ port: 443
+ targetPort: 8443
+ nodePort: 30570
+ type: NodePort
+---
diff --git a/service-exposure/rp_test.sh b/service-exposure/rp_test.sh
index c1d07a2..c26f9ae 100644
--- a/service-exposure/rp_test.sh
+++ b/service-exposure/rp_test.sh
@@ -30,23 +30,14 @@
function get_token
{
- local prefix="${1}"
+ local prefix="${1}"
url="http://192.168.49.2:31560/auth/realms"
- # echo $url
TOKEN=$(curl -s -X POST $url/provider/protocol/openid-connect/token -H \
"Content-Type: application/x-www-form-urlencoded" -d client_secret=OwTCeahULA21G5TfEVMLG1iMloGiyH3i \
- -d 'grant_type=client_credentials' -d client_id=provider-cli)
+ -d 'grant_type=client_credentials' -d client_id=provider-cli)
echo "TOKEN: $TOKEN"
ACCESS_TOKEN=$(echo $TOKEN | jq -r '.access_token')
- #echo "ACCESS_TOKEN: $ACCESS_TOKEN"
REFRESH_TOKEN=$(echo $TOKEN | jq -r '.refresh_token')
- #echo "REFRESH_TOKEN: $REFRESH_TOKEN"
- # TOKEN2=$(curl -s -X POST $url/provider/protocol/openid-connect/token -H \
- # "Content-Type: application/x-www-form-urlencoded" -d client_secret= \
- # -d refresh_token=$REFRESH_TOKEN \
- # -d 'grant_type=refresh_token' -d client_id=provider-cli)
- #echo "TOKEN2 = $TOKEN2"
- #ACCESS_TOKEN=""
echo $ACCESS_TOKEN
}
diff --git a/service-exposure/start_pods.sh b/service-exposure/start_pods.sh
index f4281c9..f1dc515 100644
--- a/service-exposure/start_pods.sh
+++ b/service-exposure/start_pods.sh
@@ -18,8 +18,31 @@
# SPDX-License-Identifier: Apache-2.0
# ============LICENSE_END=========================================================
#
+export host=$(minikube ip)
-kubectl create -f chartmuseum.yaml
+echo "Deploying applications..."
+echo "-------------------------"
+kubectl create -f chartmuseum.yaml
kubectl create -f rapps-keycloak-mgr.yaml
kubectl create -f rapps-istio-mgr.yaml
kubectl create -f rapps-helm-installer.yaml
+kubectl create -f rapps-webhook.yaml
+
+echo ""
+echo "Waiting for pods to start..."
+echo "----------------------------"
+kubectl wait deployment -n default chartmuseum-deployment --for=condition=available --timeout=90s
+kubectl wait deployment -n default rapps-keycloak-mgr-deployment --for=condition=available --timeout=90s
+kubectl wait deployment -n default rapps-istio-mgr-deployment --for=condition=available --timeout=90s
+kubectl wait deployment -n default rapps-helm-installer-deployment --for=condition=available --timeout=90s
+kubectl wait deployment -n default jwt-proxy-admission-controller-deployment --for=condition=available --timeout=90s
+
+echo ""
+echo "Configure sidecar injection..."
+echo "----------------------------"
+kubectl create -f MutatingWebhookConfiguration.yaml
+
+echo ""
+echo "Checking pod status..."
+echo "----------------------"
+kubectl get pods -n default
diff --git a/service-exposure/stop_pods.sh b/service-exposure/stop_pods.sh
index 86f22ef..fa67b13 100644
--- a/service-exposure/stop_pods.sh
+++ b/service-exposure/stop_pods.sh
@@ -19,7 +19,22 @@
# ============LICENSE_END=========================================================
#
+export host=$(minikube ip)
+
+echo "Undeploying applications..."
+echo "---------------------------"
+curl http://$host:31570/uninstall?chart=rapp-helloworld-invoker1
+echo ""
+sleep 2
+curl http://$host:31570/uninstall?chart=rapp-helloworld-invoker2
+echo ""
+sleep 2
+curl http://$host:31570/uninstall?chart=rapp-helloworld-provider
+echo ""
+
kubectl delete -f rapps-helm-installer.yaml
kubectl delete -f rapps-istio-mgr.yaml
kubectl delete -f rapps-keycloak-mgr.yaml
kubectl delete -f chartmuseum.yaml
+kubectl delete -f rapps-webhook.yaml
+kubectl delete -f MutatingWebhookConfiguration.yaml
diff --git a/service-exposure/templates/AuthorizationPolicy-template.txt b/service-exposure/templates/AuthorizationPolicy-template.txt
new file mode 100644
index 0000000..0899475
--- /dev/null
+++ b/service-exposure/templates/AuthorizationPolicy-template.txt
@@ -0,0 +1,40 @@
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+apiVersion: "security.istio.io/v1beta1"
+kind: "AuthorizationPolicy"
+metadata:
+ name: "{{.Name}}-policy"
+ namespace: {{.Namespace}}
+spec:
+ selector:
+ matchLabels:
+ app.kubernetes.io/instance: {{.Name}}
+ action: ALLOW
+ rules:
+ - from:
+ - source:
+ requestPrincipals: ["http://istio-ingressgateway.istio-system:80/auth/realms/{{.Realm}}/"]
+ - to:
+ - operation:
+ methods: ["{{.Method}}"]
+ paths: ["/{{.Name}}"]
+ when:
+ - key: request.auth.claims[clientRole]
+ values: ["{{.Role}}"]
diff --git a/service-exposure/templates/EnvoyFilter-template.txt b/service-exposure/templates/EnvoyFilter-template.txt
new file mode 100644
index 0000000..f023fa6
--- /dev/null
+++ b/service-exposure/templates/EnvoyFilter-template.txt
@@ -0,0 +1,90 @@
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+apiVersion: networking.istio.io/v1alpha3
+kind: EnvoyFilter
+metadata:
+ name: {{.Name}}-outbound-filter
+ namespace: {{.Namespace}}
+spec:
+ workloadSelector:
+ labels:
+ app.kubernetes.io/name: {{.Name}}
+ configPatches:
+ # The first patch adds the lua filter to the listener/http connection manager
+ - applyTo: HTTP_FILTER
+ match:
+ context: SIDECAR_OUTBOUND
+ listener:
+ filterChain:
+ filter:
+ name: "envoy.filters.network.http_connection_manager"
+ subFilter:
+ name: "envoy.filters.http.router"
+ patch:
+ operation: INSERT_BEFORE
+ value: # lua filter specification
+ name: envoy.lua
+ typed_config:
+ "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
+ inlineCode: |
+ function envoy_on_request(request_handle)
+ local uri = request_handle:headers():get(":path")
+ local method = request_handle:headers():get(":method")
+ if (method ~= "POST" and uri ~= "/auth/realms/{{.Realm}}/protocol/openid-connect/token")
+ then
+ -- Make an HTTP call to an upstream host with the following headers, body, and timeout.
+ local headers, body = request_handle:httpCall(
+ "jwt_cluster",
+ {
+ [":method"] = "GET",
+ [":path"] = "/token",
+ [":authority"] = "jwt-proxy",
+ ["realm"] = "{{.Realm}}",
+ ["client"] = "{{.Client}}",
+ ["authenticator"] = "{{.Authenticator}}",
+ ["ns"] = "{{.Namespace}}"
+ },
+ "jwt call",
+ 5000)
+ if (headers["authorization"] ~= nil)
+ then
+ request_handle:headers():add("authorization", headers["authorization"])
+ end
+ end
+ end
+ - applyTo: CLUSTER
+ match:
+ context: SIDECAR_OUTBOUND
+ patch:
+ operation: ADD
+ value: # cluster specification
+ name: jwt_cluster
+ type: STRICT_DNS
+ connect_timeout: 60s
+ lb_policy: ROUND_ROBIN
+ load_assignment:
+ cluster_name: jwt_cluster
+ endpoints:
+ - lb_endpoints:
+ - endpoint:
+ address:
+ socket_address:
+ address: 0.0.0.0
+ port_value: 8888
diff --git a/service-exposure/templates/Gateway-template.txt b/service-exposure/templates/Gateway-template.txt
new file mode 100644
index 0000000..594a627
--- /dev/null
+++ b/service-exposure/templates/Gateway-template.txt
@@ -0,0 +1,34 @@
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+apiVersion: networking.istio.io/v1beta1
+kind: Gateway
+metadata:
+ name: nonrtric-istio-{{.Name}}-gateway
+ namespace: {{.Namespace}}
+spec:
+ selector:
+ istio: ingressgateway # use Istio gateway implementation
+ servers:
+ - port:
+ number: 80
+ name: http
+ protocol: HTTP
+ hosts:
+ - "*"
diff --git a/service-exposure/templates/RequestAuthentication-template.txt b/service-exposure/templates/RequestAuthentication-template.txt
new file mode 100644
index 0000000..5fbdbbb
--- /dev/null
+++ b/service-exposure/templates/RequestAuthentication-template.txt
@@ -0,0 +1,31 @@
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+apiVersion: security.istio.io/v1beta1
+kind: RequestAuthentication
+metadata:
+ name: "jwt-{{.Name}}"
+ namespace: {{.Namespace}}
+spec:
+ selector:
+ matchLabels:
+ app.kubernetes.io/instance: {{.Name}}
+ jwtRules:
+ - issuer: "http://istio-ingressgateway.istio-system:80/auth/realms/{{.Realm}}"
+ jwksUri: "http://keycloak.default:8080/auth/realms/{{.Realm}}/protocol/openid-connect/certs"
diff --git a/service-exposure/templates/VirtualService-template.txt b/service-exposure/templates/VirtualService-template.txt
new file mode 100644
index 0000000..93be9cd
--- /dev/null
+++ b/service-exposure/templates/VirtualService-template.txt
@@ -0,0 +1,39 @@
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+apiVersion: networking.istio.io/v1beta1
+kind: VirtualService
+metadata:
+ name: nonrtric-istio-{{.Name}}-vs
+ namespace: {{.Namespace}}
+spec:
+ hosts:
+ - "*"
+ gateways:
+ - nonrtric-istio-{{.Name}}-gateway
+ http:
+ - name: "{{.Name}}-routes"
+ match:
+ - uri:
+ prefix: "/{{.Name}}"
+ route:
+ - destination:
+ port:
+ number: 80
+ host: {{.Name}}.{{.Namespace}}.svc.cluster.local
diff --git a/service-exposure/undeploy_rapp.sh b/service-exposure/undeploy_rapp.sh
new file mode 100644
index 0000000..5e37e17
--- /dev/null
+++ b/service-exposure/undeploy_rapp.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# ============LICENSE_START=======================================================
+# Copyright (C) 2022 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END=========================================================
+#
+export host=$(minikube ip)
+
+if [ -z "$1" ]
+ then
+ echo "No argument supplied"
+ exit 1
+fi
+
+rapp=$1
+
+curl http://$host:31570/uninstall?chart=$rapp
+echo ""
+
+kubectl wait deployment -n istio-nonrtric $rapp --for=delete --timeout=90s
+
+kubectl get pods -n istio-nonrtric
diff --git a/service-exposure/utils/generatejwt/generatejwt.go b/service-exposure/utils/generatejwt/generatejwt.go
new file mode 100644
index 0000000..7157f82
--- /dev/null
+++ b/service-exposure/utils/generatejwt/generatejwt.go
@@ -0,0 +1,184 @@
+// -
+// ========================LICENSE_START=================================
+// O-RAN-SC
+// %%
+// Copyright (C) 2022: Nordix Foundation
+// %%
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ========================LICENSE_END===================================
+//
+package generatejwt
+
+import (
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/pem"
+ "fmt"
+ "github.com/dgrijalva/jwt-go"
+ "io/ioutil"
+ "log"
+ "time"
+)
+
+type JWT struct {
+ privateKey []byte
+ publicKey []byte
+}
+
+func NewJWT(privateKey []byte, publicKey []byte) JWT {
+ return JWT{
+ privateKey: privateKey,
+ publicKey: publicKey,
+ }
+}
+
+func readFile(file string) []byte {
+ key, err := ioutil.ReadFile(file)
+ if err != nil {
+ log.Fatalln(err)
+ }
+ return key
+}
+
+func (j JWT) createWithKey(ttl time.Duration, content interface{}, client, realm string) (string, error) {
+ key, err := jwt.ParseRSAPrivateKeyFromPEM(j.privateKey)
+ if err != nil {
+ return "", fmt.Errorf("create: parse key: %w", err)
+ }
+
+ now := time.Now().UTC()
+
+ claims := make(jwt.MapClaims)
+ claims["dat"] = content // Our custom data.
+ claims["exp"] = now.Add(ttl).Unix() // The expiration time after which the token must be disregarded.
+ claims["iat"] = now.Unix() // The time at which the token was issued.
+ claims["nbf"] = now.Unix() // The time before which the token must be disregarded.
+ claims["jti"] = "myJWTId" + fmt.Sprint(now.UnixNano())
+ claims["sub"] = client
+ claims["iss"] = client
+ claims["aud"] = realm
+
+ token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
+ tokenString, err := token.SignedString(key)
+ if err != nil {
+ return "", fmt.Errorf("create: sign token: %w", err)
+ }
+
+ return tokenString, nil
+}
+
+func createWithSecret(ttl time.Duration, content interface{}, client, realm, secret string) (string, error) {
+ now := time.Now().UTC()
+
+ claims := make(jwt.MapClaims)
+ claims["dat"] = content // Our custom data.
+ claims["exp"] = now.Add(ttl).Unix() // The expiration time after which the token must be disregarded.
+ claims["iat"] = now.Unix() // The time at which the token was issued.
+ claims["nbf"] = now.Unix() // The time before which the token must be disregarded.
+ claims["jti"] = "myJWTId" + fmt.Sprint(now.UnixNano())
+ claims["sub"] = client
+ claims["iss"] = client
+ claims["aud"] = realm
+
+ token, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString([]byte(secret))
+ if err != nil {
+ return "", fmt.Errorf("create: sign token: %w", err)
+ }
+
+ return token, nil
+}
+
+func (j JWT) Validate(token string) (interface{}, error) {
+ key, err := jwt.ParseRSAPublicKeyFromPEM(j.publicKey)
+ if err != nil {
+ return "", fmt.Errorf("validate: parse key: %w", err)
+ }
+
+ tok, err := jwt.Parse(token, func(jwtToken *jwt.Token) (interface{}, error) {
+ if _, ok := jwtToken.Method.(*jwt.SigningMethodRSA); !ok {
+ return nil, fmt.Errorf("unexpected method: %s", jwtToken.Header["alg"])
+ }
+
+ return key, nil
+ })
+ if err != nil {
+ return nil, fmt.Errorf("validate: %w", err)
+ }
+
+ claims, ok := tok.Claims.(jwt.MapClaims)
+ if !ok || !tok.Valid {
+ return nil, fmt.Errorf("validate: invalid")
+ }
+
+ return claims["dat"], nil
+}
+
+func createPublicKeyFromPrivateKey(privkey_bytes []byte) []byte {
+ block, _ := pem.Decode([]byte(privkey_bytes))
+ var privateKey *rsa.PrivateKey
+ pkcs1, err := x509.ParsePKCS1PrivateKey(block.Bytes)
+ if err != nil {
+ pkcs8, err := x509.ParsePKCS8PrivateKey(block.Bytes)
+ privateKey = pkcs8.(*rsa.PrivateKey)
+ if err != nil {
+ log.Fatal(err)
+ }
+ } else {
+ privateKey = pkcs1
+ }
+
+ publicKey := &privateKey.PublicKey
+
+ pubkey_bytes, err := x509.MarshalPKIXPublicKey(publicKey)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ pubkey_pem := pem.EncodeToMemory(
+ &pem.Block{
+ Type: "PUBLIC KEY",
+ Bytes: pubkey_bytes,
+ },
+ )
+ return pubkey_pem
+}
+
+func CreateJWT(privateKeyFile, secret, client, realm string) string {
+ if secret == "" {
+ prvKey := readFile(privateKeyFile)
+ pubKey := createPublicKeyFromPrivateKey(prvKey)
+
+ jwtToken := NewJWT(prvKey, pubKey)
+
+ // 1. Create a new JWT token.
+ tok, err := jwtToken.createWithKey(time.Hour, "Can be anything", client, realm)
+ if err != nil {
+ log.Fatalln(err)
+ }
+
+ // 2. Validate an existing JWT token.
+ _, err = jwtToken.Validate(tok)
+ if err != nil {
+ log.Fatalln(err)
+ }
+ return tok
+ } else {
+ // 1. Create a new JWT token.
+ tok, err := createWithSecret(time.Hour, "Can be anything", client, realm, secret)
+ if err != nil {
+ log.Fatalln(err)
+ }
+ return tok
+ }
+
+}
diff --git a/service-exposure/utils/pemtojwks/pemtojwks.go b/service-exposure/utils/pemtojwks/pemtojwks.go
new file mode 100644
index 0000000..6317843
--- /dev/null
+++ b/service-exposure/utils/pemtojwks/pemtojwks.go
@@ -0,0 +1,133 @@
+// -
+// ========================LICENSE_START=================================
+// O-RAN-SC
+// %%
+// Copyright (C) 2022: Nordix Foundation
+// %%
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ========================LICENSE_END===================================
+//
+package pemtojwks
+
+import (
+ "crypto/rsa"
+ "crypto/sha1"
+ "crypto/x509"
+ "encoding/base64"
+ "encoding/json"
+ "encoding/pem"
+ "fmt"
+ "golang.org/x/crypto/ssh"
+ "io/ioutil"
+ "math/big"
+)
+
+type Jwks struct {
+ Keys []Key `json:"keys"`
+}
+type Key struct {
+ Kid string `json:"kid,omitempty"`
+ Kty string `json:"kty"`
+ Use string `json:"use"`
+ N string `json:"n"`
+ E string `json:"e"`
+ X5c []string `json:"x5c"`
+ X5t string `json:"x5t"`
+}
+
+func getKeyFromPrivate(key []byte) *rsa.PublicKey {
+ parsed, err := ssh.ParseRawPrivateKey(key)
+ if err != nil {
+ fmt.Println(err)
+ }
+
+ // Convert back to an *rsa.PrivateKey
+ privateKey := parsed.(*rsa.PrivateKey)
+
+ publicKey := &privateKey.PublicKey
+ return publicKey
+}
+
+func getKeyFromPublic(key []byte) *rsa.PublicKey {
+ pubPem, _ := pem.Decode(key)
+
+ parsed, err := x509.ParsePKIXPublicKey(pubPem.Bytes)
+ if err != nil {
+ fmt.Println("Unable to parse RSA public key", err)
+ }
+
+ // Convert back to an *rsa.PublicKey
+ publicKey := parsed.(*rsa.PublicKey)
+
+ return publicKey
+}
+
+func getCert(cert []byte) *x509.Certificate {
+ certPem, _ := pem.Decode(cert)
+ if certPem == nil {
+ panic("Failed to parse pem file")
+ }
+
+ // pass cert bytes
+ certificate, err := x509.ParseCertificate(certPem.Bytes)
+ if err != nil {
+ fmt.Println("Unable to parse Certificate", err)
+ }
+
+ return certificate
+}
+
+func getPublicKeyFromCert(cert_bytes []byte) *rsa.PublicKey {
+ block, _ := pem.Decode([]byte(cert_bytes))
+ var cert *x509.Certificate
+ cert, _ = x509.ParseCertificate(block.Bytes)
+ rsaPublicKey := cert.PublicKey.(*rsa.PublicKey)
+
+ return rsaPublicKey
+}
+
+func CreateJWKS(certFile string) string {
+ var publicKey *rsa.PublicKey
+
+ cert, err := ioutil.ReadFile(certFile)
+ if err != nil {
+ fmt.Println(err)
+ }
+ publicKey = getPublicKeyFromCert(cert)
+
+ certificate := getCert(cert)
+ // generate fingerprint with sha1
+ // you can also use md5, sha256, etc.
+ fingerprint := sha1.Sum(certificate.Raw)
+
+
+ jwksKey := Key{
+ Kid: "SIGNING_KEY",
+ Kty: "RSA",
+ Use: "sig",
+ N: base64.RawStdEncoding.EncodeToString(publicKey.N.Bytes()),
+ E: base64.RawStdEncoding.EncodeToString(big.NewInt(int64(publicKey.E)).Bytes()),
+ X5c: []string{base64.RawStdEncoding.EncodeToString(certificate.Raw)},
+ X5t: base64.RawStdEncoding.EncodeToString(fingerprint[:]),
+ }
+ jwksKeys := []Key{jwksKey}
+ jwks := Jwks{jwksKeys}
+
+ jwksJson, err := json.Marshal(jwks)
+ if err != nil {
+ fmt.Println(err)
+ return err.Error()
+ }
+ return string(jwksJson)
+
+}