/
oidc_client.go
124 lines (107 loc) · 3.4 KB
/
oidc_client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// TODO(2.13): Package utils is deprecated and only used for upgrade tests
// from pre 2.13 releases. Once 2.13 is released, remove this file.
package utils
import (
"bytes"
"fmt"
"io/ioutil"
"mime/multipart"
"net/http"
"net/url"
"os"
"regexp"
"strings"
)
func GetOIDCClient() (string, string) {
user := os.Getenv("KUBERMATIC_OIDC_USER")
password := os.Getenv("KUBERMATIC_OIDC_PASSWORD")
if len(user) > 0 && len(password) > 0 {
return user, password
}
return "roxy@loodse.com", "password"
}
func GetOIDCReqToken(hClient *http.Client, u url.URL, issuerURLPrefix, redirectURI string) (string, error) {
u.Path = "auth"
if len(issuerURLPrefix) > 0 {
u.Path = fmt.Sprintf("%s/auth", issuerURLPrefix)
}
qp := u.Query()
qp.Set("client_id", "kubermatic")
qp.Set("redirect_uri", redirectURI)
qp.Set("response_type", "code")
qp.Set("scope", "openid profile email")
qp.Set("state", "I wish to wash my irish wristwatch")
u.RawQuery = qp.Encode()
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
return "", err
}
rsp, err := hClient.Do(req)
if err != nil {
return "", err
}
defer rsp.Body.Close()
bodyBytes, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return "", err
}
body := string(bodyBytes)
tokenPrefix := `href=\"\/(dex\/)?auth\/local\?req=(\w)*"`
tokenCompiledRegExp := regexp.MustCompile(tokenPrefix)
potentialTokenLines := tokenCompiledRegExp.FindAllString(body, -1)
if len(potentialTokenLines) < 1 {
return "", fmt.Errorf("the response doesn't contain the expected text, the regular expression that was used=%q, unable to get a token from ODIC provider, full body=\n\n%q", tokenPrefix, body)
}
tokens := strings.Split(potentialTokenLines[0], "req=")
if len(tokens) < 1 {
return "", fmt.Errorf("unable to find a token, tried to split the text=%q by %q", potentialTokenLines[0], "req=")
}
token := tokens[1]
return strings.TrimSuffix(token, "\""), nil
}
func GetOIDCAuthToken(hClient *http.Client, reqToken string, u url.URL, issuerURLPrefix, login, password string) (string, error) {
u.Path = "auth/local"
if len(issuerURLPrefix) > 0 {
u.Path = fmt.Sprintf("%s/auth/local", issuerURLPrefix)
}
qp := u.Query()
qp.Set("req", reqToken)
u.RawQuery = qp.Encode()
buf := new(bytes.Buffer)
writer := multipart.NewWriter(buf)
if err := writer.WriteField("login", login); err != nil {
return "", err
}
if err := writer.WriteField("password", password); err != nil {
return "", err
}
err := writer.Close()
if err != nil {
return "", err
}
req, err := http.NewRequest("POST", u.String(), bytes.NewReader(buf.Bytes()))
if err != nil {
return "", err
}
req.Header.Set("Content-Type", writer.FormDataContentType())
rsp, err := hClient.Do(req)
if err != nil {
return "", err
}
defer rsp.Body.Close()
bodyBytes, err := ioutil.ReadAll(rsp.Body)
if err != nil {
return "", err
}
tokenPrefix := `(\<code\>)(\s*.*\s*)(\<\/code\>)`
tokenCompiledRegExp := regexp.MustCompile(tokenPrefix)
body := string(bodyBytes)
potentialTokenLines := tokenCompiledRegExp.FindAllString(body, -1)
if len(potentialTokenLines) < 1 {
return "", fmt.Errorf("the response doesn't contain the expected an OIDC token, the regular expression that was used=%q, unable to get a token from ODIC provider, full body=\n\n%q", tokenPrefix, body)
}
token := potentialTokenLines[0]
token = strings.TrimPrefix(token, "<code>")
token = strings.TrimSuffix(token, "</code>")
return token, nil
}