Skip to content

Commit

Permalink
config: Add support for SharedConfig file ca_bundle parameter (#1593)
Browse files Browse the repository at this point in the history
Adds support for the `ca_bundle` parameter in shared config and
credentials files. The usage of the file is the same as environment
variable, `AWS_CA_BUNDLE`, but sourced from shared config.

Fixes #1589

Usage:
  [profile myProfile]
  ca_bundle = path/to/ca/bundle.pem
  • Loading branch information
jasdel committed Feb 23, 2022
1 parent 60feb1d commit b7ee4d6
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 3 deletions.
8 changes: 8 additions & 0 deletions .changelog/aacb97e021754263bfbfe819a6e5d7c9.json
@@ -0,0 +1,8 @@
{
"id": "aacb97e0-2175-4263-bfbf-e819a6e5d7c9",
"type": "feature",
"description": "Adds support for the `ca_bundle` parameter in shared config and credentials files. The usage of the file is the same as environment variable, `AWS_CA_BUNDLE`, but sourced from shared config. Fixes [#1589](https://github.com/aws/aws-sdk-go-v2/issues/1589)",
"modules": [
"config"
]
}
2 changes: 1 addition & 1 deletion config/codegen/main.go
Expand Up @@ -22,7 +22,7 @@ const (
var implAsserts = map[string][]string{
"sharedConfigProfileProvider": {envConfigType, loadOptionsType},
"sharedConfigFilesProvider": {envConfigType, loadOptionsType},
"customCABundleProvider": {envConfigType, loadOptionsType},
"customCABundleProvider": {envConfigType, sharedConfigType, loadOptionsType},
"regionProvider": {envConfigType, sharedConfigType, loadOptionsType, ec2IMDSRegionType},
"credentialsProviderProvider": {loadOptionsType},
"defaultRegionProvider": {loadOptionsType},
Expand Down
1 change: 1 addition & 0 deletions config/provider_assert_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 40 additions & 2 deletions config/shared_config.go
@@ -1,9 +1,12 @@
package config

import (
"bytes"
"context"
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
Expand Down Expand Up @@ -81,6 +84,8 @@ const (
// Retry options
retryMaxAttemptsKey = "max_attempts"
retryModeKey = "retry_mode"

caBundleKey = "ca_bundle"
)

// defaultSharedConfigProfile allows for swapping the default profile for testing
Expand Down Expand Up @@ -171,12 +176,14 @@ type SharedConfig struct {
// s3_use_arn_region=true
S3UseARNRegion *bool

// Specifies the EC2 Instance Metadata Service default endpoint selection mode (IPv4 or IPv6)
// Specifies the EC2 Instance Metadata Service default endpoint selection
// mode (IPv4 or IPv6)
//
// ec2_metadata_service_endpoint_mode=IPv6
EC2IMDSEndpointMode imds.EndpointModeState

// Specifies the EC2 Instance Metadata Service endpoint to use. If specified it overrides EC2IMDSEndpointMode.
// Specifies the EC2 Instance Metadata Service endpoint to use. If
// specified it overrides EC2IMDSEndpointMode.
//
// ec2_metadata_service_endpoint=http://fd00:ec2::254
EC2IMDSEndpoint string
Expand Down Expand Up @@ -214,6 +221,22 @@ type SharedConfig struct {
//
// retry_mode=standard
RetryMode aws.RetryMode

// Sets the path to a custom Credentials Authority (CA) Bundle PEM file
// that the SDK will use instead of the system's root CA bundle. Only use
// this if you want to configure the SDK to use a custom set of CAs.
//
// Enabling this option will attempt to merge the Transport into the SDK's
// HTTP client. If the client's Transport is not a http.Transport an error
// will be returned. If the Transport's TLS config is set this option will
// cause the SDK to overwrite the Transport's TLS config's RootCAs value.
//
// Setting a custom HTTPClient in the aws.Config options will override this
// setting. To use this option and custom HTTP client, the HTTP client
// needs to be provided when creating the config. Not the service client.
//
// ca_bundle=$HOME/my_custom_ca_bundle
CustomCABundle string
}

func (c SharedConfig) getDefaultsMode(ctx context.Context) (value aws.DefaultsMode, ok bool, err error) {
Expand Down Expand Up @@ -323,6 +346,19 @@ func (c SharedConfig) GetUseFIPSEndpoint(ctx context.Context) (value aws.FIPSEnd
return c.UseFIPSEndpoint, true, nil
}

// GetCustomCABundle returns the custom CA bundle's PEM bytes if the file was
func (c SharedConfig) getCustomCABundle(context.Context) (io.Reader, bool, error) {
if len(c.CustomCABundle) == 0 {
return nil, false, nil
}

b, err := ioutil.ReadFile(c.CustomCABundle)
if err != nil {
return nil, false, err
}
return bytes.NewReader(b), true, nil
}

// loadSharedConfigIgnoreNotExist is an alias for loadSharedConfig with the
// addition of ignoring when none of the files exist or when the profile
// is not found in any of the files.
Expand Down Expand Up @@ -871,6 +907,8 @@ func (c *SharedConfig) setFromIniSection(profile string, section ini.Section) er
return fmt.Errorf("failed to load %s from shared config, %w", retryModeKey, err)
}

updateString(&c.CustomCABundle, section, caBundleKey)

// Shared Credentials
creds := aws.Credentials{
AccessKeyID: section.String(accessKeyIDKey),
Expand Down
9 changes: 9 additions & 0 deletions config/shared_config_test.go
Expand Up @@ -574,6 +574,15 @@ func TestNewSharedConfig(t *testing.T) {
Profile: "retrywithinvalidattempts",
Err: fmt.Errorf("failed to load max_attempts from shared config, invalid value max_attempts=invalid, expect integer"),
},
"ca bundle options": {
ConfigFilenames: []string{testConfigFilename},
CredentialsFilenames: []string{testCredentialsFilename},
Profile: "with_ca_bundle",
Expected: SharedConfig{
Profile: "with_ca_bundle",
CustomCABundle: "custom_ca_bundle_file.pem",
},
},
"merged profiles across files": {
ConfigFilenames: []string{testConfigFilename},
CredentialsFilenames: []string{testCredentialsFilename},
Expand Down
3 changes: 3 additions & 0 deletions config/testdata/shared_config
Expand Up @@ -257,3 +257,6 @@ retry_mode = invalid

[profile retrywithinvalidattempts]
max_attempts = invalid

[profile with_ca_bundle]
ca_bundle = custom_ca_bundle_file.pem

0 comments on commit b7ee4d6

Please sign in to comment.