blob: 1cad3ed19d62130c32ce8c7ebbf663726fee2b9a [file] [log] [blame]
ktimoney3570d5a2022-05-24 13:54:55 +01001// -
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
ktimoney8ead72a2022-04-12 15:10:10 +010021package main
22
23import (
24 "bytes"
25 "context"
26 "crypto/tls"
27 "crypto/x509"
28 "encoding/json"
29 "flag"
30 "fmt"
31 "io/ioutil"
32 "net"
33 "net/http"
34 "net/url"
35 "strings"
36 "time"
37)
38
39type Jwttoken struct {
40 Access_token string
41 Expires_in int
42 Refresh_expires_in int
43 Refresh_token string
44 Token_type string
45 Not_before_policy int
46 Session_state string
47 Scope string
48}
49
50var gatewayHost string
51var gatewayPort string
52var keycloakHost string
53var keycloakPort string
54var keycloakAlias string
55var securityEnabled string
56var useGateway string
57var role string
58var rapp string
59var methods string
60var realmName string
61var clientId string
62var healthy bool = true
63var ttime time.Time
64var jwt Jwttoken
65
66const (
67 namespace = "istio-nonrtric"
68 scope = "openid profile"
69)
70
71func getToken() string {
72 if ttime.Before(time.Now()) {
73 client := getClient()
74 keycloakUrl := "https://" + keycloakAlias + ":" + keycloakPort + "/auth/realms/" + realmName + "/protocol/openid-connect/token"
75 resp, err := client.PostForm(keycloakUrl, url.Values{"username": {""}, "password": {""}, "grant_type": {"password"}, "client_id": {clientId}, "scope": {scope}})
76 if err != nil {
77 fmt.Println(err)
78 panic("Something wrong with the credentials or url ")
79 }
80 defer resp.Body.Close()
81 body, err := ioutil.ReadAll(resp.Body)
82 json.Unmarshal([]byte(body), &jwt)
83 ttime = time.Now()
84 ttime = ttime.Add(time.Second * time.Duration(jwt.Expires_in))
85 }
86 return jwt.Access_token
87}
88
89func getClient() *http.Client {
90 caCert, _ := ioutil.ReadFile("/certs/rootCA.crt")
91 caCertPool := x509.NewCertPool()
92 caCertPool.AppendCertsFromPEM(caCert)
93
94 cert, _ := tls.LoadX509KeyPair("/certs/client.crt", "/certs/client.key")
95
96 dialer := &net.Dialer{
97 Timeout: 30 * time.Second,
98 KeepAlive: 30 * time.Second,
99 DualStack: true,
100 }
101
102 client := &http.Client{
103 Transport: &http.Transport{
104 DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
105 fmt.Println("address original =", addr)
106 if addr == keycloakAlias+":"+keycloakPort {
107 addr = keycloakHost + ":" + keycloakPort
108 fmt.Println("address modified =", addr)
109 }
110 return dialer.DialContext(ctx, network, addr)
111 },
112 TLSClientConfig: &tls.Config{
113 RootCAs: caCertPool,
114 Certificates: []tls.Certificate{cert},
115 },
116 },
117 }
118 return client
119}
120
121func MakeRequest(client *http.Client, prefix string, method string, ch chan string) {
122 var service = strings.Split(prefix, "/")[1]
123 var gatewayUrl = "http://" + gatewayHost + ":" + gatewayPort
124 var token = ""
125 var jsonValue []byte = []byte{}
126 var restUrl string = ""
127
128 if securityEnabled == "true" {
129 token = getToken()
130 } else {
131 useGateway = "N"
132 }
133
134 if strings.ToUpper(useGateway) != "Y" {
135 gatewayUrl = "http://" + service + "." + namespace + ":80"
136 prefix = ""
137 }
138
139 restUrl = gatewayUrl + prefix
140
141 req, err := http.NewRequest(method, restUrl, bytes.NewBuffer(jsonValue))
142 if err != nil {
143 fmt.Printf("Got error %s", err.Error())
144 }
145 req.Header.Set("Content-type", "application/json")
146 req.Header.Set("Authorization", "Bearer "+token)
147
148 resp, err := client.Do(req)
149 if err != nil {
150 fmt.Printf("Got error %s", err.Error())
151 }
152 defer resp.Body.Close()
153 body, _ := ioutil.ReadAll(resp.Body)
154
155 respString := string(body[:])
156 if respString == "RBAC: access denied" {
157 respString += " for " + service + " " + strings.ToLower(method) + " request"
158 }
159 fmt.Printf("Received response for %s %s request - %s\n", service, strings.ToLower(method), respString)
160 ch <- prefix + "," + method
161}
162
163func health(res http.ResponseWriter, req *http.Request) {
164 if healthy {
165 res.WriteHeader(http.StatusOK)
166 res.Write([]byte("healthy"))
167 } else {
168 res.WriteHeader(http.StatusInternalServerError)
169 res.Write([]byte("unhealthy"))
170 }
171}
172
173func main() {
174 ttime = time.Now()
175 time.Sleep(1 * time.Second)
176 flag.StringVar(&gatewayHost, "gatewayHost", "istio-ingressgateway.istio-system", "Gateway Host")
177 flag.StringVar(&gatewayPort, "gatewayPort", "80", "Gateway Port")
178 flag.StringVar(&keycloakHost, "keycloakHost", "istio-ingressgateway.istio-system", "Keycloak Host")
179 flag.StringVar(&keycloakPort, "keycloakPort", "443", "Keycloak Port")
180 flag.StringVar(&keycloakAlias, "keycloakAlias", "keycloak.est.tech", "Keycloak URL Alias")
181 flag.StringVar(&useGateway, "useGateway", "Y", "Connect to services through API gateway")
182 flag.StringVar(&securityEnabled, "securityEnabled", "true", "Security is required to use this application")
183 flag.StringVar(&realmName, "realm", "x509", "Keycloak realm")
184 flag.StringVar(&clientId, "client", "x509provider-cli", "Keycloak client")
185 flag.StringVar(&role, "role", "provider-viewer", "Role granted to application")
186 flag.StringVar(&rapp, "rapp", "rapp-x509-provider", "Name of rapp to invoke")
187 flag.StringVar(&methods, "methods", "GET", "Methods to access application")
188 flag.Parse()
189
190 healthHandler := http.HandlerFunc(health)
191 http.Handle("/health", healthHandler)
192 go func() {
193 http.ListenAndServe(":9000", nil)
194 }()
195
196 client := &http.Client{
197 Timeout: time.Second * 10,
198 }
199
200 ch := make(chan string)
201 var prefixArray []string = []string{"/" + rapp}
202 var methodArray []string = []string{methods}
203 for _, prefix := range prefixArray {
204 for _, method := range methodArray {
205 go MakeRequest(client, prefix, method, ch)
206 }
207 }
208
209 ioutil.WriteFile("init.txt", []byte("Initialization done."), 0644)
210
211 for r := range ch {
212 go func(resp string) {
213 time.Sleep(10 * time.Second)
214 elements := strings.Split(resp, ",")
215 prefix := elements[0]
216 method := elements[1]
217 MakeRequest(client, prefix, method, ch)
218 }(r)
219 }
220
221}