Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit 15849ab

Browse files
authored
Merge pull request #34 from philips-software/feature/stl
Secure Transport Layer support
2 parents ef26c91 + 358e5e2 commit 15849ab

25 files changed

+1727
-93
lines changed

CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file.
33

44
The format is based on [Keep a Changelog](http://keepachangelog.com/)
55
and this project adheres to [Semantic Versioning](http://semver.org/).
6+
## v0.35.0
7+
- NEW: Secure Transport Layer (STL) support
8+
9+
## v0.34.4
10+
- Fix some PKI methods
11+
- Add IAM token revoke calls
12+
13+
614
## v0.34.3
715
- Remove elastic due to license change
816

README.md

+8-4
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@ A HSDP API client enabling Go programs to interact with various HSDP APIs in a s
1212
The current implement covers only a subset of HSDP APIs. Basically we implement functionality as needed.
1313

1414
- [x] Cartel c.q. Container Host management ([examples](cartel/README.md))
15-
- [x] IronIO tasks, codes and schedules management ([examples](iron/README.md))
16-
- [x] PKI services
15+
- [x] Secure Transport Layer (STL) / Edge
16+
- [x] Device queries
17+
- [x] Application Resources management
18+
- [x] Device configuration management (firewall, logging)
19+
- [x] Public Key Infrastructe (PKI) management
1720
- [x] IAM/IDM management
1821
- [x] Groups
1922
- [x] Organizations
@@ -38,14 +41,15 @@ The current implement covers only a subset of HSDP APIs. Basically we implement
3841
- [x] Telemetry Data Repository (TDR)
3942
- [x] Contract management
4043
- [x] Data Item management
41-
- [x] S3 Credentials Policy management
44+
- [x] S3Creds Policy management
4245
- [x] DICOM Store
4346
- [x] Config management
4447
- [x] Hosted Application Streaming (HAS) management
45-
- [x] Configuration
48+
- [x] Service Discovery
4649
- [x] Console settings
4750
- [ ] Metrics Alerts
4851
- [x] Metrics Autoscalers
52+
- [x] IronIO tasks, codes and schedules management ([examples](iron/README.md))
4953

5054
## Usage
5155

config/hsdp.json

+19
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@
4141
}
4242
}
4343
},
44+
"dev": {
45+
"service": {
46+
"stl": {
47+
"url": "https://console.na3.hsdp.io/api/stl/user/v1/graphql"
48+
},
49+
"uaa": {
50+
"url": "https://uaa.cloud.phsdp.com"
51+
}
52+
}
53+
},
4454
"eu-west": {
4555
"env": {
4656
"client-test": {
@@ -110,6 +120,9 @@
110120
"domain": "emea1.phsdp.com",
111121
"host": "gw-eu1.phsdp.com"
112122
},
123+
"stl": {
124+
"url": "https://console.eu1.hsdp.io/api/stl/user/v1/graphql"
125+
},
113126
"uaa": {
114127
"url": "https://uaa.eu1.phsdp.com"
115128
}
@@ -195,6 +208,9 @@
195208
"logging": {
196209
"url": "https://logingestor2-client-test.us-east.philips-healthsuite.com"
197210
},
211+
"pki": {
212+
"url": "https://pki-client-test.us-east.philips-healthsuite.com"
213+
},
198214
"s3creds": {
199215
"url": "https://s3creds-client-test.us-east.philips-healthsuite.com"
200216
}
@@ -259,6 +275,9 @@
259275
"domain": "na1.phsdp.com",
260276
"host": "gw-na1.phsdp.com"
261277
},
278+
"stl": {
279+
"url": "https://console.na1.hsdp.io/api/stl/user/v1/graphql"
280+
},
262281
"uaa": {
263282
"url": "https://uaa.cloud.pcftest.com"
264283
}

config/hsdp.toml

+13-1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ url = "https://console.sa1.hsdp.io"
9292
[region.apac3.service.console]
9393
url = "https://console.ap3.hsdp.io"
9494

95+
# Service STL
96+
[region.dev.service.stl]
97+
url = "https://console.na3.hsdp.io/api/stl/user/v1/graphql"
98+
[region.us-east.service.stl]
99+
url = "https://console.na1.hsdp.io/api/stl/user/v1/graphql"
100+
[region.eu-west.service.stl]
101+
url = "https://console.eu1.hsdp.io/api/stl/user/v1/graphql"
102+
95103
# Service UAA
96104
[region.us-east.service.uaa]
97105
url = "https://uaa.cloud.pcftest.com"
@@ -101,6 +109,8 @@ url = "https://uaa.eu1.phsdp.com"
101109
url = "https://uaa.sys.sa1.hsdp.io"
102110
[region.apac3.service.uaa]
103111
url = "https://uaa.sys.ap3.hsdp.io"
112+
[region.dev.service.uaa]
113+
url = "https://uaa.cloud.phsdp.com"
104114

105115
# Service IAM
106116
[region.us-east.env.client-test.service.iam]
@@ -229,4 +239,6 @@ url = "https://kibana.ap3.hsdp.io"
229239

230240
# Service PKI
231241
[region.eu-west.env.client-test.service.pki]
232-
url = "https://pki-proxy-client-test.eu-west.philips-healthsuite.com"
242+
url = "https://pki-proxy-client-test.eu-west.philips-healthsuite.com"
243+
[region.us-east.env.client-test.service.pki]
244+
url = "https://pki-client-test.us-east.philips-healthsuite.com"

console/client.go

+25-52
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@ package console
33

44
import (
55
"bytes"
6-
"context"
76
"encoding/json"
87
"fmt"
98
"github.com/philips-software/go-hsdp-api/internal"
9+
"golang.org/x/oauth2"
1010
"io"
1111
"io/ioutil"
1212
"net/http"
13-
"net/http/httputil"
1413
"net/url"
1514
"os"
1615
"strings"
@@ -19,7 +18,6 @@ import (
1918

2019
validator "github.com/go-playground/validator/v10"
2120
"github.com/google/go-querystring/query"
22-
"github.com/google/uuid"
2321
autoconf "github.com/philips-software/go-hsdp-api/config"
2422
)
2523

@@ -128,7 +126,8 @@ type Client struct {
128126

129127
Metrics *MetricsService
130128

131-
debugFile *os.File
129+
debugFile *os.File
130+
consoleErr error
132131

133132
sync.Mutex
134133
}
@@ -154,25 +153,24 @@ func newClient(httpClient *http.Client, config *Config) (*Client, error) {
154153
if config.UAAURL == "" {
155154
return nil, ErrUAAURLCannotBeEmpty
156155
}
157-
if config.BaseConsoleURL == "" {
158-
return nil, ErrConsoleURLCannotBeEmpty
159-
}
160156
c := &Client{client: httpClient, config: config, UserAgent: userAgent}
161157
if err := c.SetBaseUAAURL(c.config.UAAURL); err != nil {
162158
return nil, err
163159
}
164160
if err := c.SetBaseConsoleURL(c.config.BaseConsoleURL); err != nil {
165-
return nil, err
161+
c.consoleErr = err
166162
}
167-
168163
if config.DebugLog != "" {
169-
debugFile, err := os.OpenFile(config.DebugLog, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
170-
if err != nil {
171-
c.debugFile = nil
172-
} else {
173-
c.debugFile = debugFile
164+
var err error
165+
c.debugFile, err = os.OpenFile(config.DebugLog, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600)
166+
if err == nil {
167+
httpClient.Transport = internal.NewLoggingRoundTripper(httpClient.Transport, c.debugFile)
174168
}
175169
}
170+
header := make(http.Header)
171+
header.Set("User-Agent", userAgent)
172+
httpClient.Transport = internal.NewHeaderRoundTripper(httpClient.Transport, header)
173+
176174
c.Metrics = &MetricsService{client: c}
177175
c.validate = validator.New()
178176
return c, nil
@@ -208,8 +206,8 @@ func (c *Client) HttpClient() *http.Client {
208206
return c.client
209207
}
210208

211-
// Token returns the current token
212-
func (c *Client) Token() string {
209+
// Token returns the current token. It also confirms to TokenSource
210+
func (c *Client) Token() (*oauth2.Token, error) {
213211
c.Lock()
214212
defer c.Unlock()
215213

@@ -218,10 +216,14 @@ func (c *Client) Token() string {
218216

219217
if expires-now < 60 {
220218
if c.TokenRefresh() != nil {
221-
return ""
219+
return nil, fmt.Errorf("failed to refresh console token")
222220
}
223221
}
224-
return c.token
222+
return &oauth2.Token{
223+
AccessToken: c.token,
224+
RefreshToken: c.refreshToken,
225+
Expiry: c.expiresAt,
226+
}, nil
225227
}
226228

227229
// TokenRefresh refreshes the accessToken
@@ -320,6 +322,9 @@ func (c *Client) newRequest(endpoint, method, path string, opt interface{}, opti
320322
u = *c.baseUAAURL
321323
u.Opaque = c.baseUAAURL.Path + path
322324
case CONSOLE:
325+
if c.consoleErr != nil {
326+
return nil, c.consoleErr
327+
}
323328
u = *c.baseConsoleURL
324329
u.Opaque = c.baseConsoleURL.Path + path
325330
default:
@@ -371,14 +376,10 @@ func (c *Client) newRequest(endpoint, method, path string, opt interface{}, opti
371376

372377
switch c.tokenType {
373378
case oAuthToken:
374-
if token := c.Token(); token != "" {
375-
req.Header.Set("Authorization", "Bearer "+c.token)
379+
if token, err := c.Token(); err == nil {
380+
req.Header.Set("Authorization", "Bearer "+token.AccessToken)
376381
}
377382
}
378-
379-
if c.UserAgent != "" {
380-
req.Header.Set("User-Agent", c.UserAgent)
381-
}
382383
return req, nil
383384
}
384385

@@ -401,27 +402,7 @@ func newResponse(r *http.Response) *Response {
401402
// interface, the raw response body will be written to v, without attempting to
402403
// first decode it.
403404
func (c *Client) do(req *http.Request, v interface{}) (*Response, error) {
404-
id := uuid.New()
405-
406-
if c.debugFile != nil {
407-
dumped, _ := httputil.DumpRequest(req, true)
408-
out := fmt.Sprintf("[go-hsdp-api] --- Request [%s] start ---\n%s\n[go-hsdp-api] --- Request [%s] end ---\n", id, string(dumped), id)
409-
if c.debugFile != nil {
410-
_, _ = c.debugFile.WriteString(out)
411-
} else {
412-
fmt.Println(out)
413-
}
414-
}
415405
resp, err := c.client.Do(req)
416-
if c.debugFile != nil && resp != nil {
417-
dumped, _ := httputil.DumpResponse(resp, true)
418-
out := fmt.Sprintf("[go-hsdp-api] --- Response [%s] start ---\n%s\n[go-hsdp-api] --- Response [%s] end ---\n", id, string(dumped), id)
419-
if c.debugFile != nil {
420-
_, _ = c.debugFile.WriteString(out)
421-
} else {
422-
fmt.Println(out)
423-
}
424-
}
425406
if err != nil {
426407
return nil, err
427408
}
@@ -443,14 +424,6 @@ func (c *Client) do(req *http.Request, v interface{}) (*Response, error) {
443424
return response, err
444425
}
445426

446-
// WithContext runs the request with the provided context
447-
func WithContext(ctx context.Context) OptionFunc {
448-
return func(req *http.Request) error {
449-
*req = *req.WithContext(ctx)
450-
return nil
451-
}
452-
}
453-
454427
// CheckResponse checks the API response for errors, and returns them if present.
455428
func checkResponse(r *http.Response) error {
456429
switch r.StatusCode {

console/client_test.go

+18-4
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,11 @@ func TestLogin(t *testing.T) {
8989
if err != nil {
9090
t.Fatal(err)
9191
}
92-
assert.Equal(t, token, client.Token())
92+
tk, err := client.Token()
93+
if !assert.Nil(t, err) {
94+
return
95+
}
96+
assert.Equal(t, token, tk.AccessToken)
9397
assert.Equal(t, refreshToken, client.RefreshToken())
9498
}
9599

@@ -109,7 +113,11 @@ func TestWithLogin(t *testing.T) {
109113
if !assert.NotNil(t, c) {
110114
return
111115
}
112-
assert.Equal(t, token, c.Token())
116+
tk, err := c.Token()
117+
if !assert.Nil(t, err) {
118+
return
119+
}
120+
assert.Equal(t, token, tk.AccessToken)
113121
assert.Equal(t, refreshToken, c.RefreshToken())
114122
}
115123

@@ -136,7 +144,9 @@ func TestDebug(t *testing.T) {
136144
t.Fatalf("Error: %v", err)
137145
}
138146
defer client.Close()
139-
defer os.Remove(tmpfile.Name()) // clean up
147+
defer func() {
148+
_ = os.Remove(tmpfile.Name())
149+
}() // clean up
140150

141151
err = client.Login("username", "password")
142152
assert.Nil(t, err)
@@ -226,7 +236,11 @@ func TestTokenRefresh(t *testing.T) {
226236

227237
err = client.TokenRefresh()
228238
assert.Nilf(t, err, fmt.Sprintf("Unexpected error: %v", err))
229-
assert.Equal(t, newToken, client.Token())
239+
tk, err := client.Token()
240+
if !assert.Nil(t, err) {
241+
return
242+
}
243+
assert.Equal(t, newToken, tk.AccessToken)
230244
assert.Equal(t, newRefreshToken, client.RefreshToken())
231245
httpClient := client.HttpClient()
232246
assert.NotNil(t, httpClient)

console/login_test.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ func TestSetToken(t *testing.T) {
2020
}
2121
token := "MyToken"
2222
token2 := "TokenMy"
23-
assert.Equal(t, token, client.SetToken(token).Token())
23+
tk, err := client.SetToken(token).Token()
24+
if !assert.Nil(t, err) {
25+
return
26+
}
27+
assert.Equal(t, token, tk.AccessToken)
2428
client.SetTokens(token, token2, token, time.Now().Add(10*time.Minute).Unix())
2529
assert.Equal(t, token2, client.RefreshToken())
2630
}

go.mod

+5-1
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,14 @@ require (
88
github.com/go-playground/validator/v10 v10.4.1
99
github.com/google/fhir/go v0.0.0-20201203001644-a2580b6ea022
1010
github.com/google/go-querystring v1.0.0
11-
github.com/google/uuid v1.1.1
11+
github.com/google/uuid v1.2.0
12+
github.com/hasura/go-graphql-client v0.2.0 // indirect
13+
github.com/klauspost/compress v1.11.7 // indirect
1214
github.com/philips-software/go-hsdp-signer v1.3.0
1315
github.com/stretchr/testify v1.5.1
1416
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9 // indirect
17+
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect
18+
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
1519
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 // indirect
1620
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
1721
gopkg.in/yaml.v2 v2.3.0 // indirect

0 commit comments

Comments
 (0)