Added provider and invoker

Change-Id: I443b8b11a2304621109a9729473e05af8461f4f0
diff --git a/rapps/rapps-keycloak-mgr.go b/rapps/rapps-keycloak-mgr.go
index 9496a48..0d0a29c 100644
--- a/rapps/rapps-keycloak-mgr.go
+++ b/rapps/rapps-keycloak-mgr.go
@@ -4,19 +4,43 @@
 	"context"
 	"fmt"
 	"github.com/Nerzal/gocloak/v10"
+	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"
 )
 
-// create a handler struct
-type HttpHandler struct{}
+const (
+  namespace = "istio-nonrtric"
+)
 
-// implement `ServeHTTP` method on `HttpHandler` struct
-func (h HttpHandler) ServeHTTP(res http.ResponseWriter, req *http.Request) {
+func createClient(res http.ResponseWriter, req *http.Request) {
+	query := req.URL.Query()
+	realmName := query.Get("realm")
+	clientName := query.Get("name")
+	role := query.Get("role")
 	var msg string
-	msg, err := createClient()
+	msg, err := create(realmName, clientName, role)
 	if err != nil {
 		msg = err.Error()
 	}
+	createSecret(msg, clientName, realmName, role, namespace)
+	// create response binary data
+	data := []byte(msg) // slice of bytes
+	// write `data` to response
+	res.Write(data)
+}
+
+func removeClient(res http.ResponseWriter, req *http.Request) {
+	query := req.URL.Query()
+	realmName := query.Get("realm")
+	clientName := query.Get("name")
+	role := query.Get("role")
+
+	var msg string = "Removed keycloak " + clientName + " from " + realmName + " realm"
+	remove(realmName, clientName)
+	removeSecret(namespace, role)
 	// create response binary data
 	data := []byte(msg) // slice of bytes
 	// write `data` to response
@@ -24,13 +48,14 @@
 }
 
 func main() {
-	// create a new handler
-	handler := HttpHandler{}
-	// listen and serve
-	http.ListenAndServe(":9000", handler)
+	createHandler := http.HandlerFunc(createClient)
+	http.Handle("/create", createHandler)
+	removeHandler := http.HandlerFunc(removeClient)
+	http.Handle("/remove", removeHandler)
+	http.ListenAndServe(":9000", nil)
 }
 
-func createClient() (string, error) {
+func create(realmName, clientName, clientRoleName string) (string, error) {
 	client := gocloak.NewClient("http://keycloak.default:8080")
 	ctx := context.Background()
 	token, err := client.LoginAdmin(ctx, "admin", "admin", "master")
@@ -38,7 +63,6 @@
 		return "", err
 	}
 
-	realmName := "hwrealm"
 	_, err = client.GetRealm(ctx, token.AccessToken, realmName)
 	if err != nil {
 		realmRepresentation := gocloak.RealmRepresentation{
@@ -59,14 +83,16 @@
 	}
 
 	newClient := gocloak.Client{
-		ClientID:                  gocloak.StringP("hwclient"),
+		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" },
+		DefaultClientScopes:       &[]string{"email"},
+		Attributes:                &map[string]string{"use.refresh.tokens": "true",
+	                                                      "client_credentials.use_refresh_token": "true"},
 	}
 	clientId, err := client.CreateClient(ctx, token.AccessToken, realmName, newClient)
 	if err != nil {
@@ -76,9 +102,9 @@
 	}
 
 	newClientRole := gocloak.Role{
-		Name: gocloak.StringP("hwclientrole"),
+		Name: gocloak.StringP(clientRoleName),
 	}
-	clientRoleName, err := client.CreateClientRole(ctx, token.AccessToken, realmName, clientId, newClientRole)
+	clientRoleName, err = client.CreateClientRole(ctx, token.AccessToken, realmName, clientId, newClientRole)
 	if err != nil {
 		return "", err
 	} else {
@@ -123,7 +149,7 @@
 			"jsonType.label":                       "String",
 			"multivalued":                          "true",
 			"userinfo.token.claim":                 "true",
-			"usermodel.clientRoleMapping.clientId": "hwclient",
+			"usermodel.clientRoleMapping.clientId": clientName,
 		},
 	}
 	_, err = client.CreateClientProtocolMapper(ctx, token.AccessToken, realmName, clientId, clientroleMapper)
@@ -148,3 +174,79 @@
 
 	return *cred.Value, nil
 }
+
+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 createSecret(clientSecret, clientName, realmName, role, namespace string) {
+	secretName := role +"-secret"
+	clientset := connectToK8s()
+	secrets := clientset.CoreV1().Secrets(namespace)
+	secret := &corev1.Secret{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      secretName,
+			Namespace: namespace,
+			Labels: map[string]string{
+                                        "app" : secretName,
+                                },
+		},
+		Type:       "Opaque",
+		StringData: map[string]string{"client_secret": clientSecret, "client_id": clientName, "realm": realmName},
+	}
+
+	_, err := secrets.Create(context.TODO(), secret, metav1.CreateOptions{})
+	if err != nil {
+		fmt.Println("Failed to create K8s secret.", err)
+	}
+
+	fmt.Println("Created K8s secret successfully")
+}
+
+func remove(realmName, clientName string) {
+	adminClient := gocloak.NewClient("http://192.168.49.2:31560")
+	ctx := context.Background()
+	token, err := adminClient.LoginAdmin(ctx, "admin", "admin", "master")
+	if err != nil {
+		fmt.Println(err)
+	}
+
+	clients, err := adminClient.GetClients(ctx, token.AccessToken, realmName,
+		gocloak.GetClientsParams{
+			ClientID: gocloak.StringP(clientName),
+		},
+	)
+	if err != nil {
+		panic("List clients failed:" + err.Error())
+	}
+	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)
+		}
+	}
+}
+
+func removeSecret(namespace, role string) {
+	clientset := connectToK8s()
+	secretName := role +"-secret"
+	secrets := clientset.CoreV1().Secrets(namespace)
+	err := secrets.Delete(context.TODO(), secretName, metav1.DeleteOptions{})
+	if err != nil {
+		fmt.Println(err)
+	} else {
+		fmt.Println("Deleted Secret", secretName)
+	}
+}