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