Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V2: Add proxy config #81

Merged
merged 2 commits into from
Sep 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 12 additions & 13 deletions aws_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ package awsbase

import (
"context"
"crypto/tls"
"errors"
"fmt"
"log"
"net"
"net/http"
"os"
"strings"
"time"
Expand All @@ -22,7 +20,7 @@ import (
"github.com/aws/smithy-go/middleware"
"github.com/hashicorp/aws-sdk-go-base/v2/internal/constants"
"github.com/hashicorp/aws-sdk-go-base/v2/internal/endpoints"
"github.com/hashicorp/go-cleanhttp"
"github.com/hashicorp/aws-sdk-go-base/v2/internal/httpclient"
)

func GetAwsConfig(ctx context.Context, c *Config) (aws.Config, error) {
Expand All @@ -40,8 +38,12 @@ func GetAwsConfig(ctx context.Context, c *Config) (aws.Config, error) {
Retryer: retryer,
}

loadOptions := append(
commonLoadOptions(c),
loadOptions, err := commonLoadOptions(c)
if err != nil {
return aws.Config{}, err
}
loadOptions = append(
loadOptions,
config.WithCredentialsProvider(credentialsProvider),
config.WithRetryer(func() aws.Retryer {
return retryer
Expand Down Expand Up @@ -119,13 +121,10 @@ func GetAwsAccountIDAndPartition(ctx context.Context, awsConfig aws.Config, skip
return "", endpoints.PartitionForRegion(awsConfig.Region), nil
}

func commonLoadOptions(c *Config) []func(*config.LoadOptions) error {
httpClient := cleanhttp.DefaultClient()
if c.Insecure {
transport := httpClient.Transport.(*http.Transport)
transport.TLSClientConfig = &tls.Config{
InsecureSkipVerify: true,
}
func commonLoadOptions(c *Config) ([]func(*config.LoadOptions) error, error) {
httpClient, err := httpclient.DefaultHttpClient(c)
if err != nil {
return nil, err
}

apiOptions := make([]func(*middleware.Stack) error, 0)
Expand Down Expand Up @@ -171,5 +170,5 @@ func commonLoadOptions(c *Config) []func(*config.LoadOptions) error {
os.Setenv("AWS_EC2_METADATA_DISABLED", "true")
}

return loadOptions
return loadOptions, nil
}
50 changes: 11 additions & 39 deletions config.go
Original file line number Diff line number Diff line change
@@ -1,44 +1,16 @@
package awsbase

type Config struct {
AccessKey string
APNInfo *APNInfo
AssumeRole *AssumeRole
CallerDocumentationURL string
CallerName string
DebugLogging bool
IamEndpoint string
Insecure bool
MaxRetries int
Profile string
Region string
SecretKey string
SharedCredentialsFiles []string
SharedConfigFiles []string
SkipCredsValidation bool
SkipMetadataApiCheck bool
StsEndpoint string
Token string
}
import (
"github.com/hashicorp/aws-sdk-go-base/v2/internal/config"
)

type APNInfo struct {
PartnerName string
Products []APNProduct
}
// Config, APNInfo, APNProduct, and AssumeRole are aliased to an internal package to break a dependency cycle
// in internal/httpclient.

type APNProduct struct {
Name string
Version string
Comment string
}
type Config = config.Config

type AssumeRole struct {
RoleARN string
DurationSeconds int
ExternalID string
Policy string
PolicyARNs []string
SessionName string
Tags map[string]string
TransitiveTagKeys []string
}
type APNInfo = config.APNInfo

type APNProduct = config.APNProduct

type AssumeRole = config.AssumeRole
8 changes: 6 additions & 2 deletions credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ import (
)

func getCredentialsProvider(ctx context.Context, c *Config) (aws.CredentialsProvider, error) {
loadOptions := append(
commonLoadOptions(c),
loadOptions, err := commonLoadOptions(c)
if err != nil {
return nil, err
}
loadOptions = append(
loadOptions,
config.WithSharedConfigProfile(c.Profile),
// Bypass retries when validating authentication
config.WithRetryer(func() aws.Retryer {
Expand Down
59 changes: 4 additions & 55 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,75 +2,24 @@ package awsbase

import (
"errors"
"fmt"

"github.com/hashicorp/aws-sdk-go-base/v2/internal/config"
)

// CannotAssumeRoleError occurs when AssumeRole cannot complete.
type CannotAssumeRoleError struct {
Config *Config
Err error
}

func (e CannotAssumeRoleError) Error() string {
if e.Config == nil || e.Config.AssumeRole == nil {
return fmt.Sprintf("cannot assume role: %s", e.Err)
}

return fmt.Sprintf(`IAM Role (%s) cannot be assumed.

There are a number of possible causes of this - the most common are:
* The credentials used in order to assume the role are invalid
* The credentials do not have appropriate permission to assume the role
* The role ARN is not valid

Error: %s
`, e.Config.AssumeRole.RoleARN, e.Err)
}

func (e CannotAssumeRoleError) Unwrap() error {
return e.Err
}
type CannotAssumeRoleError = config.CannotAssumeRoleError

// IsCannotAssumeRoleError returns true if the error contains the CannotAssumeRoleError type.
func IsCannotAssumeRoleError(err error) bool {
var e CannotAssumeRoleError
return errors.As(err, &e)
}

func (c *Config) NewCannotAssumeRoleError(err error) CannotAssumeRoleError {
return CannotAssumeRoleError{Config: c, Err: err}
}

// NoValidCredentialSourcesError occurs when all credential lookup methods have been exhausted without results.
type NoValidCredentialSourcesError struct {
Config *Config
Err error
}

func (e NoValidCredentialSourcesError) Error() string {
if e.Config == nil {
return fmt.Sprintf("no valid credential sources found: %s", e.Err)
}

return fmt.Sprintf(`no valid credential sources for %[1]s found.

Please see %[2]s
for more information about providing credentials.

Error: %[3]s
`, e.Config.CallerName, e.Config.CallerDocumentationURL, e.Err)
}

func (e NoValidCredentialSourcesError) Unwrap() error {
return e.Err
}
type NoValidCredentialSourcesError = config.NoValidCredentialSourcesError

// IsNoValidCredentialSourcesError returns true if the error contains the NoValidCredentialSourcesError type.
func IsNoValidCredentialSourcesError(err error) bool {
var e NoValidCredentialSourcesError
return errors.As(err, &e)
}

func (c *Config) NewNoValidCredentialSourcesError(err error) NoValidCredentialSourcesError {
return NoValidCredentialSourcesError{Config: c, Err: err}
}
29 changes: 29 additions & 0 deletions internal/config/apn_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package config

import (
smithyhttp "github.com/aws/smithy-go/transport/http"
)

// Builds the user-agent string for APN
func (apn APNInfo) BuildUserAgentString() string {
builder := smithyhttp.NewUserAgentBuilder()
builder.AddKeyValue("APN", "1.0")
builder.AddKeyValue(apn.PartnerName, "1.0")
for _, p := range apn.Products {
p.buildUserAgentPart(builder)
}
return builder.Build()
}

func (p APNProduct) buildUserAgentPart(b *smithyhttp.UserAgentBuilder) {
if p.Name != "" {
if p.Version != "" {
b.AddKeyValue(p.Name, p.Version)
} else {
b.AddKey(p.Name)
}
}
if p.Comment != "" {
b.AddKey("(" + p.Comment + ")")
}
}
45 changes: 45 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package config

type Config struct {
AccessKey string
APNInfo *APNInfo
AssumeRole *AssumeRole
CallerDocumentationURL string
CallerName string
DebugLogging bool
HTTPProxy string
IamEndpoint string
Insecure bool
MaxRetries int
Profile string
Region string
SecretKey string
SharedCredentialsFiles []string
SharedConfigFiles []string
SkipCredsValidation bool
SkipMetadataApiCheck bool
StsEndpoint string
Token string
}

type APNInfo struct {
PartnerName string
Products []APNProduct
}

type APNProduct struct {
Name string
Version string
Comment string
}

type AssumeRole struct {
RoleARN string
DurationSeconds int
ExternalID string
Policy string
PolicyARNs []string
SessionName string
Tags map[string]string
TransitiveTagKeys []string
}
63 changes: 63 additions & 0 deletions internal/config/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package config

import (
"fmt"
)

// CannotAssumeRoleError occurs when AssumeRole cannot complete.
type CannotAssumeRoleError struct {
Config *Config
Err error
}

func (e CannotAssumeRoleError) Error() string {
if e.Config == nil || e.Config.AssumeRole == nil {
return fmt.Sprintf("cannot assume role: %s", e.Err)
}

return fmt.Sprintf(`IAM Role (%s) cannot be assumed.

There are a number of possible causes of this - the most common are:
* The credentials used in order to assume the role are invalid
* The credentials do not have appropriate permission to assume the role
* The role ARN is not valid

Error: %s
`, e.Config.AssumeRole.RoleARN, e.Err)
}

func (e CannotAssumeRoleError) Unwrap() error {
return e.Err
}

func (c *Config) NewCannotAssumeRoleError(err error) CannotAssumeRoleError {
return CannotAssumeRoleError{Config: c, Err: err}
}

// NoValidCredentialSourcesError occurs when all credential lookup methods have been exhausted without results.
type NoValidCredentialSourcesError struct {
Config *Config
Err error
}

func (e NoValidCredentialSourcesError) Error() string {
if e.Config == nil {
return fmt.Sprintf("no valid credential sources found: %s", e.Err)
}

return fmt.Sprintf(`no valid credential sources for %[1]s found.

Please see %[2]s
for more information about providing credentials.

Error: %[3]s
`, e.Config.CallerName, e.Config.CallerDocumentationURL, e.Err)
}

func (e NoValidCredentialSourcesError) Unwrap() error {
return e.Err
}

func (c *Config) NewNoValidCredentialSourcesError(err error) NoValidCredentialSourcesError {
return NoValidCredentialSourcesError{Config: c, Err: err}
}
38 changes: 38 additions & 0 deletions internal/httpclient/http_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package httpclient

import (
"crypto/tls"
"fmt"
"net/http"
"net/url"

"github.com/hashicorp/aws-sdk-go-base/v2/internal/config"
"github.com/hashicorp/go-cleanhttp"
)

func DefaultHttpClient(c *config.Config) (*http.Client, error) {
httpClient := cleanhttp.DefaultClient()
transport := httpClient.Transport.(*http.Transport)

tlsConfig := transport.TLSClientConfig
if tlsConfig == nil {
tlsConfig = &tls.Config{}
transport.TLSClientConfig = tlsConfig
}
tlsConfig.MinVersion = tls.VersionTLS12

if c.Insecure {
tlsConfig.InsecureSkipVerify = true
}

if c.HTTPProxy != "" {
proxyUrl, err := url.Parse(c.HTTPProxy)
if err != nil {
return nil, fmt.Errorf("error parsing HTTP proxy URL: %w", err)
}

transport.Proxy = http.ProxyURL(proxyUrl)
}

return httpClient, nil
}
Loading