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 {
|
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{
|
return &Client{
|
||||||
publicID: publicID,
|
publicID: publicID,
|
||||||
authKeyID: authKeyID,
|
authKeyID: authKeyID,
|
||||||
authKey: authKey,
|
authKey: authKey,
|
||||||
baseURL: strings.TrimSuffix(baseURL, "/"),
|
baseURL: strings.TrimSuffix(baseURL, "/"),
|
||||||
httpClient: &http.Client{
|
httpClient: hc,
|
||||||
Timeout: 30 * time.Second,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,8 @@
|
|||||||
package sdk
|
package sdk
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"git.dragonchain.com/dragonchain/prime-sdk-go/block"
|
"git.dragonchain.com/dragonchain/prime-sdk-go/block"
|
||||||
"git.dragonchain.com/dragonchain/prime-sdk-go/client"
|
"git.dragonchain.com/dragonchain/prime-sdk-go/client"
|
||||||
"git.dragonchain.com/dragonchain/prime-sdk-go/contract"
|
"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.
|
// Returns a configured SDK client ready to make API calls.
|
||||||
// All API methods on the returned client require a context.Context parameter.
|
// All API methods on the returned client require a context.Context parameter.
|
||||||
func NewDragonchainSDK(publicID, authKeyID, authKey, baseURL string) *DragonchainSDK {
|
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{
|
return &DragonchainSDK{
|
||||||
client: c,
|
client: c,
|
||||||
Transaction: transaction.NewTransactionClient(c),
|
Transaction: transaction.NewTransactionClient(c),
|
||||||
|
|||||||
Reference in New Issue
Block a user