-
Notifications
You must be signed in to change notification settings - Fork 2
/
sc-token.go
129 lines (113 loc) · 3.67 KB
/
sc-token.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
129
package go_tenable
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"log"
)
// With the provided user name and password, attempts to create an authenticated session with Tenable.sc using the
// token endpoint. The function needs to be executed prior to any other SC client request as it sets the token and
// session cookie for requests.
func (sc *TenableSC) Login(scUser string, scPassword string) (*TokenResponse, error) {
// Read in the SC username and password
payload := TokenRequest{
scUser,
scPassword,
}
// Make POST request to token endpoint
resp, err := sc.Post("token", payload.ToBytes())
if err != nil {
log.Printf("Unable to request a new token: %v\n", err)
return nil, err
}
// Unmarshal response
tmp, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Printf("Unable to read login response body: %v\n", err)
return nil, err
}
// Check to see if a cookie was returned with the token
var cookieFound string
for _, cookie := range resp.Cookies() {
if cookie.Name == "TNS_SESSIONID" {
cookieFound = cookie.Value
}
}
// If no cookie was found then return error
if cookieFound == "" {
var errorResp = "Unable to find \"TNS_SESSIONID\" cookie in login response\n"
log.Print(errorResp)
return nil, errors.New(errorResp)
}
// Attempt to unmarshal to a successful response
var tokenResponse = TokenResponse{}
err = json.Unmarshal(tmp, &tokenResponse)
if err != nil {
// If the response is unsuccessful attempts to unmarshal to an error response
tokenErrorResponse := TokenError{}
err = json.Unmarshal(tmp, &tokenErrorResponse)
if err != nil {
// if unable to unmarshal successful or error then the request and response are FUBAR
log.Printf("Unable to unmarshal error response either. %v", err)
return nil, err
}
return nil, errors.New(fmt.Sprintf("%v", tokenErrorResponse.ErrorMsg))
}
// At this point we should have a valid token and session cookie
sc.token = tokenResponse.Response.Token
sc.session = cookieFound
// Set the cookie session and token header on the client object
sc.BaseClient.Headers.Add("X-SecurityCenter", fmt.Sprintf("%v", sc.token))
sc.BaseClient.Headers.Add("Cookie", fmt.Sprintf("TNS_SESSIONID=%v", sc.session))
return &tokenResponse, nil
}
func (sc *TenableSC) Logout() error {
_, err := sc.Delete("token", "")
if err != nil {
log.Printf("Unable to log out of Tenable.SC: %v\n", err)
return err
}
return nil
}
type TokenRequest struct {
Username string `json:"username"`
Password string `json:"password"`
}
type TokenResponse struct {
Type string `json:"type"`
Response struct {
LastLogin string `json:"lastLogin"`
LastLoginIP string `json:"lastLoginIP"`
FailedLogins string `json:"failedLogins"`
FailedLoginIP string `json:"failedLoginIP"`
LastFailedLogin string `json:"lastFailedLogin"`
Token int `json:"token"`
UnassociatedCert string `json:"unassociatedCert"`
} `json:"response"`
ErrorCode int `json:"error_code"`
ErrorMsg string `json:"error_msg"`
Warnings []interface{} `json:"warnings"`
Timestamp int `json:"timestamp"`
}
type TokenError struct {
Type string `json:"type"`
Response []interface{} `json:"response"`
ErrorCode int `json:"error_code"`
ErrorMsg string `json:"error_msg"`
Warnings []interface{} `json:"warnings"`
Timestamp int `json:"timestamp"`
}
type TokenCookie struct {
HTTPOnly bool `json:"httpOnly"`
Path string `json:"path"`
Secure bool `json:"secure"`
Value string `json:"value"`
}
func (req TokenRequest) ToBytes() []byte {
ret, err := json.Marshal(req)
if err != nil {
log.Printf("Unable to marshal token request body")
}
return ret
}