client: allow injecting a custom *http.Client (SSRF-guardable)
NewClient hardcoded its *http.Client, so a server-side caller making requests to an attacker-influenced baseURL (a tenant's prime_endpoint) had no way to attach an SSRF policy — the transport followed redirects and dialed any resolved IP, reachable being the cloud metadata service. Add NewClientWithHTTPClient + NewDragonchainSDKWithHTTPClient so callers can supply a client whose transport enforces a dial-time resolved-IP guard and redirect policy. Existing constructors delegate with the prior default (30s timeout), so this is backward compatible — the guard itself lives in the consuming server (e.g. brill-api/pkg/prime), not in this client lib.
This commit is contained in:
@@ -23,14 +23,23 @@ type Client struct {
|
||||
}
|
||||
|
||||
func NewClient(publicID, authKeyID, authKey, baseURL string) *Client {
|
||||
return NewClientWithHTTPClient(publicID, authKeyID, authKey, baseURL, nil)
|
||||
}
|
||||
|
||||
// NewClientWithHTTPClient is like NewClient but uses a caller-supplied
|
||||
// *http.Client — e.g. one whose transport is SSRF-guarded, or one with a
|
||||
// non-default timeout. A nil hc falls back to the package default (30s
|
||||
// timeout, default transport), so existing callers are unaffected.
|
||||
func NewClientWithHTTPClient(publicID, authKeyID, authKey, baseURL string, hc *http.Client) *Client {
|
||||
if hc == nil {
|
||||
hc = &http.Client{Timeout: 30 * time.Second}
|
||||
}
|
||||
return &Client{
|
||||
publicID: publicID,
|
||||
authKeyID: authKeyID,
|
||||
authKey: authKey,
|
||||
baseURL: strings.TrimSuffix(baseURL, "/"),
|
||||
httpClient: &http.Client{
|
||||
Timeout: 30 * time.Second,
|
||||
},
|
||||
httpClient: hc,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
package sdk
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"git.dragonchain.com/dragonchain/prime-sdk-go/block"
|
||||
"git.dragonchain.com/dragonchain/prime-sdk-go/client"
|
||||
"git.dragonchain.com/dragonchain/prime-sdk-go/contract"
|
||||
@@ -80,7 +82,15 @@ type DragonchainSDK struct {
|
||||
// Returns a configured SDK client ready to make API calls.
|
||||
// All API methods on the returned client require a context.Context parameter.
|
||||
func NewDragonchainSDK(publicID, authKeyID, authKey, baseURL string) *DragonchainSDK {
|
||||
c := client.NewClient(publicID, authKeyID, authKey, baseURL)
|
||||
return NewDragonchainSDKWithHTTPClient(publicID, authKeyID, authKey, baseURL, nil)
|
||||
}
|
||||
|
||||
// NewDragonchainSDKWithHTTPClient is like NewDragonchainSDK but routes every
|
||||
// request through the caller-supplied *http.Client. Pass a client whose
|
||||
// transport enforces an SSRF policy (guarded dialer + redirect checks) when
|
||||
// the baseURL is attacker-influenced. A nil hc falls back to the SDK default.
|
||||
func NewDragonchainSDKWithHTTPClient(publicID, authKeyID, authKey, baseURL string, hc *http.Client) *DragonchainSDK {
|
||||
c := client.NewClientWithHTTPClient(publicID, authKeyID, authKey, baseURL, hc)
|
||||
return &DragonchainSDK{
|
||||
client: c,
|
||||
Transaction: transaction.NewTransactionClient(c),
|
||||
|
||||
Reference in New Issue
Block a user