Skip to content

Commit

Permalink
Merge pull request #775 from hashicorp/b-proxy-config
Browse files Browse the repository at this point in the history
Adds full proxy configuration
  • Loading branch information
gdavison authored Nov 14, 2023
2 parents d9c55ad + f788913 commit 110a94d
Show file tree
Hide file tree
Showing 18 changed files with 844 additions and 30 deletions.
10 changes: 6 additions & 4 deletions .semgrep/imports.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ rules:
paths:
exclude:
- awsv1shim
- tfawserr
- awsmocks
patterns:
- pattern: |
import ("$X")
- focus-metavariable: $X
- metavariable-regex:
metavariable: "$X"
regex: '^"github.com/aws/aws-sdk-go/.+"$'
regex: 'github.com/aws/aws-sdk-go/.+'
severity: ERROR

- id: no-sdkv2-imports-in-awsv1shim
Expand All @@ -24,15 +24,17 @@ rules:
paths:
include:
- awsv1shim
- tfawserr
patterns:
- pattern: |
import ("$X")
- focus-metavariable: $X
- metavariable-regex:
metavariable: "$X"
regex: '^"github.com/aws/aws-sdk-go-v2/.+"$'
regex: 'github.com/aws/aws-sdk-go-v2/.+'
- pattern-not: |
import ("github.com/aws/aws-sdk-go-v2/aws/transport/http")
- pattern-not: |
import ("github.com/aws/aws-sdk-go-v2/config")
- pattern-not: |
import ("github.com/aws/aws-sdk-go-v2/aws/retry")
severity: ERROR
Empty file added .semgrepignore
Empty file.
5 changes: 5 additions & 0 deletions aws_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ func GetAwsConfig(ctx context.Context, c *Config) (context.Context, aws.Config,
}
}

c.ValidateProxySettings(&diags)
if diags.HasError() {
return ctx, aws.Config{}, diags
}

logger.Debug(baseCtx, "Resolving credentials provider")
credentialsProvider, initialSource, d := getCredentialsProvider(baseCtx, c)
if d.HasError() {
Expand Down
2 changes: 1 addition & 1 deletion aws_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1239,7 +1239,7 @@ func testUserAgentProducts(t *testing.T, testCase test.UserAgentTestCase) {
}
}

var errCancelOperation = fmt.Errorf("Test: Cancelling request")
var errCancelOperation = errors.New("Test: Cancelling request")

// cancelRequestMiddleware creates a Smithy middleware that intercepts the request before sending and cancels it
func cancelRequestMiddleware(t *testing.T, id string, f func(t *testing.T, request *smithyhttp.Request)) middleware.FinalizeMiddleware {
Expand Down
5 changes: 5 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,8 @@ func EC2MetadataEndpointMode_Values() []string {
EC2MetadataEndpointModeIPv6,
}
}

const (
HTTPProxyModeLegacy = config.HTTPProxyModeLegacy
HTTPProxyModeSeparate = config.HTTPProxyModeSeparate
)
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ require (
go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.45.0
go.opentelemetry.io/otel v1.19.0
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
golang.org/x/net v0.17.0
golang.org/x/text v0.14.0
)

Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1
go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
16 changes: 16 additions & 0 deletions http_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package awsbase

import (
"net/http"
"testing"

"github.com/hashicorp/aws-sdk-go-base/v2/internal/config"
Expand Down Expand Up @@ -33,3 +34,18 @@ func TestHTTPClientConfiguration_insecureHTTPS(t *testing.T) {

test.HTTPClientConfigurationTest_insecureHTTPS(t, transport)
}

func TestHTTPClientConfiguration_proxy(t *testing.T) {
test.HTTPClientConfigurationTest_proxy(t, transport)
}

func transport(t *testing.T, config *config.Config) *http.Transport {
t.Helper()

client, err := defaultHttpClient(config)
if err != nil {
t.Fatalf("creating client: %s", err)
}

return client.GetTransport()
}
103 changes: 96 additions & 7 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,17 @@ import (
"github.com/aws/aws-sdk-go-v2/aws"
awshttp "github.com/aws/aws-sdk-go-v2/aws/transport/http"
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
"github.com/hashicorp/aws-sdk-go-base/v2/diag"
"github.com/hashicorp/aws-sdk-go-base/v2/internal/expand"
"github.com/hashicorp/aws-sdk-go-base/v2/logging"
"golang.org/x/net/http/httpproxy"
)

type ProxyMode int

const (
HTTPProxyModeLegacy ProxyMode = iota
HTTPProxyModeSeparate
)

type Config struct {
Expand All @@ -33,12 +42,15 @@ type Config struct {
EC2MetadataServiceEndpointMode string
ForbiddenAccountIds []string
HTTPClient *http.Client
HTTPProxy string
HTTPProxy *string
HTTPSProxy *string
IamEndpoint string
Insecure bool
Logger logging.Logger
MaxRetries int
NoProxy string
Profile string
HTTPProxyMode ProxyMode
Region string
RetryMode aws.RetryMode
SecretKey string
Expand Down Expand Up @@ -88,11 +100,18 @@ func (c Config) CustomCABundleReader() (*bytes.Reader, error) {
// The returned options function is called on both AWS SDKv1 and v2 default HTTP clients.
func (c Config) HTTPTransportOptions() (func(*http.Transport), error) {
var err error
var proxyUrl *url.URL
if c.HTTPProxy != "" {
proxyUrl, err = url.Parse(c.HTTPProxy)
var httpProxyUrl *url.URL
if c.HTTPProxy != nil {
httpProxyUrl, err = url.Parse(aws.ToString(c.HTTPProxy))
if err != nil {
return nil, fmt.Errorf("error parsing HTTP proxy URL: %w", err)
return nil, fmt.Errorf("parsing HTTP proxy URL: %w", err)
}
}
var httpsProxyUrl *url.URL
if c.HTTPSProxy != nil {
httpsProxyUrl, err = url.Parse(aws.ToString(c.HTTPSProxy))
if err != nil {
return nil, fmt.Errorf("parsing HTTPS proxy URL: %w", err)
}
}

Expand All @@ -111,14 +130,84 @@ func (c Config) HTTPTransportOptions() (func(*http.Transport), error) {
tr.TLSClientConfig.InsecureSkipVerify = true
}

if proxyUrl != nil {
tr.Proxy = http.ProxyURL(proxyUrl)
proxyConfig := httpproxy.FromEnvironment()
if httpProxyUrl != nil {
proxyConfig.HTTPProxy = httpProxyUrl.String()
if c.HTTPProxyMode == HTTPProxyModeLegacy && proxyConfig.HTTPSProxy == "" {
proxyConfig.HTTPSProxy = httpProxyUrl.String()
}
}
if httpsProxyUrl != nil {
proxyConfig.HTTPSProxy = httpsProxyUrl.String()
}
if c.NoProxy != "" {
proxyConfig.NoProxy = c.NoProxy
}
tr.Proxy = func(req *http.Request) (*url.URL, error) {
return proxyConfig.ProxyFunc()(req.URL)
}
}

return opts, nil
}

func (c Config) ValidateProxySettings(diags *diag.Diagnostics) {
if c.HTTPProxy != nil {
if _, err := url.Parse(aws.ToString(c.HTTPProxy)); err != nil {
*diags = diags.AddError(
"Invalid HTTP Proxy",
fmt.Sprintf("Unable to parse URL: %s", err),
)
}
}

if c.HTTPSProxy != nil {
if _, err := url.Parse(aws.ToString(c.HTTPSProxy)); err != nil {
*diags = diags.AddError(
"Invalid HTTPS Proxy",
fmt.Sprintf("Unable to parse URL: %s", err),
)
}
}

if c.HTTPProxy != nil && *c.HTTPProxy != "" && c.HTTPSProxy == nil && os.Getenv("HTTPS_PROXY") == "" && os.Getenv("https_proxy") == "" {
if c.HTTPProxyMode == HTTPProxyModeLegacy {
*diags = diags.Append(
missingHttpsProxyLegacyWarningDiag(aws.ToString(c.HTTPProxy)),
)
} else {
*diags = diags.Append(
missingHttpsProxyWarningDiag(),
)
}
}
}

const (
missingHttpsProxyWarningSummary = "Missing HTTPS Proxy"
missingHttpsProxyDetailProblem = "An HTTP proxy was set but no HTTPS proxy was."
missingHttpsProxyDetailResolution = "To specify no proxy for HTTPS, set the HTTPS to an empty string."
)

func missingHttpsProxyLegacyWarningDiag(s string) diag.Diagnostic {
return diag.NewWarningDiagnostic(
missingHttpsProxyWarningSummary,
fmt.Sprintf(
missingHttpsProxyDetailProblem+" Using HTTP proxy %q for HTTPS requests. This behavior may change in future versions.\n\n"+
missingHttpsProxyDetailResolution,
s,
),
)
}

func missingHttpsProxyWarningDiag() diag.Diagnostic {
return diag.NewWarningDiagnostic(
missingHttpsProxyWarningSummary,
missingHttpsProxyDetailProblem+"\n\n"+
missingHttpsProxyDetailResolution,
)
}

func (c Config) ResolveSharedConfigFiles() ([]string, error) {
v, err := expand.FilePaths(c.SharedConfigFiles)
if err != nil {
Expand Down
Loading

0 comments on commit 110a94d

Please sign in to comment.