Update keycloak version 37/10837/2
authorktimoney <kevin.timoney@est.tech>
Tue, 4 Apr 2023 16:17:35 +0000 (17:17 +0100)
committerKevin Timoney <kevin.timoney@est.tech>
Wed, 5 Apr 2023 06:43:04 +0000 (06:43 +0000)
Change-Id: Idc3113c4886d0870647eb5be1598ecd4fb824d9f
Issue-ID: NONRTRIC-857
Signed-off-by: ktimoney <kevin.timoney@est.tech>
service-exposure/README.md
service-exposure/certs/client_certs.sh
service-exposure/certs/server_certs.sh
service-exposure/keycloak.yaml
service-exposure/rapps-helm-installer.go
service-exposure/rapps-jwt.go
service-exposure/rapps-keycloak-mgr.go
service-exposure/templates/AuthorizationPolicy-template.txt
service-exposure/templates/RequestAuthentication-template.txt
service-exposure/utils/pemtojwks/pemtojwks.go

index 6f34b36..938e4ae 100644 (file)
@@ -1,6 +1,6 @@
 #
 # ============LICENSE_START=======================================================
-#  Copyright (C) 2022 Nordix Foundation.
+#  Copyright (C) 2022-2023 Nordix Foundation.
 # ================================================================================
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -36,7 +36,7 @@ rapps-webhook.yaml:           "-hostPath", "/var/rapps/certs"
 or change them to match your own setup.
 
 The certs directory contains 3 shell scripts for creating the server, client and webhook certs: server_certs.sh, client_certs.sh and webhook_certs.sh
-Certs generated by the server_certs.sh script: rootCA.crt, tls.crt and tls.key go in the "/var/keycloak/certs" directory
+Keystores/Truststores generated by the server_certs.sh script: server.keystore and server.truststore go in the "/var/keycloak/certs" directory
 Certs generated by the client_certs.sh script: client.crt, client.key and rootCA.crt go in the "/var/rapps/certs" directory
 The webhook_certs.sh script generates certs for use in the MutatingWebhookConfiguration.yaml and the rapps-webhook.yaml files.
 To configure MutatingWebhookConfiguration.yaml run the following commands:
index fbda1ec..bad7583 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 #
 # ============LICENSE_START=======================================================
-#  Copyright (C) 2022 Nordix Foundation.
+#  Copyright (C) 2022-2023 Nordix Foundation.
 # ================================================================================
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 # ============LICENSE_END=========================================================
 #
 
-
 CLIENT_SUBJECT="/C=IE/ST=Dublin/L=Dublin/O=Keycloak/OU=Keycloak/CN=localhost/emailAddress=client@mail.com"
 PW=changeit
+CERTNAME=client
+IP=$(minikube ip)
+DAYS=3650
 
+rm ${CERTNAME}.key ${CERTNAME}.csr ${CERTNAME}.crt ${CERTNAME}.p12 ${CERTNAME}.pem ${CERTNAME}_pub.key 2>/dev/null
 echo $PW > secretfile.txt
 
-openssl req -new -newkey rsa:4096 -nodes -keyout client.key -subj "$CLIENT_SUBJECT" -out client.csr
+echo "subjectKeyIdentifier   = hash" > x509.ext
+echo "authorityKeyIdentifier = keyid:always,issuer:always" >> x509.ext
+echo "basicConstraints       = CA:TRUE" >> x509.ext
+echo "keyUsage               = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign" >> x509.ext
+echo "subjectAltName         = DNS.1:localhost, IP.1:127.0.0.1, DNS.2:minikube, IP.2:${IP}, DNS.3:keycloak.default, DNS.4:keycloak.est.tech, DNS.5:keycloak" >> x509.ext
+echo "issuerAltName          = issuer:copy" >> x509.ext
+
+openssl req -new -newkey rsa:4096 -nodes -keyout ${CERTNAME}.key -subj "$CLIENT_SUBJECT" -out ${CERTNAME}.csr 
+
+openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -in ${CERTNAME}.csr -passin file:secretfile.txt -out ${CERTNAME}.crt -days $DAYS -CAcreateserial -extfile x509.ext 
+
+
+openssl pkcs12 -export -clcerts -in ${CERTNAME}.crt -inkey ${CERTNAME}.key -passout file:secretfile.txt -out ${CERTNAME}.p12
+
+openssl pkcs12 -in ${CERTNAME}.p12 -password pass:$PW -passout file:secretfile.txt -out ${CERTNAME}.pem -clcerts -nodes
 
-openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -in client.csr -passin file:secretfile.txt -out client.crt -days 365 -CAcreateserial
+openssl rsa -in ${CERTNAME}.key -outform PEM -pubout -out ${CERTNAME}_pub.key
 
-rm secretfile.txt 2>/dev/null
+rm secretfile.txt x509.ext 2>/dev/null
index a606368..15cccb7 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 #
 # ============LICENSE_START=======================================================
-#  Copyright (C) 2022 Nordix Foundation.
+#  Copyright (C) 2022-2023 Nordix Foundation.
 # ================================================================================
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 CA_SUBJECT="/C=IE/ST=Dublin/L=Dublin/O=Keycloak/OU=Keycloak/CN=localhost/emailAddress=ca@mail.com"
 SERVER_SUBJECT="/C=IE/ST=Dublin/L=Dublin/O=Keycloak/OU=Keycloak/CN=localhost/emailAddress=server@mail.com"
 PW=changeit
+CERTNAME=tls
+CANAME=rootCA
+IP=$(minikube ip)
+DAYS=3650
+TRUSTSTORE=server.truststore
+KEYSTORE=server.keystore
+STORETYPE=PKCS12
 
+rm $TRUSTSTORE $KEYSTORE ${CANAME}.key ${CANAME}.crt ${CERTNAME}.key ${CERTNAME}.csr ${CERTNAME}.crt ${CERTNAME}.p12 2>/dev/null
 echo $PW > secretfile.txt
 
-openssl req -x509 -sha256 -days 3650 -newkey rsa:4096 -keyout rootCA.key -subj "$CA_SUBJECT" -passout file:secretfile.txt -out rootCA.crt
+openssl req -x509 -sha256 -days $DAYS -newkey rsa:4096 -keyout ${CANAME}.key -subj "$CA_SUBJECT" -passout file:secretfile.txt -out ${CANAME}.crt
 
-openssl req -new -newkey rsa:4096 -keyout tls.key -subj "$SERVER_SUBJECT" -out tls.csr -nodes
+openssl req -new -newkey rsa:4096 -keyout ${CERTNAME}.key -subj "$SERVER_SUBJECT" -out ${CERTNAME}.csr -nodes
 
-echo "authorityKeyIdentifier=keyid,issuer" > openssl.ext
-echo "basicConstraints=CA:FALSE" >> openssl.ext
-echo "subjectAltName = @alt_names" >> openssl.ext
-echo "[alt_names]" >> openssl.ext
-echo "DNS.1 = localhost" >> openssl.ext
+echo "subjectKeyIdentifier   = hash" > x509.ext
+echo "authorityKeyIdentifier = keyid:always,issuer:always" >> x509.ext
+echo "basicConstraints       = CA:TRUE" >> x509.ext
+echo "keyUsage               = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign" >> x509.ext
+echo "subjectAltName         = DNS.1:localhost, IP.1:127.0.0.1, DNS.2:minikube, IP.2:${IP}, DNS.3:keycloak.default, DNS.4:keycloak.est.tech, DNS.5:keycloak" >> x509.ext
+echo "issuerAltName          = issuer:copy" >> x509.ext
+echo "[ ca ]" >> x509.ext
+echo "# X509 extensions for a ca" >> x509.ext
+echo "keyUsage                = critical, cRLSign, keyCertSign" >> x509.ext
+echo "basicConstraints        = CA:TRUE, pathlen:0" >> x509.ext
+echo "subjectKeyIdentifier    = hash" >> x509.ext
+echo "authorityKeyIdentifier  = keyid:always,issuer:always" >> x509.ext
+echo "" >> x509.ext
+echo "[ server ]" >> x509.ext
+echo "# X509 extensions for a server" >> x509.ext
+echo "keyUsage                = critical,digitalSignature,keyEncipherment" >> x509.ext
+echo "extendedKeyUsage        = serverAuth,clientAuth" >> x509.ext
+echo "basicConstraints        = critical,CA:FALSE" >> x509.ext
+echo "subjectKeyIdentifier    = hash" >> x509.ext
+echo "authorityKeyIdentifier  = keyid,issuer:always" >> x509.ext 
 
-openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -in tls.csr -passin file:secretfile.txt -out tls.crt -days 365 -CAcreateserial -ext openssl.ext
+openssl x509 -req -CA ${CANAME}.crt -CAkey ${CANAME}.key -in ${CERTNAME}.csr -passin file:secretfile.txt -out ${CERTNAME}.crt -days $DAYS -CAcreateserial -extfile x509.ext
 
-rm secretfile.txt openssl.ext 2>/dev/null
+keytool -import -trustcacerts -file ${CANAME}.crt -keystore $TRUSTSTORE -storepass $PW  -storetype $STORETYPE -noprompt
+
+openssl pkcs12 -export -clcerts -in ${CERTNAME}.crt -inkey ${CERTNAME}.key -passout file:secretfile.txt -out ${CERTNAME}.p12
+
+keytool -importkeystore -srckeystore ${CERTNAME}.p12 -srcstorepass $PW -srcstoretype $STORETYPE -destkeystore $KEYSTORE -deststorepass $PW -deststoretype $STORETYPE 
+
+rm secretfile.txt x509.ext 2>/dev/null
index 2beace2..b6a18c3 100644 (file)
@@ -1,6 +1,6 @@
 #
 # ============LICENSE_START=======================================================
-#  Copyright (C) 2022 Nordix Foundation.
+#  Copyright (C) 2022-2023 Nordix Foundation.
 # ================================================================================
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 apiVersion: v1
 kind: ServiceAccount
 metadata:
-  name: keycloak
+  name: keycloak 
   namespace: default
 ---
 apiVersion: v1
 kind: Service
 metadata:
   name: keycloak
-  namespace: default
   labels:
     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
@@ -66,42 +65,48 @@ spec:
       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:16.1.1
-        imagePullPolicy: IfNotPresent
+        image: quay.io/keycloak/keycloak:latest
+        imagePullPolicy: IfNotPresent 
+        args: [ 
+                'start',
+                '--https-key-store-file=/etc/x509/https/server.keystore',
+                '--https-key-store-password=changeit',
+                '--https-key-store-type=PKCS12',
+                '--https-trust-store-file=/etc/x509/https/server.truststore',
+                '--https-trust-store-password=changeit',
+                '--https-trust-store-type=PKCS12',
+                '--https-client-auth=request',
+                '--http-enabled=true'
+              ]
+
         env:
-        - name: KEYCLOAK_USER
-          value: "admin"
-        - name: KEYCLOAK_PASSWORD
-          value: "admin"
-        - name: KEYCLOAK_HTTPS_PORT
-          value: "8443"
-        - name: PROXY_ADDRESS_FORWARDING
+        - name : X509_CA_BUNDLE 
+          value: /etc/x509/https/rootCA.crt 
+        - name : KEYCLOAK_ADMIN 
+          value: admin 
+        - name : KEYCLOAK_ADMIN_PASSWORD 
+          value: admin 
+        - name : KC_DB 
+          value: postgres 
+        - name : KC_DB_URL 
+          value: "jdbc:postgresql://postgres:5432/keycloak"  
+        - name : KC_DB_USERNAME
+          value: keycloak
+        - name : KC_DB_PASSWORD
+          value: keycloak
+        - name : KC_HOSTNAME
+          value: keycloak 
+        - name : MY_PROVIDER_JAR_URL 
+          value: /opt/jboss/keycloak/standalone/deployments/authz-js-policies.jar 
+        - name: KC_HEALTH_ENABLED
+          value: "true"
+        - name: KC_METRICS_ENABLED 
           value: "true"
-        - name: MANAGEMENT_USER
-          value: "wildfly-admin"
-        - name: MANAGEMENT_PASSWORD
-          value: "secret"
-        - name: INGRESS_ENABLED
-          value: "false"
-        - name: DB_VENDOR
-          value: "postgres"
-        - name: DB_ADDR
-          value: "postgres"
-        - name: DB_PORT
-          value: "5432"
-        - name: DB_DATABASE
-          value: "keycloak"
-        - name: DB_USER
-          value: "keycloak"
-        - name : DB_PASSWORD
-          value: "keycloak"
-        - name : X509_CA_BUNDLE
-          value: /etc/x509/https/rootCA.crt
         ports:
         - name: http
           containerPort: 8080
@@ -109,22 +114,28 @@ spec:
           containerPort: 8443
         readinessProbe:
           httpGet:
-            path: /auth/realms/master
-            port: 8080
+            scheme: HTTPS 
+            path: /health/ready 
+            port: 8443
         volumeMounts:
-        - name: keycloak-certs
-          mountPath: /etc/x509/https
+        - name: keycloak-certs 
+          mountPath: /etc/x509/https 
+        - name: authz-js-policies 
+          mountPath: /opt/jboss/keycloak/standalone/deployments/authz-js-policies.jar 
       volumes:
-      - name: keycloak-certs
+      - name: keycloak-certs 
         hostPath:
-           path: /var/keycloak/certs
+           path: /var/keycloak/certs 
            type: Directory
+      - name: authz-js-policies 
+        hostPath:
+           path: /var/keycloak/deployments/authz-js-policies.jar 
+           type: File
 ---
 apiVersion: networking.istio.io/v1alpha3
 kind: Gateway
 metadata:
   name: kcgateway
-  namespace: default
 spec:
   selector:
     istio: ingressgateway # use istio default ingress gateway
@@ -136,7 +147,7 @@ spec:
     tls:
       mode: PASSTHROUGH
     hosts:
-    - keycloak.oran.org
+    - keycloak.est.tech
   - port:
       number: 80
       name: http
@@ -148,17 +159,16 @@ apiVersion: networking.istio.io/v1alpha3
 kind: VirtualService
 metadata:
   name: keycloak-tls-vs
-  namespace: default
 spec:
   hosts:
-  - keycloak.oran.org
+  - keycloak.est.tech
   gateways:
   - kcgateway
   tls:
   - match:
     - port: 443
       sniHosts:
-      - keycloak.oran.org
+      - keycloak.est.tech
     route:
     - destination:
         host: keycloak.default.svc.cluster.local
@@ -169,17 +179,16 @@ apiVersion: networking.istio.io/v1beta1
 kind: VirtualService
 metadata:
   name: keycloak-vs
-  namespace: default
 spec:
   hosts:
   - "*"
   gateways:
-  - kcgateway
+  - kcgateway 
   http:
   - name: "keycloak-routes"
     match:
     - uri:
-        prefix: "/auth"
+        prefix: "/realms"
     route:
     - destination:
         port:
index 9dec9f7..4a5d464 100644 (file)
@@ -2,7 +2,7 @@
 //   ========================LICENSE_START=================================
 //   O-RAN-SC
 //   %%
-//   Copyright (C) 2022: Nordix Foundation
+//   Copyright (C) 2022-2023: Nordix Foundation
 //   %%
 //   Licensed under the Apache License, Version 2.0 (the "License");
 //   you may not use this file except in compliance with the License.
@@ -225,7 +225,6 @@ func runUninstall(res http.ResponseWriter, req *http.Request) {
 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
@@ -243,7 +242,7 @@ func uninstallSecurity(rapp Rapp, chartName string) error {
                // remove keycloak client
                fmt.Println("Removing keycloak client")
                url = "http://rapps-keycloak-mgr.default/remove?"
-               params = "name=" + client + "&realm=" + realm + "&role=" + role + "&authType=" + authenticator
+               params = "name=" + client + "&realm=" + realm + "&authType=" + authenticator
                url += params
                _, err = http.Get(url)
                if err != nil {
index d220458..ae00432 100644 (file)
@@ -2,7 +2,7 @@
 //   ========================LICENSE_START=================================
 //   O-RAN-SC
 //   %%
-//   Copyright (C) 2022: Nordix Foundation
+//   Copyright (C) 2022-2023: Nordix Foundation
 //   %%
 //   Licensed under the Apache License, Version 2.0 (the "License");
 //   you may not use this file except in compliance with the License.
@@ -70,7 +70,7 @@ func getToken(res http.ResponseWriter, req *http.Request) {
        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"
+       keycloakUrl := "http://" + keycloakHost + ":" + keycloakPort + "/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", "")
@@ -78,6 +78,8 @@ func getToken(res http.ResponseWriter, req *http.Request) {
        if authenticator == "client-jwt" {
                resp, err = getJwtToken(keycloakUrl, clientId)
        } else if authenticator == "client-x509" {
+               keycloakPort = "443"
+               keycloakUrl := "https://" + keycloakAlias + ":" + keycloakPort + "/realms/" + realmName + "/protocol/openid-connect/token"
                resp, err = getx509Token(keycloakUrl, clientId)
        } else {
                resp, err = getSecretToken(keycloakUrl, clientId)
@@ -119,8 +121,10 @@ func getJwtToken(keycloakUrl, clientId string) (*http.Response, error) {
 }
 
 func getClientAssertion() string {
-       realm := "http://" + keycloakHost + ":" + keycloakPort + "/auth/realms/" + realmName
-       clientAssertion := generatejwt.CreateJWT("/certs/client.key", "", clientId, realm)
+       //aud := "http://" + keycloakHost + ":" + keycloakPort + "/auth/realms/" + realmName
+       //aud := "http://keycloak/auth/realms/" + realmName
+       aud := "https://keycloak:8443/realms/" + realmName
+       clientAssertion := generatejwt.CreateJWT("/certs/client.key", "", clientId, aud)
        return clientAssertion
 }
 
@@ -214,7 +218,7 @@ func health(res http.ResponseWriter, req *http.Request) {
 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.StringVar(&keycloakAlias, "keycloakAlias", "keycloak.est.tech", "Keycloak URL Alias")
        flag.Parse()
 
        healthHandler := http.HandlerFunc(health)
index 35e503d..6c72d87 100644 (file)
@@ -1,33 +1,36 @@
 // -
-//   ========================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
+//     ========================LICENSE_START=================================
+//     O-RAN-SC
+//     %%
+//     Copyright (C) 2022-2023: 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
 //
-//   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===================================
+//          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"
        "context"
+       "encoding/json"
        "fmt"
-       "github.com/Nerzal/gocloak/v10"
+       "io/ioutil"
        corev1 "k8s.io/api/core/v1"
        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/pemtojwks"
 )
 
@@ -35,6 +38,84 @@ const (
        namespace = "istio-nonrtric"
 )
 
+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
+}
+
+type RealmRepresentation struct {
+       Id          string `json:"id,omitempty"`
+       Realm       string `json:"realm,omitempty"`
+       DisplayName string `json:"displayName,omitempty"`
+       Enabled     bool   `json:"enabled"`
+}
+
+type Client struct {
+       ClientID                           string            `json:"clientId,omitempty"`
+       Enabled                            bool              `json:"enabled,omitempty"`
+       DirectAccessGrantsEnabled          bool              `json:"directAccessGrantsEnabled,omitempty"`
+       BearerOnly                         bool              `json:"bearerOnly,omitempty"`
+       PublicClient                       bool              `json:"publicClient,omitempty"`
+       ServiceAccountsEnabled             bool              `json:"serviceAccountsEnabled,omitempty"`
+       ClientAuthenticatorType            string            `json:"clientAuthenticatorType,omitempty"`
+       DefaultClientScopes                []string          `json:"defaultClientScopes,omitempty"`
+       Attributes                         map[string]string `json:"attributes,omitempty"`
+       AuthenticationFlowBindingOverrides map[string]string `json:"authenticationFlowBindingOverrides,omitempty"`
+}
+
+type Role struct {
+       Name string `json:"name,omitempty"`
+}
+
+type User struct {
+       ID       string `json:"id,omitempty"`
+       Username string `json:"username,omitempty"`
+       Email    string `json:"email,omitempty"`
+       Enabled  bool   `json:"enabled"`
+}
+
+type ProtocolMapperRepresentation struct {
+       Name           string            `json:"name,omitempty"`
+       Protocol       string            `json:"protocol,omitempty"`
+       ProtocolMapper string            `json:"protocolMapper,omitempty"`
+       Config         map[string]string `json:"config,omitempty"`
+}
+
+type RoleRepresentation struct {
+       ID         string `json:"id,omitempty"`
+       Name       string `json:"name,omitempty"`
+       Composite  bool   `json:"composite"`
+       ClientRole bool   `json:"clientRole"`
+}
+
+type AuthenticationFlowRepresentation struct {
+       Alias                   string   `json:"alias,omitempty"`
+       Description             string   `json:"description,omitempty"`
+       ProviderId              string   `json:"providerId,omitempty"`
+       TopLevel                bool     `json:"topLevel"`
+       BuiltIn                 bool     `json:"builtIn"`
+       AthenticationExecutions []string `json:"authenticationExecutions,omitempty"`
+}
+
+type Execution struct {
+       Provider string `json:"provider,omitempty"`
+}
+
+type AuthenticatorConfigRepresentation struct {
+       Alias  string            `json:"alias,omitempty"`
+       Config map[string]string `json:"config,omitempty"`
+}
+
+var keycloakUrl string = "http://keycloak:8080"
+var token Jwttoken
+var flowAlias string = "x509 direct grant"
+
 func createClient(res http.ResponseWriter, req *http.Request) {
        query := req.URL.Query()
        realmName := query.Get("realm")
@@ -47,7 +128,7 @@ func createClient(res http.ResponseWriter, req *http.Request) {
                msg = err.Error()
        }
        if authType == "client-secret" {
-               createSecret(msg, clientName, realmName, role, namespace)
+               createSecret(msg, clientName, realmName, namespace)
        }
        // create response binary data
        data := []byte(msg) // slice of bytes
@@ -59,13 +140,12 @@ func removeClient(res http.ResponseWriter, req *http.Request) {
        query := req.URL.Query()
        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 authType == "client-secret" {
-               removeSecret(namespace, role)
+               removeSecret(namespace, clientName)
        }
        // create response binary data
        data := []byte(msg) // slice of bytes
@@ -81,220 +161,269 @@ func main() {
        http.ListenAndServe(":9000", nil)
 }
 
-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")
+func getAdminToken() {
+       var resp = &http.Response{}
+       var err error
+       username := "admin"
+       password := "admin"
+       clientId := "admin-cli"
+       restUrl := keycloakUrl + "/realms/master/protocol/openid-connect/token"
+       resp, err = http.PostForm(restUrl,
+               url.Values{"username": {username}, "password": {password}, "grant_type": {"password"}, "client_id": {clientId}})
        if err != nil {
-               return "", err
+               fmt.Println(err)
+               panic("Something wrong with the credentials or url ")
        }
+       defer resp.Body.Close()
+       body, err := ioutil.ReadAll(resp.Body)
+       json.Unmarshal([]byte(body), &token)
+}
 
-       _, err = client.GetRealm(ctx, token.AccessToken, realmName)
-       if err != nil {
-               realmRepresentation := gocloak.RealmRepresentation{
-                       ID:          gocloak.StringP(realmName),
-                       Realm:       gocloak.StringP(realmName),
-                       DisplayName: gocloak.StringP(realmName),
-                       Enabled:     gocloak.BoolP(true),
-               }
-
-               realm, err := client.CreateRealm(ctx, token.AccessToken, realmRepresentation)
-               if err != nil {
-                       return "", err
-               } else {
-                       fmt.Println("Created realm", realm)
-               }
-       } else {
-               fmt.Println("Realm already exists", realmName)
-       }
+func sendRequest(method, url string, data []byte) (int, string) {
+       fmt.Printf("Sending %s request to %s\n", method, url)
+       req, err := http.NewRequest(method, url, bytes.NewBuffer(data))
+       req.Header.Set("Content-Type", "application/json")
+       req.Header.Set("Authorization", "Bearer "+token.Access_token)
 
-       flowAlias := "x509 direct grant"
-       flowId := ""
-       flows, err := client.GetAuthenticationFlows(ctx, token.AccessToken, realmName)
+       client := &http.Client{}
+       resp, err := client.Do(req)
        if err != nil {
-               fmt.Println("Oh no!, failed to get flows :(")
-       } else {
-               for _, flow := range flows {
-                       if flow.Alias != nil && *flow.Alias == flowAlias {
-                               flowId = *flow.ID
-                       }
-               }
-               fmt.Println("Retrieved AuthenticationFlow id", flowId)
-       }
-
-       secretClient := 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-secret"),
-               DefaultClientScopes:       &[]string{"email"},
-               Attributes: &map[string]string{"use.refresh.tokens": "true",
-                       "client_credentials.use_refresh_token": "true"},
-       }
-
-       x509Client := 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-x509"),
-               DefaultClientScopes:       &[]string{"openid", "profile", "email"},
-               Attributes: &map[string]string{"use.refresh.tokens": "true",
-                       "client_credentials.use_refresh_token": "true",
-                       "x509.subjectdn":                       ".*client@mail.com.*",
-                       "x509.allow.regex.pattern.comparison":  "true"},
-               AuthenticationFlowBindingOverrides: &map[string]string{"direct_grant": flowId},
+               panic(err)
        }
+       defer resp.Body.Close()
+       body, _ := ioutil.ReadAll(resp.Body)
+       respString := string(body)
+       fmt.Println("response Status:", resp.Status)
+       return resp.StatusCode, respString
+}
 
-       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",
-               },
+func create(realmName, clientName, clientRoleName, authType string) (string, error) {
+       getAdminToken()
+       var userId string = ""
+       var jsonValue []byte = []byte{}
+       restUrl := keycloakUrl + "/realms/" + realmName
+       statusCode, _ := sendRequest("GET", restUrl, nil)
+
+       if statusCode != 200 {
+               realmRepresentation := RealmRepresentation{
+                       Id:          realmName,
+                       Realm:       realmName,
+                       DisplayName: realmName,
+                       Enabled:     true,
+               }
+               restUrl := keycloakUrl + "/admin/realms"
+               jsonValue, _ := json.Marshal(realmRepresentation)
+               statusCode, _ = sendRequest("POST", restUrl, jsonValue)
        }
 
-       var newClient gocloak.Client
+       var flowId string = ""
        if authType == "client-x509" {
-               newClient = x509Client
-       } else if authType == "client-jwt" {
-               newClient = jwtClient
-       } else {
-               newClient = secretClient
+               flowId = getFlowId(realmName)
+               if flowId == "" {
+                       createx509Flow(realmName)
+                       flowId = getFlowId(realmName)
+               }
+               newUser := User{
+                       ID:       realmName + "user",
+                       Username: realmName + "user",
+                       Email:    "client@mail.com",
+                       Enabled:  true,
+               }
+               restUrl = keycloakUrl + "/admin/realms/" + realmName + "/users"
+               jsonValue, _ = json.Marshal(newUser)
+               statusCode, _ = sendRequest("POST", restUrl, jsonValue)
+               userId = getUserId(realmName, realmName+"user")
        }
 
-       clientId, err := client.CreateClient(ctx, token.AccessToken, realmName, newClient)
-       if err != nil {
-               fmt.Println("Failed to create client", err)
-               return "", err
-       } else {
-               fmt.Println("Created realm client", clientId)
-       }
+       newClient := getClient(authType, clientName, flowId)
+       restUrl = keycloakUrl + "/admin/realms/" + realmName + "/clients"
+       jsonValue, _ = json.Marshal(newClient)
+       statusCode, _ = sendRequest("POST", restUrl, jsonValue)
 
-       newClientRole := gocloak.Role{
-               Name: gocloak.StringP(clientRoleName),
-       }
-       clientRoleName, err = client.CreateClientRole(ctx, token.AccessToken, realmName, clientId, newClientRole)
-       if err != nil {
-               return "", err
-       } else {
-               fmt.Println("Created client role", clientRoleName)
+       clientId, clientSecret := getClientInfo(realmName, clientName)
+
+       newClientRole := Role{
+               Name: clientRoleName,
        }
+       restUrl = keycloakUrl + "/admin/realms/" + realmName + "/clients/" + clientId + "/roles"
+       jsonValue, _ = json.Marshal(newClientRole)
+       statusCode, _ = sendRequest("POST", restUrl, jsonValue)
 
-       user, err := client.GetClientServiceAccount(ctx, token.AccessToken, realmName, clientId)
+       restUrl = keycloakUrl + "/admin/realms/" + realmName + "/clients/" + clientId + "/roles/" + clientRoleName
+       statusCode, data := sendRequest("GET", restUrl, nil)
+       roles := make(map[string]interface{})
+       err := json.Unmarshal([]byte(data), &roles)
        if err != nil {
                fmt.Println(err)
-               panic("Oh no!, failed to get client user :(")
-       } else {
-               fmt.Println("Service Account user", *user.Username)
        }
+       roleId := fmt.Sprintf("%v", roles["id"])
 
-       if authType == "client-x509" {
-               newUser := gocloak.User{
-                       ID:       gocloak.StringP(realmName + "user"),
-                       Username: gocloak.StringP(realmName + "user"),
-                       Email:    gocloak.StringP("client@mail.com"),
-                       Enabled:  gocloak.BoolP(true),
-               }
-
-               realmUser, err := client.CreateUser(ctx, token.AccessToken, realmName, newUser)
+       if authType != "client-x509" {
+               restUrl = keycloakUrl + "/admin/realms/" + realmName + "/clients/" + clientId + "/service-account-user"
+               statusCode, data = sendRequest("GET", restUrl, nil)
+               serviceAccount := make(map[string]interface{})
+               err = json.Unmarshal([]byte(data), &serviceAccount)
                if err != nil {
                        fmt.Println(err)
-                       panic("Oh no!, failed to create user :(")
-               } else {
-                       fmt.Println("Created new user", realmUser)
                }
+               userId = fmt.Sprintf("%v", serviceAccount["id"])
        }
 
-       clientRole, err := client.GetClientRole(ctx, token.AccessToken, realmName, clientId, clientRoleName)
-       if err != nil {
-               fmt.Println(err)
-               panic("Oh no!, failed to get client role :(")
-       } else {
-               fmt.Println("Retrieved client role", clientRoleName)
+       roleRepresentation := RoleRepresentation{
+               ID:         roleId,
+               Name:       clientRoleName,
+               Composite:  false,
+               ClientRole: true,
        }
 
-       clientRoles := []gocloak.Role{*clientRole}
-       err = client.AddClientRoleToUser(ctx, token.AccessToken, realmName, clientId, *user.ID, clientRoles)
-       if err != nil {
-               fmt.Println(err)
-               panic("Oh no!, failed to add client role to user :(")
-       } else {
-               fmt.Printf("Added %s to %s\n", *clientRole.Name, *user.Username)
-       }
+       restUrl = keycloakUrl + "/admin/realms/" + realmName + "/users/" + userId + "/role-mappings/clients/" + clientId
+       jsonValue, _ = json.Marshal([]RoleRepresentation{roleRepresentation})
+       statusCode, data = sendRequest("POST", restUrl, jsonValue)
 
-       clientroleMapper := gocloak.ProtocolMapperRepresentation{
-               ID:             gocloak.StringP("Client Role " + clientName + " Mapper"),
-               Name:           gocloak.StringP("Client Role " + clientName + " Mapper"),
-               Protocol:       gocloak.StringP("openid-connect"),
-               ProtocolMapper: gocloak.StringP("oidc-usermodel-client-role-mapper"),
-               Config: &map[string]string{
+       clientroleMapper := ProtocolMapperRepresentation{
+               Name:           "Client Role " + clientName + " Mapper",
+               Protocol:       "openid-connect",
+               ProtocolMapper: "oidc-usermodel-client-role-mapper",
+               Config: map[string]string{
                        "access.token.claim":                   "true",
                        "aggregate.attrs":                      "",
                        "claim.name":                           "clientRole",
                        "id.token.claim":                       "true",
                        "jsonType.label":                       "String",
                        "multivalued":                          "true",
-                       "userinfo.token.claim":                 "true",
                        "usermodel.clientRoleMapping.clientId": clientName,
+                       "userinfo.token.claim":                 "false",
                },
        }
-       _, err = client.CreateClientProtocolMapper(ctx, token.AccessToken, realmName, clientId, clientroleMapper)
-       if err != nil {
-               fmt.Println(err)
-               panic("Oh no!, failed to add client roleampper to client :(")
+
+       restUrl = keycloakUrl + "/admin/realms/" + realmName + "/clients/" + clientId + "/protocol-mappers/models"
+       jsonValue, _ = json.Marshal(clientroleMapper)
+       statusCode, _ = sendRequest("POST", restUrl, jsonValue)
+       return clientSecret, nil
+}
+
+func getClient(authType, clientName, flowId string) Client {
+       var newClient Client
+       newClient.ClientID = clientName
+       newClient.Enabled = true
+       newClient.DirectAccessGrantsEnabled = true
+       newClient.BearerOnly = false
+       newClient.PublicClient = false
+       newClient.ServiceAccountsEnabled = true
+       newClient.ClientAuthenticatorType = authType
+       newClient.DefaultClientScopes = []string{"email"}
+       if authType == "client-secret" {
+               newClient.Attributes = map[string]string{
+                       "use.refresh.tokens":                   "true",
+                       "client_credentials.use_refresh_token": "true"}
+       } else if authType == "client-x509" {
+               newClient.Attributes = map[string]string{
+                       "use.refresh.tokens":                   "true",
+                       "client_credentials.use_refresh_token": "true",
+                       "x509.subjectdn":                       ".*client@mail.com.*",
+                       "x509.allow.regex.pattern.comparison":  "true"}
+               newClient.AuthenticationFlowBindingOverrides = map[string]string{
+                       "direct_grant": flowId}
        } else {
-               fmt.Println("Client rolemapper added to client")
+               jwksString, publicKey, kid := pemtojwks.CreateJWKS("/certs/client.crt")
+               newClient.Attributes = map[string]string{
+                       "token.endpoint.auth.signing.alg":      "RS256",
+                       "jwt.credential.public.key":            publicKey,
+                       "jwt.credential.kid":                   kid,
+                       "use.jwks.url":                         "false",
+                       "jwks.url":                             jwksString,
+                       "use.refresh.tokens":                   "true",
+                       "client_credentials.use_refresh_token": "true",
+               }
        }
+       return newClient
+}
 
-       if authType == "client-x509" {
-               clientRole := *newClient.ClientID + "." + clientRoleName
-
-               clientroleMapper := gocloak.ProtocolMapperRepresentation{
-                       ID:             gocloak.StringP("Hardcoded " + clientName + " Mapper"),
-                       Name:           gocloak.StringP("Hardcoded " + clientName + " Mapper"),
-                       Protocol:       gocloak.StringP("openid-connect"),
-                       ProtocolMapper: gocloak.StringP("oidc-hardcoded-role-mapper"),
-                       Config: &map[string]string{
-                               "role": clientRole,
-                       },
-               }
-               _, err = client.CreateClientProtocolMapper(ctx, token.AccessToken, realmName, clientId, clientroleMapper)
-               if err != nil {
-                       return "", err
-               } else {
-                       fmt.Println("Created hardcoded-role-mapper for ", clientRole)
-               }
+func getClientInfo(realmName, clientName string) (string, string) {
+       restUrl := keycloakUrl + "/admin/realms/" + realmName + "/clients?clientId=" + clientName
+       _, data := sendRequest("GET", restUrl, nil)
+
+       clients := make([]map[string]interface{}, 0)
+       err := json.Unmarshal([]byte(data), &clients)
+       if err != nil {
+               fmt.Println(err)
        }
+       clientId := fmt.Sprintf("%v", clients[0]["id"])
+       clientSecret := fmt.Sprintf("%v", clients[0]["secret"])
+       return clientId, clientSecret
+}
 
-       _, err = client.RegenerateClientSecret(ctx, token.AccessToken, realmName, clientId)
+func createx509Flow(realmName string) {
+       var jsonValue []byte = []byte{}
+       authenticationFlowRepresentation := AuthenticationFlowRepresentation{
+               Alias:                   flowAlias,
+               Description:             "OpenID Connect Resource Owner Grant",
+               ProviderId:              "basic-flow",
+               TopLevel:                true,
+               BuiltIn:                 false,
+               AthenticationExecutions: []string{},
+       }
+       restUrl := keycloakUrl + "/admin/realms/" + realmName + "/authentication/flows"
+       jsonValue, _ = json.Marshal(authenticationFlowRepresentation)
+       sendRequest("POST", restUrl, jsonValue)
+
+       execution := Execution{
+               Provider: "direct-grant-auth-x509-username",
+       }
+       restUrl = keycloakUrl + "/admin/realms/" + realmName + "/authentication/flows/" + flowAlias + "/executions/execution"
+       jsonValue, _ = json.Marshal(execution)
+       sendRequest("POST", restUrl, jsonValue)
+
+       restUrl = keycloakUrl + "/admin/realms/" + realmName + "/authentication/flows/" + flowAlias + "/executions"
+       _, data := sendRequest("GET", restUrl, nil)
+       executionInfo := make([]map[string]interface{}, 0)
+       err := json.Unmarshal([]byte(data), &executionInfo)
        if err != nil {
-               return "", err
+               fmt.Println(err)
        }
+       executionId := fmt.Sprintf("%v", executionInfo[0]["id"])
+
+       authenticatorConfigRepresentation := AuthenticatorConfigRepresentation{
+               Alias: flowAlias + " config",
+               Config: map[string]string{
+                       "x509-cert-auth.canonical-dn-enabled":           "false",
+                       "x509-cert-auth.serialnumber-hex-enabled":       "false",
+                       "x509-cert-auth.ocsp-fail-open":                 "false",
+                       "x509-cert-auth.regular-expression":             "(.*?)(?:$)",
+                       "x509-cert-auth.crl-checking-enabled":           "false",
+                       "x509-cert-auth.certificate-policy-mode":        "All",
+                       "x509-cert-auth.timestamp-validation-enabled":   "false",
+                       "x509-cert-auth.confirmation-page-disallowed":   "false",
+                       "x509-cert-auth.mapper-selection":               "Username or Email",
+                       "x509-cert-auth.revalidate-certificate-enabled": "false",
+                       "x509-cert-auth.crldp-checking-enabled":         "false",
+                       "x509-cert-auth.mapping-source-selection":       "Subject's e-mail",
+                       "x509-cert-auth.ocsp-checking-enabled":          "false",
+               },
+       }
+       restUrl = keycloakUrl + "/admin/realms/" + realmName + "/authentication/executions/" + executionId + "/config"
+       jsonValue, _ = json.Marshal(authenticatorConfigRepresentation)
+       sendRequest("POST", restUrl, jsonValue)
+}
 
-       cred, err := client.GetClientSecret(ctx, token.AccessToken, realmName, clientId)
+func getFlowId(realmName string) string {
+       var flowId string = ""
+       restUrl := keycloakUrl + "/admin/realms/" + realmName + "/authentication/flows"
+       _, data := sendRequest("GET", restUrl, nil)
+       flows := make([]map[string]interface{}, 0)
+       err := json.Unmarshal([]byte(data), &flows)
        if err != nil {
-               return "", err
-       } else {
-               fmt.Println("Generated client secret", *cred.Value)
+               fmt.Println(err)
        }
 
-       return *cred.Value, nil
+       for i, _ := range flows {
+               id := fmt.Sprintf("%v", flows[i]["id"])
+               alias := fmt.Sprintf("%v", flows[i]["alias"])
+               if alias == flowAlias {
+                       flowId = id
+               }
+       }
+       return flowId
 }
 
 func connectToK8s() *kubernetes.Clientset {
@@ -311,8 +440,8 @@ func connectToK8s() *kubernetes.Clientset {
        return clientset
 }
 
-func createSecret(clientSecret, clientName, realmName, role, namespace string) {
-       secretName := role + "-secret"
+func createSecret(clientSecret, clientName, realmName, namespace string) {
+       secretName := clientName + "-secret"
        clientset := connectToK8s()
        secrets := clientset.CoreV1().Secrets(namespace)
        secret := &corev1.Secret{
@@ -336,52 +465,45 @@ func createSecret(clientSecret, clientName, realmName, role, namespace string) {
 }
 
 func remove(realmName, clientName string) {
-       adminClient := gocloak.NewClient("http://keycloak.default:8080")
-       ctx := context.Background()
-       token, err := adminClient.LoginAdmin(ctx, "admin", "admin", "master")
-       if err != nil {
-               fmt.Println(err)
-       }
+       getAdminToken()
+       clientId, _ := getClientInfo(realmName, clientName)
 
-       clients, err := adminClient.GetClients(ctx, token.AccessToken, realmName,
-               gocloak.GetClientsParams{
-                       ClientID: gocloak.StringP(clientName),
-               },
-       )
-       if err != nil {
-               panic("List clients failed:" + err.Error())
+       restUrl := keycloakUrl + "/admin/realms/" + realmName + "/clients/" + clientId
+       sendRequest("DELETE", restUrl, nil)
+
+       var userId string = ""
+       userName := realmName + "user"
+       userId = getUserId(realmName, userName)
+       if userId != "" {
+               restUrl = keycloakUrl + "/admin/realms/" + realmName + "/users/" + userId
+               sendRequest("DELETE", restUrl, nil)
        }
-       for _, client := range clients {
-               err = adminClient.DeleteClient(ctx, token.AccessToken, realmName, *client.ID)
-               if err != nil {
-                       fmt.Println(err)
-               } else {
-                       fmt.Println("Deleted client ", clientName)
-               }
+
+       flowId := getFlowId(realmName)
+       if flowId != "" {
+               restUrl = keycloakUrl + "/admin/realms/" + realmName + "/authentication/flows/" + flowId
+               sendRequest("DELETE", restUrl, nil)
        }
+}
 
-       userName := realmName + "user"
-       users, err := adminClient.GetUsers(ctx, token.AccessToken, realmName,
-               gocloak.GetUsersParams{
-                       Username: gocloak.StringP(userName),
-               })
+func getUserId(realmName, userName string) string {
+       var userId string = ""
+       restUrl := keycloakUrl + "/admin/realms/" + realmName + "/users?username=demouser"
+       _, data := sendRequest("GET", restUrl, nil)
+       user := make([]map[string]interface{}, 0)
+       err := json.Unmarshal([]byte(data), &user)
        if err != nil {
-               panic("List users failed:" + err.Error())
+               fmt.Println(err)
        }
-       for _, user := range users {
-               err = adminClient.DeleteUser(ctx, token.AccessToken, realmName, *user.ID)
-               if err != nil {
-                       fmt.Println(err)
-               } else {
-                       fmt.Println("Deleted user ", userName)
-               }
+       if len(user) > 0 {
+               userId = fmt.Sprintf("%v", user[0]["id"])
        }
-
+       return userId
 }
 
-func removeSecret(namespace, role string) {
+func removeSecret(namespace, clientName string) {
        clientset := connectToK8s()
-       secretName := role + "-secret"
+       secretName := clientName + "-secret"
        secrets := clientset.CoreV1().Secrets(namespace)
        err := secrets.Delete(context.TODO(), secretName, metav1.DeleteOptions{})
        if err != nil {
index 0899475..79c90e0 100644 (file)
@@ -1,6 +1,6 @@
 #
 # ============LICENSE_START=======================================================
-#  Copyright (C) 2022 Nordix Foundation.
+#  Copyright (C) 2022-2023 Nordix Foundation.
 # ================================================================================
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -30,7 +30,7 @@ spec:
   rules:
   - from:
     - source:
-        requestPrincipals: ["http://istio-ingressgateway.istio-system:80/auth/realms/{{.Realm}}/"]
+        requestPrincipals: ["http://istio-ingressgateway.istio-system:80/auth/realms/{{.Realm}}/", "https://keycloak:8443/realms/{{.Realm}}"]
   - to:
     - operation:
         methods: ["{{.Method}}"]
index 5fbdbbb..48f651a 100644 (file)
@@ -1,6 +1,6 @@
 #
 # ============LICENSE_START=======================================================
-#  Copyright (C) 2022 Nordix Foundation.
+#  Copyright (C) 2022-2023 Nordix Foundation.
 # ================================================================================
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -29,3 +29,5 @@ spec:
   jwtRules:
   - issuer: "http://istio-ingressgateway.istio-system:80/auth/realms/{{.Realm}}"
     jwksUri: "http://keycloak.default:8080/auth/realms/{{.Realm}}/protocol/openid-connect/certs"
+  - issuer: "https://keycloak:8443/realms/{{.Realm}}"
+    jwksUri: "http://keycloak.default:8080/realms/{{.Realm}}/protocol/openid-connect/certs"
index 6317843..d232d78 100644 (file)
@@ -2,7 +2,7 @@
 //   ========================LICENSE_START=================================
 //   O-RAN-SC
 //   %%
-//   Copyright (C) 2022: Nordix Foundation
+//   Copyright (C) 2022-2023: Nordix Foundation
 //   %%
 //   Licensed under the Apache License, Version 2.0 (the "License");
 //   you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
 //   limitations under the License.
 //   ========================LICENSE_END===================================
 //
-package pemtojwks
+package pemtojwks 
 
 import (
        "crypto/rsa"
@@ -38,6 +38,7 @@ type Jwks struct {
 type Key struct {
        Kid string `json:"kid,omitempty"`
        Kty string `json:"kty"`
+       Alg string `json:"alg"`
        Use string `json:"use"`
        N   string `json:"n"`
        E   string `json:"e"`
@@ -93,27 +94,35 @@ func getPublicKeyFromCert(cert_bytes []byte) *rsa.PublicKey {
         cert, _ = x509.ParseCertificate(block.Bytes)
         rsaPublicKey := cert.PublicKey.(*rsa.PublicKey)
 
-        return rsaPublicKey
+        return rsaPublicKey 
 }
 
-func CreateJWKS(certFile string) string {
+func CreateJWKS(certFile string) (string, string, string) {
        var publicKey *rsa.PublicKey
+       var kid string = "SIGNING_KEY"
 
        cert, err := ioutil.ReadFile(certFile)
        if err != nil {
                fmt.Println(err)
        }
        publicKey = getPublicKeyFromCert(cert)
+       publicKeyBytes, err := x509.MarshalPKIXPublicKey(publicKey)
+       if err != nil {
+               fmt.Println(err)
+       }
+       publicKeyPem := pem.EncodeToMemory(&pem.Block{Type: "RSA PUBLIC KEY", Bytes: publicKeyBytes})
+       block, _ := pem.Decode(publicKeyPem)
+       publicKeyString := base64.StdEncoding.EncodeToString(block.Bytes)
 
        certificate := getCert(cert)
        // generate fingerprint with sha1
        // you can also use md5, sha256, etc.
        fingerprint := sha1.Sum(certificate.Raw)
 
-
        jwksKey := Key{
-               Kid: "SIGNING_KEY",
+               Kid: kid,
                Kty: "RSA",
+               Alg: "RS256",
                Use: "sig",
                N: base64.RawStdEncoding.EncodeToString(publicKey.N.Bytes()),
                E: base64.RawStdEncoding.EncodeToString(big.NewInt(int64(publicKey.E)).Bytes()),
@@ -126,8 +135,7 @@ func CreateJWKS(certFile string) string {
        jwksJson, err := json.Marshal(jwks)
        if err != nil {
                fmt.Println(err)
-               return err.Error()
        }
-       return string(jwksJson)
+       return string(jwksJson), publicKeyString, kid
 
 }