forked from things-go/go-socks5
-
Notifications
You must be signed in to change notification settings - Fork 0
/
akeyless.go
129 lines (112 loc) · 2.98 KB
/
akeyless.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
125
126
127
128
package socks5
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"log"
"strings"
"time"
)
var client = &http.Client{
Timeout: 10 * time.Second,
}
var allowedAccessIds []string
func init() {
allowedAccessIds = strings.Split(os.Getenv("ALLOWED_ACCESS_IDS"), ",")
}
type CurlOutput struct {
AuthCreds string `json:"auth_creds"`
UamCreds string `json:"uam_creds"`
KfmCreds string `json:"kfm_creds"`
Token string `json:"token"`
}
func ValidateToken(token string) (bool, error) {
debug := os.Getenv("DEBUG")
if debug == "true" {
log.Printf("GW URL:[%s], AUTH URL:[%s]\n", os.Getenv("AKEYLESS_GW_URL"), os.Getenv("AKEYLESS_AUTH_URL"))
}
resp, err := sendReq(os.Getenv("AKEYLESS_AUTH_URL")+"/get-tmp-creds", token)
if resp == "" {
if debug == "true" {
log.Printf("Err:[%s]\n", "empty response")
}
return false, err
}
curlRes := CurlOutput{}
err = json.Unmarshal([]byte(resp), &curlRes)
if err != nil {
if debug == "true" {
log.Printf("Err: json unmarshal [%s]\n", err.Error())
}
return false, err
}
claims, err := ParseUnvalidatedClaimsFromJWT(curlRes.UamCreds)
if err != nil {
if debug == "true" {
log.Printf("Err: ParseUnvalidatedClaimsFromJWT [%s]\n", err.Error())
}
return false, err
}
if claims.AccessId == "" {
if debug == "true" {
log.Printf("Err: empty [%s]\n", "claims.AccessId")
}
return false, err
}
for _, id := range allowedAccessIds {
if id == claims.AccessId {
log.Printf("Valid AccessId:[%s]\n", claims.AccessId)
return true, nil
}
}
return false, nil
}
func authWithAkeyless(token string) error {
if !strings.HasPrefix(token, "t-") && !strings.HasPrefix(token, "u-") {
return fmt.Errorf("Invalid token")
}
if ok, err := ValidateToken(token); !ok || err != nil {
return fmt.Errorf("Invalid token Error: %v", err)
}
return nil
}
func sendReq(url, headerStr string) (string, error) {
req, err := http.NewRequest("GET", url, nil)
req.Header.Set("akeylessaccesstoken", headerStr)
req.Close = true
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
resbody, err := ioutil.ReadAll(resp.Body)
return string(resbody), err
}
type Claims struct {
AccessId string `json:"access_id"`
SigningKeyId string `json:"signing_key_id"`
Nonce string `json:"nonce"`
Type string `json:"typ"`
SubjectParams string `json:"sub_params"`
Attaches string `json:"attaches"`
}
func ParseUnvalidatedClaimsFromJWT(creds string) (*Claims, error) {
parts := strings.Split(creds, ".")
if len(parts) != 3 {
return nil, fmt.Errorf("token contains an invalid number of segments")
}
claimBytes, err := base64.RawURLEncoding.DecodeString(parts[1])
if err != nil {
return nil, fmt.Errorf("failed to decode segment. %v", err.Error())
}
dec := json.NewDecoder(bytes.NewBuffer(claimBytes))
var claims Claims
if err = dec.Decode(&claims); err != nil {
return nil, fmt.Errorf("failed to parse JWT. %v", err.Error())
}
return &claims, nil
}