fb584bd7d409e25622cdfe749793beb076f60da9
[nonrtric.git] / service-exposure / rapps-istio-mgr.go
1 // -
2 //   ========================LICENSE_START=================================
3 //   O-RAN-SC
4 //   %%
5 //   Copyright (C) 2022: Nordix Foundation
6 //   %%
7 //   Licensed under the Apache License, Version 2.0 (the "License");
8 //   you may not use this file except in compliance with the License.
9 //   You may obtain a copy of the License at
10 //
11 //        http://www.apache.org/licenses/LICENSE-2.0
12 //
13 //   Unless required by applicable law or agreed to in writing, software
14 //   distributed under the License is distributed on an "AS IS" BASIS,
15 //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 //   See the License for the specific language governing permissions and
17 //   limitations under the License.
18 //   ========================LICENSE_END===================================
19 //
20 package main
21
22 import (
23         "bytes"
24         "context"
25         "fmt"
26         netv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1"
27         netv1alpha3 "istio.io/client-go/pkg/apis/networking/v1alpha3"
28         secv1beta1 "istio.io/client-go/pkg/apis/security/v1beta1"
29         versioned "istio.io/client-go/pkg/clientset/versioned"
30         metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31         k8Yaml "k8s.io/apimachinery/pkg/util/yaml"
32         "k8s.io/client-go/rest"
33         clientcmd "k8s.io/client-go/tools/clientcmd"
34         "log"
35         "net/http"
36         "os"
37         "path/filepath"
38         "text/template"
39 )
40
41 const (
42         NAMESPACE = "istio-nonrtric"
43 )
44
45 type TemplateConfig struct {
46     Name string
47     Namespace string
48     Realm string
49     Client string
50     Authenticator string
51     Role string
52     Method string
53 }
54
55 var inputs TemplateConfig
56 var appName string
57
58 var config *template.Template
59
60 func connectToK8s() *versioned.Clientset {
61         config, err := rest.InClusterConfig()
62         if err != nil {
63                 // fallback to kubeconfig
64                 home, exists := os.LookupEnv("HOME")
65                 if !exists {
66                         home = "/root"
67                 }
68
69                 kubeconfig := filepath.Join(home, ".kube", "config")
70                 if envvar := os.Getenv("KUBECONFIG"); len(envvar) > 0 {
71                         kubeconfig = envvar
72                 }
73                 config, err = clientcmd.BuildConfigFromFlags("", kubeconfig)
74                 if err != nil {
75                         log.Fatalln("failed to create K8s config")
76                 }
77         }
78
79         ic, err := versioned.NewForConfig(config)
80         if err != nil {
81                 log.Fatalf("Failed to create istio client: %s", err)
82         }
83
84         return ic
85 }
86
87 func createGateway(clientset *versioned.Clientset) (string, error) {
88         gtClient := clientset.NetworkingV1beta1().Gateways(NAMESPACE)
89         config = template.Must(template.ParseFiles("./templates/Gateway-template.txt"))
90         var manifest bytes.Buffer
91         err := config.Execute(&manifest, inputs)
92         if err != nil {
93                 return "", err
94         }
95
96         gt := &netv1beta1.Gateway{}
97         dec := k8Yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(manifest.String())), 1000)
98
99         if err := dec.Decode(&gt); err != nil {
100                 return "", err
101         }
102
103         result, err := gtClient.Create(context.TODO(), gt, metav1.CreateOptions{})
104
105         if err != nil {
106                 return "", err
107         }
108
109         fmt.Printf("Create Gateway %s \n", result.GetName())
110         return result.GetName(), nil
111 }
112
113 func createVirtualService(clientset *versioned.Clientset) (string, error) {
114         vsClient := clientset.NetworkingV1beta1().VirtualServices(NAMESPACE)
115         config = template.Must(template.ParseFiles("./templates/VirtualService-template.txt"))
116         var manifest bytes.Buffer
117         err := config.Execute(&manifest, inputs)
118         if err != nil {
119                 return "", err
120         }
121
122         vs := &netv1beta1.VirtualService{}
123         dec := k8Yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(manifest.String())), 1000)
124
125         if err := dec.Decode(&vs); err != nil {
126                 return "", err
127         }
128
129         result, err := vsClient.Create(context.TODO(), vs, metav1.CreateOptions{})
130
131         if err != nil {
132                 return "", err
133         }
134
135         fmt.Printf("Create Virtual Service %s \n", result.GetName())
136         return result.GetName(), nil
137 }
138
139 func createRequestAuthentication(clientset *versioned.Clientset) (string, error) {
140         raClient := clientset.SecurityV1beta1().RequestAuthentications(NAMESPACE)
141         config = template.Must(template.ParseFiles("./templates/RequestAuthentication-template.txt"))
142         var manifest bytes.Buffer
143         err := config.Execute(&manifest, inputs)
144         if err != nil {
145                 return "", err
146         }
147
148         ra := &secv1beta1.RequestAuthentication{}
149         dec := k8Yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(manifest.String())), 1000)
150
151         if err := dec.Decode(&ra); err != nil {
152                 return "", err
153         }
154
155         result, err := raClient.Create(context.TODO(), ra, metav1.CreateOptions{})
156
157         if err != nil {
158                 return "", err
159         }
160
161         fmt.Printf("Create Request Authentication %s \n", result.GetName())
162         return result.GetName(), nil
163 }
164
165 func createAuthorizationPolicy(clientset *versioned.Clientset) (string, error) {
166         apClient := clientset.SecurityV1beta1().AuthorizationPolicies(NAMESPACE)
167         config = template.Must(template.ParseFiles("./templates/AuthorizationPolicy-template.txt"))
168         var manifest bytes.Buffer
169         err := config.Execute(&manifest, inputs)
170         if err != nil {
171                 return "", err
172         }
173
174         ap := &secv1beta1.AuthorizationPolicy{}
175         dec := k8Yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(manifest.String())), 1000)
176
177         if err := dec.Decode(&ap); err != nil {
178                 return "", err
179         }
180
181         result, err := apClient.Create(context.TODO(), ap, metav1.CreateOptions{})
182
183         if err != nil {
184                 return "", err
185         }
186
187         fmt.Printf("Create Authorization Policy %s \n", result.GetName())
188         return result.GetName(), nil
189 }
190
191 func createEnvoyFilter(clientset *versioned.Clientset) (string, error) {
192         efClient := clientset.NetworkingV1alpha3().EnvoyFilters(NAMESPACE)
193         config = template.Must(template.ParseFiles("./templates/EnvoyFilter-template.txt"))
194         var manifest bytes.Buffer
195         err := config.Execute(&manifest, inputs)
196         if err != nil {
197                 return "", err
198         }
199
200         ef := &netv1alpha3.EnvoyFilter{}
201         dec := k8Yaml.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(manifest.String())), 1000)
202
203         if err = dec.Decode(&ef); err != nil {
204                 return "", err
205         }
206
207         result, err := efClient.Create(context.TODO(), ef, metav1.CreateOptions{})
208
209         if err != nil {
210                 return "", err
211         }
212
213         fmt.Printf("Create Envoy Filter %s \n", result.GetName())
214         return result.GetName(), nil
215 }
216
217 func removeGateway(clientset *versioned.Clientset) {
218         gtClient := clientset.NetworkingV1beta1().Gateways(NAMESPACE)
219         err := gtClient.Delete(context.TODO(), "nonrtric-istio-"+appName+"-gateway", metav1.DeleteOptions{})
220         if err != nil {
221                 fmt.Println(err)
222         } else {
223                 fmt.Println("Deleted Gateway nonrtric-istio-" + appName + "-gateway")
224         }
225 }
226
227 func removeVirtualService(clientset *versioned.Clientset) {
228         vsClient := clientset.NetworkingV1beta1().VirtualServices(NAMESPACE)
229         err := vsClient.Delete(context.TODO(), "nonrtric-istio-"+appName+"-vs", metav1.DeleteOptions{})
230         if err != nil {
231                 fmt.Println(err)
232         } else {
233                 fmt.Println("Deleted VirtualServices nonrtric-istio-" + appName + "-vs")
234         }
235 }
236
237 func removeRequestAuthentication(clientset *versioned.Clientset) {
238         raClient := clientset.SecurityV1beta1().RequestAuthentications(NAMESPACE)
239         err := raClient.Delete(context.TODO(), "jwt-"+appName, metav1.DeleteOptions{})
240         if err != nil {
241                 fmt.Println(err)
242         } else {
243                 fmt.Println("Deleted RequestAuthentication jwt-" + appName)
244         }
245 }
246
247 func removeAuthorizationPolicy(clientset *versioned.Clientset) {
248         apClient := clientset.SecurityV1beta1().AuthorizationPolicies(NAMESPACE)
249         err := apClient.Delete(context.TODO(), appName+"-policy", metav1.DeleteOptions{})
250         if err != nil {
251                 fmt.Println(err)
252         } else {
253                 fmt.Println("Deleted AuthorizationPolicy " + appName + "-policy")
254         }
255 }
256
257 func removeEnvoyFilter(clientset *versioned.Clientset) {
258         efClient := clientset.NetworkingV1alpha3().EnvoyFilters(NAMESPACE)
259         err := efClient.Delete(context.TODO(), appName+"-outbound-filter", metav1.DeleteOptions{})
260         if err != nil {
261                 fmt.Println(err)
262         } else {
263                 fmt.Println("Deleted EnvoyFilter " + appName + "-outbound-filter")
264         }
265 }
266
267 func createIstioPolicy(res http.ResponseWriter, req *http.Request) {
268         query := req.URL.Query()
269         realmName := query.Get("realm")
270         appName := query.Get("name")
271         roleName := query.Get("role")
272         methodName := query.Get("method")
273         inputs = TemplateConfig{Name: appName, Namespace: NAMESPACE, Realm: realmName, Role: roleName, Method: methodName }
274         var msg string
275         clientset := connectToK8s()
276         _, err := createGateway(clientset)
277         if err != nil {
278                 msg = err.Error()
279                 fmt.Println(err.Error())
280         } else {
281                 _, err := createVirtualService(clientset)
282                 if err != nil {
283                         msg = err.Error()
284                         fmt.Println(err.Error())
285                 } else {
286                         _, err := createRequestAuthentication(clientset)
287                         if err != nil {
288                                 msg = err.Error()
289                                 fmt.Println(err.Error())
290                         } else {
291                                 _, err := createAuthorizationPolicy(clientset)
292                                 if err != nil {
293                                         msg = err.Error()
294                                         fmt.Println(err.Error())
295                                 } else {
296                                         msg = "Istio rapp security setup successfully"
297                                 }
298                         }
299                 }
300         }
301
302         // create response binary data
303         data := []byte(msg) // slice of bytes
304         // write `data` to response
305         res.Write(data)
306 }
307
308 func createIstioFilter(res http.ResponseWriter, req *http.Request) {
309         query := req.URL.Query()
310         realmName := query.Get("realm")
311         clientId := query.Get("client")
312         appName := query.Get("name")
313         authType := query.Get("authType")
314         inputs = TemplateConfig{Name: appName, Namespace: NAMESPACE, Realm: realmName, Client: clientId, Authenticator: authType}
315         var msg string
316         clientset := connectToK8s()
317         _, err := createEnvoyFilter(clientset)
318         if err != nil {
319                 msg = err.Error()
320                 fmt.Println(err.Error())
321         }
322         // create response binary data
323         data := []byte(msg) // slice of bytes
324         // write `data` to response
325         res.Write(data)
326 }
327
328 func removeIstioPolicy(res http.ResponseWriter, req *http.Request) {
329         query := req.URL.Query()
330         appName = query.Get("name")
331         clientset := connectToK8s()
332         removeAuthorizationPolicy(clientset)
333         removeRequestAuthentication(clientset)
334         removeVirtualService(clientset)
335         removeGateway(clientset)
336 }
337
338 func removeIstioFilter(res http.ResponseWriter, req *http.Request) {
339         query := req.URL.Query()
340         appName = query.Get("name")
341         clientset := connectToK8s()
342         removeEnvoyFilter(clientset)
343 }
344
345 func main() {
346         createIstioPolicyHandler := http.HandlerFunc(createIstioPolicy)
347         http.Handle("/create-policy", createIstioPolicyHandler)
348         removeIstioPolicyHandler := http.HandlerFunc(removeIstioPolicy)
349         http.Handle("/remove-policy", removeIstioPolicyHandler)
350         createIstioFilterHandler := http.HandlerFunc(createIstioFilter)
351         http.Handle("/create-filter", createIstioFilterHandler)
352         removeIstioFilterHandler := http.HandlerFunc(removeIstioFilter)
353         http.Handle("/remove-filter", removeIstioFilterHandler)
354         http.ListenAndServe(":9000", nil)
355 }