Skip to content

Commit 64d5972

Browse files
committed
chore: refactor to oauth2 library again
1 parent 13dbcd0 commit 64d5972

File tree

2 files changed

+16
-102
lines changed

2 files changed

+16
-102
lines changed

README.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,15 @@ falcon:
5454

5555
# vmware workspace one
5656
ws1:
57+
# the api endpoint of your Workspace ONE instance, eg. "https://asXXXX.awmdm.com/api/"
5758
api_url: "https://xxx.awmdm.com/api/"
58-
api_key: "XXX"
59-
user: "XXX"
60-
password: "XXX"
59+
# your Workspace ONE oauth2 credentials
60+
# Groups & Settings > Configurations > Search for "oauth" > Click > Add with a Reader role
61+
client_id: "XXX"
62+
client_secret: "XXX"
63+
# the location of your Workspace ONE tenant, see 'Region-specific Token URLs'
64+
# https://docs.vmware.com/en/VMware-Workspace-ONE-UEM/services/UEM_ConsoleBasics/GUID-BF20C949-5065-4DCF-889D-1E0151016B5A.html
65+
auth_location: "emea"
6166
# what policies you want to skip
6267
# leave user or policy blank to ignore it
6368
skip:
@@ -135,6 +140,6 @@ templates:
135140
{{ end }}
136141
{{ end }}
137142
```
138-
4. Run `css -config=your-config.yml -log=debug -dry` to test.
139-
5. See the security overview popup to you in Slack!
140-
6. Now run it for real with `css -config=your-config.yml`.
143+
7. Run `css -config=your-config.yml -log=debug -dry` to test.
144+
8. See the security overview popup to you in Slack!
145+
9. Now run it for real with `css -config=your-config.yml`.

pkg/ws1/extractor.go

Lines changed: 5 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@ import (
88
"github.com/hazcod/crowdstrike-spotlight-slacker/config"
99
"github.com/pkg/errors"
1010
"github.com/sirupsen/logrus"
11+
"golang.org/x/oauth2/clientcredentials"
1112
"io"
1213
"net/http"
13-
"net/http/httputil"
14-
"net/url"
1514
"strconv"
1615
"strings"
1716
"time"
@@ -33,94 +32,6 @@ type UserDeviceFinding struct {
3332
ComplianceName string
3433
}
3534

36-
type LoggedRoundTripper struct {
37-
Proxied http.RoundTripper
38-
Logger *logrus.Logger
39-
}
40-
41-
func (t LoggedRoundTripper) RoundTrip(req *http.Request) (res *http.Response, e error) {
42-
resp, err := t.Proxied.RoundTrip(req)
43-
44-
if t.Logger != nil && t.Logger.IsLevelEnabled(logrus.TraceLevel) {
45-
dumped, err := httputil.DumpRequest(req, true)
46-
if err != nil {
47-
t.Logger.WithError(err).Error("could not dump http request")
48-
} else {
49-
t.Logger.Trace(string(dumped))
50-
}
51-
52-
if req.Response == nil {
53-
t.Logger.Trace("No response")
54-
} else {
55-
dumped, err = httputil.DumpResponse(req.Response, true)
56-
if err != nil {
57-
t.Logger.WithError(err).Error("could not dump http response")
58-
} else {
59-
t.Logger.Trace(string(dumped))
60-
}
61-
}
62-
}
63-
64-
return resp, err
65-
}
66-
67-
type authResponse struct {
68-
Token string `json:"access_token"`
69-
Expires int `json:"expires_in"`
70-
Type string `json:"token_type"`
71-
}
72-
73-
func renewAuth(_ context.Context, ws1AuthLocation, clientID, secret string) (token string, expiry time.Time, err error) {
74-
data := url.Values{
75-
"client_id": {clientID},
76-
"client_secret": {secret},
77-
"grant_type": {"client_credentials"},
78-
}
79-
80-
resp, err := http.PostForm(fmt.Sprintf("https://%s.uemauth.vmwservices.com/connect/token", ws1AuthLocation), data)
81-
if err != nil {
82-
return "", time.Time{}, errors.Wrap(err, "could not post to token endpoint")
83-
}
84-
85-
if resp.StatusCode > 399 {
86-
return "", time.Time{}, errors.Errorf("token endpoint returned status code: %d", resp.StatusCode)
87-
}
88-
89-
defer resp.Body.Close()
90-
91-
respB, err := io.ReadAll(resp.Body)
92-
if err != nil {
93-
return "", time.Time{}, errors.Wrap(err, "could not read token response")
94-
}
95-
96-
logrus.Debugf("%s", string(respB))
97-
98-
var response authResponse
99-
if err := json.Unmarshal(respB, &response); err != nil {
100-
return "", time.Time{}, errors.Wrap(err, "could not decode token response")
101-
}
102-
103-
if !strings.EqualFold(response.Type, "bearer") {
104-
return "", time.Time{}, errors.Wrap(err, "not a bearer token")
105-
}
106-
107-
if response.Expires <= 0 {
108-
return "", time.Time{}, errors.New("empty expires returned")
109-
}
110-
111-
if response.Token == "" {
112-
return "", time.Time{}, errors.New("no token returned")
113-
}
114-
115-
timeExpires := time.Now().Add(time.Second * time.Duration(response.Expires))
116-
117-
if timeExpires.Before(time.Now()) {
118-
return "", time.Time{}, errors.New("token retrieved is already expired")
119-
}
120-
121-
return response.Token, timeExpires, nil
122-
}
123-
12435
func doAuthRequest(ctx context.Context, ws1AuthLocation, clientID, secret, url, method string, payload interface{}) (respBytes []byte, err error) {
12536
var reqPayload []byte
12637
if payload != nil {
@@ -129,10 +40,10 @@ func doAuthRequest(ctx context.Context, ws1AuthLocation, clientID, secret, url,
12940
}
13041
}
13142

132-
token, _, err := renewAuth(ctx, ws1AuthLocation, clientID, secret)
133-
if err != nil {
134-
return nil, errors.Wrap(err, "could not renew auth")
135-
}
43+
oauth2Config := clientcredentials.Config{ClientID: clientID, ClientSecret: secret,
44+
TokenURL: fmt.Sprintf("https://%s.uemauth.vmwservices.com/connect/token", ws1AuthLocation)}
45+
httpClient := oauth2Config.Client(ctx)
46+
httpClient.Timeout = time.Second * 10
13647

13748
req, err := http.NewRequest(method, url, bytes.NewReader(reqPayload))
13849
req = req.WithContext(ctx)
@@ -141,9 +52,7 @@ func doAuthRequest(ctx context.Context, ws1AuthLocation, clientID, secret, url,
14152
}
14253

14354
req.Header.Set("Accept", "application/json")
144-
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
14555

146-
httpClient := http.Client{Timeout: time.Second * 10}
14756
resp, err := httpClient.Do(req)
14857
if err != nil {
14958
return nil, errors.Wrap(err, "http request failed")

0 commit comments

Comments
 (0)