Skip to content

Commit e6f83c3

Browse files
Merge pull request #16 from speakeasy-api/feature/spe-348-masking
feat: add masking for captured data
2 parents 6d0c02b + bf7eace commit e6f83c3

File tree

41 files changed

+1467
-379
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1467
-379
lines changed

.golangci.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ issues:
4242
- nosnakecase
4343
- maintidx
4444
- gosec
45+
- gocyclo
4546
- path: _exports_test\.go
4647
linters:
4748
- testpackage

README.md

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ func main() {
4040
// Configure the Global SDK
4141
speakeasy.Configure(speakeasy.Config {
4242
APIKey: "YOUR API KEY HERE", // retrieve from Speakeasy API dashboard.
43-
ApiID: "YOUR API ID HERE", // custom Api ID to associate captured requests with.
44-
VersionID: "YOUR VERSION ID HERE", // custom Version ID to associate captured requests with.
43+
ApiID: "YOUR API ID HERE", // this is an ID you provide that you would like to associate captured requests with.
44+
VersionID: "YOUR VERSION ID HERE", // this is a Version you provide that you would like to associate captured requests with.
4545
})
4646

4747
// Associate the SDK's middleware with your router
@@ -63,16 +63,28 @@ The Speakeasy SDK provides both a global and per Api configuration option. If yo
6363
import "github.com/speakeasy-api/speakeasy-go-sdk"
6464

6565
func main() {
66-
// Configure a new instance of the SDK
67-
sdkInstance := speakeasy.New(speakeasy.Config {
66+
r := mux.NewRouter()
67+
68+
// Configure a new instance of the SDK for the store API
69+
storeSDKInstance := speakeasy.New(speakeasy.Config {
6870
APIKey: "YOUR API KEY HERE", // retrieve from Speakeasy API dashboard.
69-
ApiID: "YOUR API ID HERE", // custom Api ID to associate captured requests with.
70-
VersionID: "YOUR VERSION ID HERE", // custom Version ID to associate captured requests with.
71+
ApiID: "store_api", // this is an ID you provide that you would like to associate captured requests with.
72+
VersionID: "1.0.0", // this is a Version you provide that you would like to associate captured requests with.
7173
})
7274

73-
// Associate the SDK's middleware with your router
74-
r := mux.NewRouter()
75-
r.Use(sdkInstance.Middleware)
75+
// Configure a new instance of the SDK for the product API
76+
productSDKInstance := speakeasy.New(speakeasy.Config {
77+
APIKey: "YOUR API KEY HERE", // retrieve from Speakeasy API dashboard.
78+
ApiID: "product_api", // this is an ID you provide that you would like to associate captured requests with.
79+
VersionID: "1.0.0", // this is a Version you provide that you would like to associate captured requests with.
80+
})
81+
82+
// The different instances of the SDK (with differnt IDs or even versions assigned) can be used to associate requests with different APIs and Versions.
83+
s := r.PathPrefix("/store").Subrouter()
84+
r.Use(storeSDKInstance.Middleware)
85+
86+
s := r.PathPrefix("/products").Subrouter()
87+
r.Use(productSDKInstance.Middleware)
7688
}
7789
```
7890

@@ -131,4 +143,53 @@ func MyHandler(w http.ResponseWriter, r *http.Request) {
131143
}
132144
```
133145

134-
Note: This is not required, but is highly recommended. By setting a customer ID you can easily associate requests with your customers/users in the Speakeasy Dashboard, powering filters in the Request Viewer [(Coming soon)](https://docs.speakeasyapi.dev/speakeasy-user-guide/request-viewer-coming-soon).
146+
Note: This is not required, but is highly recommended. By setting a customer ID you can easily associate requests with your customers/users in the Speakeasy Dashboard, powering filters in the [Request Viewer](https://docs.speakeasyapi.dev/speakeasy-user-guide/request-viewer).
147+
148+
## Masking sensitive data
149+
150+
Speakeasy can mask sensitive data in the query string parameters, headers, cookies and request/response bodies captured by the SDK. This is useful for maintaining sensitive data isolation, and retaining control over the data that is captured.
151+
152+
Using the `Advanced Configuration` section above you can completely ignore certain routes by not assigning the middleware to their router, causing the SDK to not capture any requests to that router.
153+
154+
But if you would like to be more selective you can mask certain sensitive data using our middleware controller allowing you to mask fields as needed in different handlers:
155+
156+
```go
157+
func MyHandler(w http.ResponseWriter, r *http.Request) {
158+
ctrl := speakeasy.MiddlewareController(req)
159+
ctrl.Masking(speakeasy.WithRequestHeaderMask("Authorization")) // Mask the Authorization header in the request
160+
161+
// the rest of your handlers code
162+
}
163+
```
164+
165+
The `Masking` function takes a number of different options to mask sensitive data in the request:
166+
167+
* `speakeasy.WithQueryStringMask` - **WithQueryStringMask** will mask the specified query strings with an optional mask string.
168+
* `speakeasy.WithRequestHeaderMask` - **WithRequestHeaderMask** will mask the specified request headers with an optional mask string.
169+
* `speakeasy.WithResponseHeaderMask` - **WithResponseHeaderMask** will mask the specified response headers with an optional mask string.
170+
* `speakeasy.WithRequestCookieMask` - **WithRequestCookieMask** will mask the specified request cookies with an optional mask string.
171+
* `speakeasy.WithResponseCookieMask` - **WithResponseCookieMask** will mask the specified response cookies with an optional mask string.
172+
* `speakeasy.WithRequestFieldMaskString` - **WithRequestFieldMaskString** will mask the specified request body fields with an optional mask. Supports string fields only. Matches using regex.
173+
* `speakeasy.WithRequestFieldMaskNumber` - **WithRequestFieldMaskNumber** will mask the specified request body fields with an optional mask. Supports number fields only. Matches using regex.
174+
* `speakeasy.WithResponseFieldMaskString` - **WithResponseFieldMaskString** will mask the specified response body fields with an optional mask. Supports string fields only. Matches using regex.
175+
* `speakeasy.WithResponseFieldMaskNumber` - **WithResponseFieldMaskNumber** will mask the specified response body fields with an optional mask. Supports number fields only. Matches using regex.
176+
177+
Masking can also be done more globally on all routes or a selection of routes by taking advantage of middleware. Here is an example:
178+
179+
```go
180+
speakeasy.Configure(speakeasy.Config {
181+
APIKey: "YOUR API KEY HERE", // retrieve from Speakeasy API dashboard.
182+
ApiID: "YOUR API ID HERE", // this is an ID you provide that you would like to associate captured requests with.
183+
VersionID: "YOUR VERSION ID HERE", // this is a Version you provide that you would like to associate captured requests with.
184+
})
185+
186+
r := mux.NewRouter()
187+
r.Use(speakeasy.Middleware)
188+
r.Use(func (next http.Handler) http.Handler {
189+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
190+
// Mask the Authorization header in the request for all requests served by this middleware
191+
ctrl := speakeasy.MiddlewareController(req)
192+
ctrl.Masking(speakeasy.WithRequestHeaderMask("Authorization"))
193+
})
194+
})
195+
```

0 commit comments

Comments
 (0)