Unverified Commit 710b01a5 authored by Brian Flad's avatar Brian Flad Committed by GitHub
Browse files

Merge pull request #22253 from hashicorp/v-aws-sdk-go-v1.21.7

deps: github.com/aws/aws-sdk-go@v1.21.7
parents 19ae3a79 acf794b0
main 0.15.3 26258 MatthewTestBranch add-cont-valid-callout add-internals-to-sidebar add-jsonstate-to-cloudbackendstate add-jsonstate-to-cloudbackendstate2 add-learn-callout-moved-blocks add-new-intro-docs add-note-about-spaces add-page-metadata add-tutorial-custom-conditions add-version-notes-1.2 add-warnings-backends alisdair/alpine-latest alisdair/are-consul-tests-running alisdair/backend-config-override-fix-remote-test alisdair/concise-diff-experiment alisdair/disable-preconditions-postconditions alisdair/duplicate-no-color alisdair/fix-configload-snapshot-panic alisdair/fix-remote-backend-migrate-version-check alisdair/getproviders-retries-bad-branch-do-not-use alisdair/metadata-functions-command alisdair/mildwonkey/type-func alisdair/plan-summary-after-changes alisdair/prototype-moved-actions alisdair/providers-list alisdair/remote-input-variable-unset alisdair/resource-instance-object-dependencies alisdair/still-applying-consolidation alisdair/version-should-include-prerelease b-1.1-module-source-git b-check-output-multi-expand b-check-resource-multi-expand b-dev-overrides-plan-warning b-diags-sensitive-value b-flatten-panic b-miekg-dns-upgrade b-module-instance-resource-deps b-move-implied-cross-package b-tf-builtin-provider-parser-fix b-type-conversion-funcs-null b-yamldecode-emptydoc-null backport/29156_do_not_log_sensitive_values/nearly-safe-bullfrog backport/4th-alternate-mirror-directory-fix/closely-key-civet backport/add-cont-valid-callout/luckily-golden-wildcat backport/add-format-function-guidance/ultimately-lucky-halibut backport/add-internals-to-sidebar/willingly-bright-sunbird backport/add-learn-callout-moved-blocks/multiply-awaited-cub backport/add-new-intro-docs/strangely-lucky-bluegill backport/add-powershell-warning/certainly-amazing-lemur backport/add-version-notes-1.2/amazingly-premium-woodcock backport/add-warnings-backends/physically-many-mantis backport/alisdair/cty-1.8.3/seriously-tidy-foal backport/alisdair/fix-30641/firmly-musical-lemming backport/alisdair/fix-show-plan-against-non-default-state/blatantly-balanced-porpoise backport/alisdair/fix-stuck-lock-when-applying-state-plan/enormously-refined-sheepdog backport/alisdair/json-ui-resource-drift/broadly-careful-rooster backport/alisdair/pre-convert-optional-defaults/virtually-able-mouse backport/alisdair/redact-sensitive-values-from-function-errors/definitely-assured-mantis backport/alisdair/sensitive-attribute-forces-replacement/mildly-optimal-platypus backport/b-check-resource-multi-expand/extremely-key-sheep backport/backport/cstella84/patch-add-hyperlink-for-referenced-argument/manually-patient-locust backport/barrettclark/update-go-slug/severely-destined-crow backport/bugfix_typos/hardly-sharp-mosquito backport/clarify-backend-state-storage/ultimately-causal-ladybird backport/consul-size-limit/amazingly-innocent-python backport/cstella84/patch-add-hyperlink-for-referenced-argument backport/description-metadata-language-docs/frankly-desired-penguin backport/doc-provisioner-scp/definitely-capital-bug backport/doc-refactoring-nav-link/honestly-sweet-sawfly backport/doc-s3-fix/utterly-close-rabbit backport/docs-fix-typo/usefully-blessed-monkey backport/docs-for-each-list-toset/basically-still-zebra backport/docs/unknwon-value/completely-musical-lionfish backport/f-build-go1.19.3/largely-peaceful-grouper backport/f-cty-funcs-marks/poorly-mutual-walleye backport/f-non-existing-module-instance-crash/neatly-perfect-kiwi backport/f-plan-action-reason/incredibly-concrete-jackal backport/f-plan-refresh-only-and-replace/really-absolute-silkworm backport/file-provisioner-powershell-warning/noticeably-adequate-mullet backport/fix-apt-page/abnormally-relative-quagga backport/fix-backends-link/strangely-emerging-crane backport/fix-backends-link/vertically-noble-hornet backport/fix-broken-link/certainly-measured-chipmunk backport/fix-broken-links-1-10/firmly-equal-rabbit backport/fix-cdktf-link/highly-pumped-snapper backport/fix-glossary-table-contents/uniquely-pro-garfish backport/fix-grammar/precisely-polite-tortoise backport/fix-internals-overview/globally-allowed-kid backport/fix-internals-overview/noticeably-up-rodent backport/fix-intro-page-images/constantly-capable-shiner backport/fix-last-intro-nits/infinitely-workable-redfish backport/fix-links-devdot/strictly-notable-sparrow backport/fix-links-release/seemingly-living-dinosaur backport/fix-remote-backend-references/primarily-tops-mite backport/fix-workspace-name-docs/ideally-uncommon-pheasant backport/jbardin/cancel-auto-approve/extremely-brave-bear backport/jbardin/coerce-value-nested-types/certainly-rested-chigger backport/jbardin/format-empty-nested-attrs/rightly-uncommon-bluegill backport/jbardin/format-id-name-marks/perfectly-boss-bass backport/jbardin/ignore-changes-marks/formerly-new-insect backport/jbardin/k8s-mod-update/likely-probable-falcon backport/jbardin/optional-attrs/obviously-growing-duck backport/jbardin/static-validate-nested-types/possibly-crack-mouse backport/k8s-backend-credentials/radically-decent-mite backport/kevin/rewrite-internal-redirects/quietly-helped-pelican backport/laura-add-mrui-to-sidebar/highly-resolved-blowfish backport/main/absolutely-sterling-whippet backport/main/cleanly-mature-scorpion backport/mg_no_code_prov_followup/marginally-relevant-eagle backport/mktg-tf-76ef54dc3c574e032725e0341be8e1d2/constantly-smart-kingfish backport/mktg-tf-76ef54dc3c574e032725e0341be8e1d2/distinctly-sharp-ferret backport/mktg-tf-76ef54dc3c574e032725e0341be8e1d2/friendly-evident-grouse backport/module-invocation-warning/fully-fitting-buzzard backport/nvanthao/update-docs-implicit-provider/locally-neutral-lemur backport/optional-type-attributes-note/inherently-dear-goat backport/patch-1/gladly-mature-oarfish backport/patch-1/manually-fine-mantis backport/patch-1/nationally-working-kite backport/patch-1/noticeably-comic-manatee backport/patch-1/rarely-informed-gopher backport/patch-1/sensibly-saving-swine backport/patch-1/usually-clear-shad backport/patch-1/vaguely-deciding-beagle backport/patch-1/virtually-more-rhino backport/patch-1/wholly-verified-racer backport/patch-1/willingly-usable-husky backport/patch-1/yearly-rich-skunk backport/patch-2/badly-game-spider backport/patch-2/finally-amazed-catfish backport/patch-2/openly-clean-tick backport/patch-2/weekly-selected-tiger backport/rar-docs-update-add-anchor/cheaply-sincere-escargot backport/remove-future-statement-import/briefly-viable-glowworm backport/remove-provisioners/readily-correct-ferret backport/remove-provisioners/widely-singular-hound backport/replace-flag-clarifications/definitely-saved-elf backport/replace-flag-updates/nominally-assured-weevil backport/startsswith-to-startswith/highly-gorgeous-katydid backport/system-parameter/infinitely-open-bluebird backport/tf-integration-program-guide/briefly-certain-quail backport/tweak-multi-to-multi-migration-tfc/suddenly-real-duckling backport/update-cloud-block-pages/verbally-key-kangaroo backport/update-console-docs/closely-genuine-javelin backport/update-for-each-example/early-crucial-piranha backport/update-plan-page/lightly-outgoing-halibut backport/update-run-task-result/factually-star-sunfish backport/update_docs_for_30072/gradually-trusting-wahoo backport/workspaces-confusion-fixes/secondly-huge-titmouse barrettclark/fix-state-outputs-read-permissions before-sdk-extraction brandonc/changelog_nested_sensitive brandonc/changelog_sensitive_diff_fixes brandonc/cloud_upgrade_013 brandonc/nested_attr_sensitive brandonc/output_cloud_reads brandonc/providers-estimate brandonc/run_variables_types brandonc/scheme_override_cloud brandonc/variable_parsing_refactor build-circleci build-pr-checks build-workflow-dev/cgo-enabled build-workflow-dev/liamcervante/equivalence-test-action bump-gcp-storage-dependency bump-gcp-storage-dependency-2 cgriggs01-stable-pdp cgriggs01-tpdp-default cloud-e2e-fix cloud-integration-changelog-entry cmd-fmt-parens-error dependabot/go_modules/github.com/bmatcuk/doublestar-1.3.4 dependabot/go_modules/github.com/mattn/go-shellwords-1.0.12 dev-portal-updates-docs dividers-devdot-fixes doc-config-refactoring doc-provisioner-scp doc-refactoring-nav-link doc-s3-backend-dynamodb-locks doc-unicode-hcl doc-yamlencode-stable docs-for-each-list-toset docs-readme-updates-versioned-docs docs/top-pages-gloss ds.submodule-nav-main f-addrs-static-checkable f-build-go1.19.3 f-cli-hide-fast-refresh f-cliconfig-hcl2api f-cmd-output-raw f-cmd-show-config f-cmd-web f-cmdline-funcs f-config-refcount f-core-rpc f-cty-funcs-marks f-debugger f-decode-moved f-depfile-pkg f-derived-values-tracking f-diagnostics-cli-reorg f-dynamic-provider-assignment f-e2etest-deps-forbidden f-expand-root-outputs f-exprstress f-fewer-apply-updates f-fileexists-errmsg f-func-cidrsubnets f-func-expandnull f-functions-in-providers f-gen-integration-tests f-implied-move-module-call f-init-provider-source-feedback f-jsonstate-2 f-langserver f-moduletest-2 f-moved-again f-new-build-pipeline f-new-plan-modes f-ng-workflow f-nix-legacy-providers f-output-value-types f-outputs-plan f-partial-plan-on-error f-partial-plan-on-error-ui f-persistent-checks-old f-plan-immediate-ops f-plan-reads f-plan-refresh-only-and-replace f-playground f-plugin-finder f-possible-apply-refactoring f-preconditions-postconditions f-prototype-drift f-prototype-workspaces-are-states f-provider-http-mirrors f-provider-source-local-discovery f-provider-state-storage f-providerinst-command-tests f-providers-mirror f-providers-mirror-2 f-providers-new-installer f-refresh-plan f-rpcplugin-interface f-skip-attrs-as-blocks f-submodule-outputs-inferred-sensitive f-svcauth-environment f-temp-without-provider-blocks f-template-values f-terraform-version-lock f-testing-with-conditions f-tfaddr-lib f-unused-attr f-validate-lint f-workspaces2-prototype f/azurerm-backend-msal fix-apt-page fix-broken-link fix-broken-links-1-10 fix-cdktf-link fix-dividers-for-devdot fix-future-facing-language fix-future-lang-2 fix-internals-overview fix-intro-page-images fix-last-intro-nits fix-links-devdot fix-links-release fix-postconditions-example fix-preconditions fix-provisioners-content fix-readme-again fix-value-assertion-errors gcs-backend-add-kms gcs-backend-add-private-connect-support gcs-refactor-credential-handling gitrgoliveira-patch-1 go-get1.5.2 gs/add-pre-plan-run-tasks jan21_language_urls jan21_test_broken_link_check jan21_url_rfc jbardin/1.3-destroy-perf jbardin/backport-29017 jbardin/backport-29167 jbardin/backport-29559 jbardin/backport-31576 jbardin/call-plan-destroy jbardin/data-source-destroy-edges jbardin/go-getter-update jbardin/lookup-objects jbardin/null-variable jbardin/output-perf jbardin/plan-orphan-deleted jbardin/remove-deprecated-backends jbardin/resolved-provided-by jbardin/terraform-data jbardin/terraform-null jbardin/trigger-replacement jbardin/variable-eval json-schema-export-crash july2020_pre0.13_stable-website_backup k8s-backend-credentials k8sback kevin/local-preview-post-split kevin/preview kevin/remove-guides-docs kevin/vercel-config kmoe/http-backend-debug-log kmoe/init-checksum-miss-error kmoe/misc-help-text kmoe/unused-resource-attributes lafentres/autolabel-dependabot-prs lafentres/refactor-show-command laura-fix-jsonencode-note laura-update-docs-readme laura-update-pre-post-conditions liamcervante/cicd-go-vet liamcervante/structured-run-output link_multicloud_tutorial_from_use_cases link_to_refresh_tutorial link_workflow_tutorials megan_invalid_creds megan_update_msg migrate-go-tfe-1_0 mnomitch/varialbe-errors-on-remote-backend nf/nov21-migrate-away-from-cloud nq.content-update nq.docs-content-update omarismail/run-vars p-go-azure-helpers-0.10.0 paddy_backport_proto6_download paddy_module_attribution_tmp paddy_paul_proto52 paddy_protocol_six_registry paddy_tf_log_json pault/0.14-tfce-continue-on-error preapply-runtasks-cli-output preapply-runtasks-clioutput prototype-implicit-graph ps-protocol2 pselle/env_delete rar-docs-update-add-anchor regenerate-protobufs registry-provider-tiers release-notes-env-credentials remote-backend-refresh-alias replace-flag-updates res-add-learn-link-debug res-add-learn-link-debug-1 res-lifecycle-tutorial revamp-cli-config revert-29088-minify_jsonencode review-1.0-docs rln-add-versions-tutorials-links rln-modules-track-reference rt-backport-changelog rt-changelog-entry-1.1 run-tasks-backport sebasslash/add-cloud-e2e-test-workflow sebasslash/add-tf-hostname-env-var sebasslash/add-tf-org-env-var sebasslash/env-cloud-e2e-tests sebasslash/err-approval-input-false sebasslash/resolve-flaky-env-var-test sebasslash/tf-workspace-cloud-config solutiongeek-patch-1 stable-website tags-reconfigure-msg tchupp/override-local-vars test-branch-protection-workflow tf-swift-backend-swauth tfc-integration-docs uk1288/backport-cloud-integration-panic-fix uk1288/fix-for-cloud-integration-panic uk1288/update-changelog-md uk1288/update-changelog-md-v1-1 update-TF-WORKSPACE-variable update-cidrnetmask-docs update-depends-on-docs update-for-each-example update-packaging-action-name update-tfe-login-flow update_gen_meta uturunku1-patch-1 uturunku1-patch-2 v0.12 v0.13 v0.14 v0.15 v1.0 v1.1 v1.4.0-alpha20221109 v1.3.5 v1.3.4 v1.3.3 v1.3.2 v1.3.1 v1.3.0 v1.3.0-rc1 v1.3.0-dev v1.3.0-beta1 v1.3.0-alpha20220817 v1.3.0-alpha20220803 v1.3.0-alpha20220706 v1.3.0-alpha20220622 v1.3.0-alpha20220608 v1.2.9 v1.2.8 v1.2.7 v1.2.6 v1.2.5 v1.2.4 v1.2.3 v1.2.2 v1.2.1 v1.2.0 v1.2.0-rc2 v1.2.0-rc1 v1.2.0-beta1 v1.2.0-alpha20220413 v1.2.0-alpha-20220328 v1.1.9 v1.1.8 v1.1.7 v1.1.6 v1.1.5 v1.1.4 v1.1.3 v1.1.2 v1.1.1 v1.1.0 v1.1.0-rc1 v1.1.0-beta2 v1.1.0-beta1 v1.1.0-alpha20211029 v1.1.0-alpha20211020 v1.1.0-alpha20211006 v1.1.0-alpha20210922 v1.1.0-alpha20210908 v1.1.0-alpha20210811 v1.1.0-alpha20210728 v1.1.0-alpha20210714 v1.1.0-alpha20210630 v1.1.0-alpha20210616 v1.0.11 v1.0.10 v1.0.9 v1.0.8 v1.0.7 v1.0.6 v1.0.5 v1.0.4 v1.0.3 v1.0.2 v1.0.1 v1.0.0 v0.15.5 v0.15.4 v0.15.3 v0.15.2 v0.15.1 v0.15.0 v0.15.0-rc2 v0.15.0-rc1 v0.15.0-beta2 v0.15.0-beta1 v0.15.0-alpha20210210 v0.15.0-alpha20210127 v0.15.0-alpha20210107 v0.14.11 v0.14.10 v0.14.9 v0.14.8 v0.14.7 v0.14.6 v0.14.5 v0.14.4 v0.14.3 v0.14.2 v0.14.1 v0.14.0 v0.14.0-rc1 v0.14.0-beta2 v0.14.0-beta1 v0.14.0-alpha20201007 v0.14.0-alpha20200923 v0.14.0-alpha20200910 v0.13.7 v0.13.6 v0.13.5 v0.13.4 v0.13.3 v0.13.2 v0.13.1 v0.13.0 v0.13.0-rc1 v0.13.0-beta3 v0.13.0-beta2 v0.13.0-beta1 v0.12.31 v0.12.30 v0.12.29 v0.12.28 v0.12.27 v0.12.26 v0.12.25 v0.12.24 v0.12.23 v0.12.22 v0.12.21 v0.12.20 v0.12.19 v0.12.18 v0.12.17 v0.12.16 v0.12.15 v0.12.14 v0.12.13 v0.12.12 v0.12.11 v0.12.10 v0.12.9 v0.12.8 v0.12.7 v0.12.6
No related merge requests found
Showing with 748 additions and 269 deletions
+748 -269
......@@ -16,7 +16,7 @@ require (
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da // indirect
github.com/armon/go-radix v1.0.0 // indirect
github.com/aws/aws-sdk-go v1.20.19
github.com/aws/aws-sdk-go v1.21.7
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
github.com/blang/semver v3.5.1+incompatible
github.com/boltdb/bolt v1.3.1 // indirect
......
......@@ -208,7 +208,7 @@ func (e errorList) Error() string {
// How do we want to handle the array size being zero
if size := len(e); size > 0 {
for i := 0; i < size; i++ {
msg += fmt.Sprintf("%s", e[i].Error())
msg += e[i].Error()
// We check the next index to see if it is within the slice.
// If it is, then we append a newline. We do this, because unit tests
// could be broken with the additional '\n'
......
......@@ -185,13 +185,12 @@ func ValuesAtPath(i interface{}, path string) ([]interface{}, error) {
// SetValueAtPath sets a value at the case insensitive lexical path inside
// of a structure.
func SetValueAtPath(i interface{}, path string, v interface{}) {
if rvals := rValuesAtPath(i, path, true, false, v == nil); rvals != nil {
for _, rval := range rvals {
if rval.Kind() == reflect.Ptr && rval.IsNil() {
continue
}
setValue(rval, v)
rvals := rValuesAtPath(i, path, true, false, v == nil)
for _, rval := range rvals {
if rval.Kind() == reflect.Ptr && rval.IsNil() {
continue
}
setValue(rval, v)
}
}
......
......@@ -67,10 +67,14 @@ func logRequest(r *request.Request) {
if !bodySeekable {
r.SetReaderBody(aws.ReadSeekCloser(r.HTTPRequest.Body))
}
// Reset the request body because dumpRequest will re-wrap the r.HTTPRequest's
// Body as a NoOpCloser and will not be reset after read by the HTTP
// client reader.
r.ResetBody()
// Reset the request body because dumpRequest will re-wrap the
// r.HTTPRequest's Body as a NoOpCloser and will not be reset after
// read by the HTTP client reader.
if err := r.Error; err != nil {
r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg,
r.ClientInfo.ServiceName, r.Operation.Name, err))
return
}
}
r.Config.Logger.Log(fmt.Sprintf(logReqMsg,
......
......@@ -84,6 +84,12 @@ type Value struct {
ProviderName string
}
// HasKeys returns if the credentials Value has both AccessKeyID and
// SecretAccessKey value set.
func (v Value) HasKeys() bool {
return len(v.AccessKeyID) != 0 && len(v.SecretAccessKey) != 0
}
// A Provider is the interface for any component which will provide credentials
// Value. A provider is required to manage its own Expired state, and what to
// be expired means.
......
package stscreds
import (
"fmt"
"io/ioutil"
"strconv"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/service/sts"
"github.com/aws/aws-sdk-go/service/sts/stsiface"
)
const (
// ErrCodeWebIdentity will be used as an error code when constructing
// a new error to be returned during session creation or retrieval.
ErrCodeWebIdentity = "WebIdentityErr"
// WebIdentityProviderName is the web identity provider name
WebIdentityProviderName = "WebIdentityCredentials"
)
// now is used to return a time.Time object representing
// the current time. This can be used to easily test and
// compare test values.
var now = time.Now
// WebIdentityRoleProvider is used to retrieve credentials using
// an OIDC token.
type WebIdentityRoleProvider struct {
credentials.Expiry
client stsiface.STSAPI
ExpiryWindow time.Duration
tokenFilePath string
roleARN string
roleSessionName string
}
// NewWebIdentityCredentials will return a new set of credentials with a given
// configuration, role arn, and token file path.
func NewWebIdentityCredentials(c client.ConfigProvider, roleARN, roleSessionName, path string) *credentials.Credentials {
svc := sts.New(c)
p := NewWebIdentityRoleProvider(svc, roleARN, roleSessionName, path)
return credentials.NewCredentials(p)
}
// NewWebIdentityRoleProvider will return a new WebIdentityRoleProvider with the
// provided stsiface.STSAPI
func NewWebIdentityRoleProvider(svc stsiface.STSAPI, roleARN, roleSessionName, path string) *WebIdentityRoleProvider {
return &WebIdentityRoleProvider{
client: svc,
tokenFilePath: path,
roleARN: roleARN,
roleSessionName: roleSessionName,
}
}
// Retrieve will attempt to assume a role from a token which is located at
// 'WebIdentityTokenFilePath' specified destination and if that is empty an
// error will be returned.
func (p *WebIdentityRoleProvider) Retrieve() (credentials.Value, error) {
b, err := ioutil.ReadFile(p.tokenFilePath)
if err != nil {
errMsg := fmt.Sprintf("unable to read file at %s", p.tokenFilePath)
return credentials.Value{}, awserr.New(ErrCodeWebIdentity, errMsg, err)
}
sessionName := p.roleSessionName
if len(sessionName) == 0 {
// session name is used to uniquely identify a session. This simply
// uses unix time in nanoseconds to uniquely identify sessions.
sessionName = strconv.FormatInt(now().UnixNano(), 10)
}
resp, err := p.client.AssumeRoleWithWebIdentity(&sts.AssumeRoleWithWebIdentityInput{
RoleArn: &p.roleARN,
RoleSessionName: &sessionName,
WebIdentityToken: aws.String(string(b)),
})
if err != nil {
return credentials.Value{}, awserr.New(ErrCodeWebIdentity, "failed to retrieve credentials", err)
}
p.SetExpiration(aws.TimeValue(resp.Credentials.Expiration), p.ExpiryWindow)
value := credentials.Value{
AccessKeyID: aws.StringValue(resp.Credentials.AccessKeyId),
SecretAccessKey: aws.StringValue(resp.Credentials.SecretAccessKey),
SessionToken: aws.StringValue(resp.Credentials.SessionToken),
ProviderName: WebIdentityProviderName,
}
return value, nil
}
......@@ -118,7 +118,7 @@ func (rep *Reporter) sendAPICallMetric(r *request.Request) {
Type: aws.String("ApiCall"),
AttemptCount: aws.Int(r.RetryCount + 1),
Region: r.Config.Region,
Latency: aws.Int(int(time.Now().Sub(r.Time) / time.Millisecond)),
Latency: aws.Int(int(time.Since(r.Time) / time.Millisecond)),
XAmzRequestID: aws.String(r.RequestID),
MaxRetriesExceeded: aws.Int(boolIntValue(r.RetryCount >= r.MaxRetries())),
}
......
......@@ -27,6 +27,7 @@ const (
EuWest1RegionID = "eu-west-1" // EU (Ireland).
EuWest2RegionID = "eu-west-2" // EU (London).
EuWest3RegionID = "eu-west-3" // EU (Paris).
MeSouth1RegionID = "me-south-1" // Middle East (Bahrain).
SaEast1RegionID = "sa-east-1" // South America (Sao Paulo).
UsEast1RegionID = "us-east-1" // US East (N. Virginia).
UsEast2RegionID = "us-east-2" // US East (Ohio).
......@@ -128,6 +129,9 @@ var awsPartition = partition{
"eu-west-3": region{
Description: "EU (Paris)",
},
"me-south-1": region{
Description: "Middle East (Bahrain)",
},
"sa-east-1": region{
Description: "South America (Sao Paulo)",
},
......@@ -166,6 +170,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -178,6 +183,7 @@ var awsPartition = partition{
Protocols: []string{"https"},
},
Endpoints: endpoints{
"ap-east-1": endpoint{},
"ap-northeast-1": endpoint{},
"ap-northeast-2": endpoint{},
"ap-south-1": endpoint{},
......@@ -270,6 +276,12 @@ var awsPartition = partition{
Region: "eu-west-3",
},
},
"me-south-1": endpoint{
Hostname: "api.ecr.me-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "me-south-1",
},
},
"sa-east-1": endpoint{
Hostname: "api.ecr.sa-east-1.amazonaws.com",
CredentialScope: credentialScope{
......@@ -381,6 +393,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -409,6 +422,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -503,6 +517,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -657,6 +672,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -748,6 +764,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -841,6 +858,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-1-fips": endpoint{
......@@ -1002,6 +1020,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -1089,6 +1108,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -1117,6 +1137,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -1157,6 +1178,12 @@ var awsPartition = partition{
Region: "eu-west-1",
},
},
"eu-west-2": endpoint{
Hostname: "rds.eu-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-2",
},
},
"us-east-1": endpoint{
Hostname: "rds.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
......@@ -1227,8 +1254,9 @@ var awsPartition = partition{
Region: "us-east-1",
},
},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-1-fips": endpoint{
Hostname: "dynamodb-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
......@@ -1275,6 +1303,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -1308,6 +1337,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -1336,11 +1366,12 @@ var awsPartition = partition{
Region: "us-west-1",
},
},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
},
},
"elasticbeanstalk": service{
......@@ -1358,6 +1389,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -1401,6 +1433,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -1428,6 +1461,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{
SSLCommonName: "{service}.{region}.{dnsSuffix}",
......@@ -1514,6 +1548,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -1568,8 +1603,10 @@ var awsPartition = partition{
"ap-southeast-2": endpoint{},
"eu-central-1": endpoint{},
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
"us-west-2": endpoint{},
},
},
......@@ -1609,6 +1646,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -1670,6 +1708,7 @@ var awsPartition = partition{
Protocols: []string{"https"},
},
Endpoints: endpoints{
"ap-east-1": endpoint{},
"ap-northeast-1": endpoint{},
"ap-northeast-2": endpoint{},
"ap-south-1": endpoint{},
......@@ -1775,6 +1814,65 @@ var awsPartition = partition{
"us-west-2": endpoint{},
},
},
"iotevents": service{
Endpoints: endpoints{
"ap-northeast-1": endpoint{},
"ap-southeast-2": endpoint{},
"eu-central-1": endpoint{},
"eu-west-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-2": endpoint{},
},
},
"ioteventsdata": service{
Endpoints: endpoints{
"ap-northeast-1": endpoint{
Hostname: "data.iotevents.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
},
"ap-southeast-2": endpoint{
Hostname: "data.iotevents.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
},
"eu-central-1": endpoint{
Hostname: "data.iotevents.eu-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-central-1",
},
},
"eu-west-1": endpoint{
Hostname: "data.iotevents.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
},
"us-east-1": endpoint{
Hostname: "data.iotevents.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
"us-east-2": endpoint{
Hostname: "data.iotevents.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
"us-west-2": endpoint{
Hostname: "data.iotevents.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
},
},
"iotthingsgraph": service{
Defaults: endpoint{
CredentialScope: credentialScope{
......@@ -1796,6 +1894,7 @@ var awsPartition = partition{
"ap-southeast-1": endpoint{},
"ap-southeast-2": endpoint{},
"eu-central-1": endpoint{},
"eu-north-1": endpoint{},
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
......@@ -1819,6 +1918,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -1867,6 +1967,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -1889,6 +1990,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -1951,6 +2053,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -2123,6 +2226,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -2390,6 +2494,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -2429,6 +2534,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -2440,8 +2546,11 @@ var awsPartition = partition{
Endpoints: endpoints{
"ap-northeast-1": endpoint{},
"ap-southeast-1": endpoint{},
"eu-central-1": endpoint{},
"eu-west-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-2": endpoint{},
},
},
......@@ -2572,8 +2681,9 @@ var awsPartition = partition{
Hostname: "s3.eu-west-1.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"s3-external-1": endpoint{
Hostname: "s3-external-1.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
......@@ -2991,6 +3101,7 @@ var awsPartition = partition{
Endpoints: endpoints{
"ap-northeast-1": endpoint{},
"ap-northeast-2": endpoint{},
"ap-south-1": endpoint{},
"ap-southeast-1": endpoint{},
"ap-southeast-2": endpoint{},
......@@ -3023,6 +3134,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -3072,7 +3184,8 @@ var awsPartition = partition{
Region: "us-west-2",
},
},
"sa-east-1": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{
SSLCommonName: "queue.{dnsSuffix}",
},
......@@ -3096,6 +3209,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -3118,6 +3232,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -3139,6 +3254,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -3178,8 +3294,9 @@ var awsPartition = partition{
Region: "us-east-1",
},
},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-1-fips": endpoint{
Hostname: "dynamodb-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
......@@ -3241,8 +3358,14 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"me-south-1": endpoint{
Hostname: "sts.me-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "me-south-1",
},
},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-1-fips": endpoint{
Hostname: "sts-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
......@@ -3299,6 +3422,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -3321,6 +3445,7 @@ var awsPartition = partition{
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"me-south-1": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
......@@ -3400,12 +3525,16 @@ var awsPartition = partition{
Endpoints: endpoints{
"ap-northeast-1": endpoint{},
"ap-northeast-2": endpoint{},
"ap-south-1": endpoint{},
"ap-southeast-1": endpoint{},
"ap-southeast-2": endpoint{},
"ca-central-1": endpoint{},
"eu-central-1": endpoint{},
"eu-north-1": endpoint{},
"eu-west-1": endpoint{},
"eu-west-2": endpoint{},
"eu-west-3": endpoint{},
"sa-east-1": endpoint{},
"us-east-1": endpoint{},
"us-east-2": endpoint{},
"us-west-1": endpoint{},
......
......@@ -15,12 +15,15 @@ type offsetReader struct {
closed bool
}
func newOffsetReader(buf io.ReadSeeker, offset int64) *offsetReader {
func newOffsetReader(buf io.ReadSeeker, offset int64) (*offsetReader, error) {
reader := &offsetReader{}
buf.Seek(offset, sdkio.SeekStart)
_, err := buf.Seek(offset, sdkio.SeekStart)
if err != nil {
return nil, err
}
reader.buf = buf
return reader
return reader, nil
}
// Close will close the instance of the offset reader's access to
......@@ -54,7 +57,9 @@ func (o *offsetReader) Seek(offset int64, whence int) (int64, error) {
// CloseAndCopy will return a new offsetReader with a copy of the old buffer
// and close the old buffer.
func (o *offsetReader) CloseAndCopy(offset int64) *offsetReader {
o.Close()
func (o *offsetReader) CloseAndCopy(offset int64) (*offsetReader, error) {
if err := o.Close(); err != nil {
return nil, err
}
return newOffsetReader(o.buf, offset)
}
......@@ -264,7 +264,18 @@ func (r *Request) SetStringBody(s string) {
// SetReaderBody will set the request's body reader.
func (r *Request) SetReaderBody(reader io.ReadSeeker) {
r.Body = reader
r.BodyStart, _ = reader.Seek(0, sdkio.SeekCurrent) // Get the Bodies current offset.
if aws.IsReaderSeekable(reader) {
var err error
// Get the Bodies current offset so retries will start from the same
// initial position.
r.BodyStart, err = reader.Seek(0, sdkio.SeekCurrent)
if err != nil {
r.Error = awserr.New(ErrCodeSerialization,
"failed to determine start of request body", err)
return
}
}
r.ResetBody()
}
......@@ -336,9 +347,7 @@ func getPresignedURL(r *Request, expire time.Duration) (string, http.Header, err
}
const (
willRetry = "will retry"
notRetrying = "not retrying"
retryCount = "retry %v/%v"
)
func debugLogReqError(r *Request, stage, retryStr string, err error) {
......@@ -393,12 +402,16 @@ func (r *Request) Sign() error {
return r.Error
}
func (r *Request) getNextRequestBody() (io.ReadCloser, error) {
func (r *Request) getNextRequestBody() (body io.ReadCloser, err error) {
if r.safeBody != nil {
r.safeBody.Close()
}
r.safeBody = newOffsetReader(r.Body, r.BodyStart)
r.safeBody, err = newOffsetReader(r.Body, r.BodyStart)
if err != nil {
return nil, awserr.New(ErrCodeSerialization,
"failed to get next request body reader", err)
}
// Go 1.8 tightened and clarified the rules code needs to use when building
// requests with the http package. Go 1.8 removed the automatic detection
......@@ -415,10 +428,10 @@ func (r *Request) getNextRequestBody() (io.ReadCloser, error) {
// Related golang/go#18257
l, err := aws.SeekerLen(r.Body)
if err != nil {
return nil, awserr.New(ErrCodeSerialization, "failed to compute request body size", err)
return nil, awserr.New(ErrCodeSerialization,
"failed to compute request body size", err)
}
var body io.ReadCloser
if l == 0 {
body = NoBody
} else if l > 0 {
......@@ -495,13 +508,16 @@ func (r *Request) Send() error {
return r.Error
}
r.prepareRetry()
if err := r.prepareRetry(); err != nil {
r.Error = err
return err
}
continue
}
}
}
func (r *Request) prepareRetry() {
func (r *Request) prepareRetry() error {
if r.Config.LogLevel.Matches(aws.LogDebugWithRequestRetries) {
r.Config.Logger.Log(fmt.Sprintf("DEBUG: Retrying Request %s/%s, attempt %d",
r.ClientInfo.ServiceName, r.Operation.Name, r.RetryCount))
......@@ -512,12 +528,19 @@ func (r *Request) prepareRetry() {
// the request's body even though the Client's Do returned.
r.HTTPRequest = copyHTTPRequest(r.HTTPRequest, nil)
r.ResetBody()
if err := r.Error; err != nil {
return awserr.New(ErrCodeSerialization,
"failed to prepare body for retry", err)
}
// Closing response body to ensure that no response body is leaked
// between retry attempts.
if r.HTTPResponse != nil && r.HTTPResponse.Body != nil {
r.HTTPResponse.Body.Close()
}
return nil
}
func (r *Request) sendRequest() (sendErr error) {
......
......@@ -4,6 +4,8 @@ package request
import (
"net/http"
"github.com/aws/aws-sdk-go/aws/awserr"
)
// NoBody is a http.NoBody reader instructing Go HTTP client to not include
......@@ -24,7 +26,8 @@ var NoBody = http.NoBody
func (r *Request) ResetBody() {
body, err := r.getNextRequestBody()
if err != nil {
r.Error = err
r.Error = awserr.New(ErrCodeSerialization,
"failed to reset request body", err)
return
}
......
......@@ -146,7 +146,7 @@ func (r *Request) nextPageTokens() []interface{} {
return nil
}
case bool:
if v == false {
if !v {
return nil
}
}
......
......@@ -14,123 +14,175 @@ import (
"github.com/aws/aws-sdk-go/internal/shareddefaults"
)
// valid credential source values
const (
credSourceEc2Metadata = "Ec2InstanceMetadata"
credSourceEnvironment = "Environment"
credSourceECSContainer = "EcsContainer"
)
func resolveCredentials(cfg *aws.Config,
envCfg envConfig, sharedCfg sharedConfig,
handlers request.Handlers,
sessOpts Options,
) (*credentials.Credentials, error) {
// Credentials from Assume Role with specific credentials source.
if envCfg.EnableSharedConfig && len(sharedCfg.AssumeRole.CredentialSource) > 0 {
return resolveCredsFromSource(cfg, envCfg, sharedCfg, handlers, sessOpts)
}
// Credentials from environment variables
if len(envCfg.Creds.AccessKeyID) > 0 {
switch {
case len(envCfg.Profile) != 0:
// User explicitly provided an Profile, so load from shared config
// first.
return resolveCredsFromProfile(cfg, envCfg, sharedCfg, handlers, sessOpts)
case envCfg.Creds.HasKeys():
// Environment credentials
return credentials.NewStaticCredentialsFromCreds(envCfg.Creds), nil
case len(envCfg.WebIdentityTokenFilePath) != 0:
// Web identity token from environment, RoleARN required to also be
// set.
return assumeWebIdentity(cfg, handlers,
envCfg.WebIdentityTokenFilePath,
envCfg.RoleARN,
envCfg.RoleSessionName,
)
default:
// Fallback to the "default" credential resolution chain.
return resolveCredsFromProfile(cfg, envCfg, sharedCfg, handlers, sessOpts)
}
}
// WebIdentityEmptyRoleARNErr will occur if 'AWS_WEB_IDENTITY_TOKEN_FILE' was set but
// 'AWS_IAM_ROLE_ARN' was not set.
var WebIdentityEmptyRoleARNErr = awserr.New(stscreds.ErrCodeWebIdentity, "role ARN is not set", nil)
// WebIdentityEmptyTokenFilePathErr will occur if 'AWS_IAM_ROLE_ARN' was set but
// 'AWS_WEB_IDENTITY_TOKEN_FILE' was not set.
var WebIdentityEmptyTokenFilePathErr = awserr.New(stscreds.ErrCodeWebIdentity, "token file path is not set", nil)
func assumeWebIdentity(cfg *aws.Config, handlers request.Handlers,
filepath string,
roleARN, sessionName string,
) (*credentials.Credentials, error) {
if len(filepath) == 0 {
return nil, WebIdentityEmptyTokenFilePathErr
}
if len(roleARN) == 0 {
return nil, WebIdentityEmptyRoleARNErr
}
// Fallback to the "default" credential resolution chain.
return resolveCredsFromProfile(cfg, envCfg, sharedCfg, handlers, sessOpts)
creds := stscreds.NewWebIdentityCredentials(
&Session{
Config: cfg,
Handlers: handlers.Copy(),
},
roleARN,
sessionName,
filepath,
)
return creds, nil
}
func resolveCredsFromProfile(cfg *aws.Config,
envCfg envConfig, sharedCfg sharedConfig,
handlers request.Handlers,
sessOpts Options,
) (*credentials.Credentials, error) {
) (creds *credentials.Credentials, err error) {
if envCfg.EnableSharedConfig && len(sharedCfg.AssumeRole.RoleARN) > 0 && sharedCfg.AssumeRoleSource != nil {
switch {
case sharedCfg.SourceProfile != nil:
// Assume IAM role with credentials source from a different profile.
cred, err := resolveCredsFromProfile(cfg, envCfg, *sharedCfg.AssumeRoleSource, handlers, sessOpts)
if err != nil {
return nil, err
}
creds, err = resolveCredsFromProfile(cfg, envCfg,
*sharedCfg.SourceProfile, handlers, sessOpts,
)
cfgCp := *cfg
cfgCp.Credentials = cred
return credsFromAssumeRole(cfgCp, handlers, sharedCfg, sessOpts)
} else if len(sharedCfg.Creds.AccessKeyID) > 0 {
case sharedCfg.Creds.HasKeys():
// Static Credentials from Shared Config/Credentials file.
return credentials.NewStaticCredentialsFromCreds(
creds = credentials.NewStaticCredentialsFromCreds(
sharedCfg.Creds,
), nil
)
} else if len(sharedCfg.CredentialProcess) > 0 {
case len(sharedCfg.CredentialProcess) != 0:
// Get credentials from CredentialProcess
cred := processcreds.NewCredentials(sharedCfg.CredentialProcess)
// if RoleARN is provided, so the obtained cred from the Credential Process to assume the role using RoleARN
if len(sharedCfg.AssumeRole.RoleARN) > 0 {
cfgCp := *cfg
cfgCp.Credentials = cred
return credsFromAssumeRole(cfgCp, handlers, sharedCfg, sessOpts)
}
return cred, nil
} else if envCfg.EnableSharedConfig && len(sharedCfg.AssumeRole.CredentialSource) > 0 {
// Assume IAM Role with specific credential source.
return resolveCredsFromSource(cfg, envCfg, sharedCfg, handlers, sessOpts)
}
creds = processcreds.NewCredentials(sharedCfg.CredentialProcess)
// Fallback to default credentials provider, include mock errors
// for the credential chain so user can identify why credentials
// failed to be retrieved.
return credentials.NewCredentials(&credentials.ChainProvider{
VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors),
Providers: []credentials.Provider{
&credProviderError{
Err: awserr.New("EnvAccessKeyNotFound",
"failed to find credentials in the environment.", nil),
},
&credProviderError{
Err: awserr.New("SharedCredsLoad",
fmt.Sprintf("failed to load profile, %s.", envCfg.Profile), nil),
case len(sharedCfg.CredentialSource) != 0:
creds, err = resolveCredsFromSource(cfg, envCfg,
sharedCfg, handlers, sessOpts,
)
case len(sharedCfg.WebIdentityTokenFile) != 0:
// Credentials from Assume Web Identity token require an IAM Role, and
// that roll will be assumed. May be wrapped with another assume role
// via SourceProfile.
return assumeWebIdentity(cfg, handlers,
sharedCfg.WebIdentityTokenFile,
sharedCfg.RoleARN,
sharedCfg.RoleSessionName,
)
default:
// Fallback to default credentials provider, include mock errors for
// the credential chain so user can identify why credentials failed to
// be retrieved.
creds = credentials.NewCredentials(&credentials.ChainProvider{
VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors),
Providers: []credentials.Provider{
&credProviderError{
Err: awserr.New("EnvAccessKeyNotFound",
"failed to find credentials in the environment.", nil),
},
&credProviderError{
Err: awserr.New("SharedCredsLoad",
fmt.Sprintf("failed to load profile, %s.", envCfg.Profile), nil),
},
defaults.RemoteCredProvider(*cfg, handlers),
},
defaults.RemoteCredProvider(*cfg, handlers),
},
}), nil
})
}
if err != nil {
return nil, err
}
if len(sharedCfg.RoleARN) > 0 {
cfgCp := *cfg
cfgCp.Credentials = creds
return credsFromAssumeRole(cfgCp, handlers, sharedCfg, sessOpts)
}
return creds, nil
}
// valid credential source values
const (
credSourceEc2Metadata = "Ec2InstanceMetadata"
credSourceEnvironment = "Environment"
credSourceECSContainer = "EcsContainer"
)
func resolveCredsFromSource(cfg *aws.Config,
envCfg envConfig, sharedCfg sharedConfig,
handlers request.Handlers,
sessOpts Options,
) (*credentials.Credentials, error) {
// if both credential_source and source_profile have been set, return an
// error as this is undefined behavior. Only one can be used at a time
// within a profile.
if len(sharedCfg.AssumeRole.SourceProfile) > 0 {
return nil, ErrSharedConfigSourceCollision
}
) (creds *credentials.Credentials, err error) {
cfgCp := *cfg
switch sharedCfg.AssumeRole.CredentialSource {
switch sharedCfg.CredentialSource {
case credSourceEc2Metadata:
p := defaults.RemoteCredProvider(cfgCp, handlers)
cfgCp.Credentials = credentials.NewCredentials(p)
p := defaults.RemoteCredProvider(*cfg, handlers)
creds = credentials.NewCredentials(p)
case credSourceEnvironment:
cfgCp.Credentials = credentials.NewStaticCredentialsFromCreds(envCfg.Creds)
creds = credentials.NewStaticCredentialsFromCreds(envCfg.Creds)
case credSourceECSContainer:
if len(os.Getenv(shareddefaults.ECSCredsProviderEnvVar)) == 0 {
return nil, ErrSharedConfigECSContainerEnvVarEmpty
}
p := defaults.RemoteCredProvider(cfgCp, handlers)
cfgCp.Credentials = credentials.NewCredentials(p)
p := defaults.RemoteCredProvider(*cfg, handlers)
creds = credentials.NewCredentials(p)
default:
return nil, ErrSharedConfigInvalidCredSource
}
return credsFromAssumeRole(cfgCp, handlers, sharedCfg, sessOpts)
return creds, nil
}
func credsFromAssumeRole(cfg aws.Config,
......@@ -138,7 +190,8 @@ func credsFromAssumeRole(cfg aws.Config,
sharedCfg sharedConfig,
sessOpts Options,
) (*credentials.Credentials, error) {
if len(sharedCfg.AssumeRole.MFASerial) > 0 && sessOpts.AssumeRoleTokenProvider == nil {
if len(sharedCfg.MFASerial) != 0 && sessOpts.AssumeRoleTokenProvider == nil {
// AssumeRole Token provider is required if doing Assume Role
// with MFA.
return nil, AssumeRoleTokenProviderNotSetError{}
......@@ -149,28 +202,28 @@ func credsFromAssumeRole(cfg aws.Config,
Config: &cfg,
Handlers: handlers.Copy(),
},
sharedCfg.AssumeRole.RoleARN,
sharedCfg.RoleARN,
func(opt *stscreds.AssumeRoleProvider) {
opt.RoleSessionName = sharedCfg.AssumeRole.RoleSessionName
opt.RoleSessionName = sharedCfg.RoleSessionName
opt.Duration = sessOpts.AssumeRoleDuration
// Assume role with external ID
if len(sharedCfg.AssumeRole.ExternalID) > 0 {
opt.ExternalID = aws.String(sharedCfg.AssumeRole.ExternalID)
if len(sharedCfg.ExternalID) > 0 {
opt.ExternalID = aws.String(sharedCfg.ExternalID)
}
// Assume role with MFA
if len(sharedCfg.AssumeRole.MFASerial) > 0 {
opt.SerialNumber = aws.String(sharedCfg.AssumeRole.MFASerial)
if len(sharedCfg.MFASerial) > 0 {
opt.SerialNumber = aws.String(sharedCfg.MFASerial)
opt.TokenProvider = sessOpts.AssumeRoleTokenProvider
}
},
), nil
}
// AssumeRoleTokenProviderNotSetError is an error returned when creating a session when the
// MFAToken option is not set when shared config is configured load assume a
// role with an MFA token.
// AssumeRoleTokenProviderNotSetError is an error returned when creating a
// session when the MFAToken option is not set when shared config is configured
// load assume a role with an MFA token.
type AssumeRoleTokenProviderNotSetError struct{}
// Code is the short id of the error.
......@@ -197,8 +250,6 @@ type credProviderError struct {
Err error
}
var emptyCreds = credentials.Value{}
func (c credProviderError) Retrieve() (credentials.Value, error) {
return credentials.Value{}, c.Err
}
......
......@@ -104,11 +104,27 @@ type envConfig struct {
CSMClientID string
CSMHost string
enableEndpointDiscovery string
// Enables endpoint discovery via environment variables.
//
// AWS_ENABLE_ENDPOINT_DISCOVERY=true
EnableEndpointDiscovery *bool
enableEndpointDiscovery string
// Specifies the WebIdentity token the SDK should use to assume a role
// with.
//
// AWS_WEB_IDENTITY_TOKEN_FILE=file_path
WebIdentityTokenFilePath string
// Specifies the IAM role arn to use when assuming an role.
//
// AWS_ROLE_ARN=role_arn
RoleARN string
// Specifies the IAM role session name to use when assuming a role.
//
// AWS_ROLE_SESSION_NAME=session_name
RoleSessionName string
}
var (
......@@ -154,6 +170,15 @@ var (
sharedConfigFileEnvKey = []string{
"AWS_CONFIG_FILE",
}
webIdentityTokenFilePathEnvKey = []string{
"AWS_WEB_IDENTITY_TOKEN_FILE",
}
roleARNEnvKey = []string{
"AWS_ROLE_ARN",
}
roleSessionNameEnvKey = []string{
"AWS_ROLE_SESSION_NAME",
}
)
// loadEnvConfig retrieves the SDK's environment configuration.
......@@ -182,9 +207,23 @@ func envConfigLoad(enableSharedConfig bool) envConfig {
cfg.EnableSharedConfig = enableSharedConfig
setFromEnvVal(&cfg.Creds.AccessKeyID, credAccessEnvKey)
setFromEnvVal(&cfg.Creds.SecretAccessKey, credSecretEnvKey)
setFromEnvVal(&cfg.Creds.SessionToken, credSessionEnvKey)
// Static environment credentials
var creds credentials.Value
setFromEnvVal(&creds.AccessKeyID, credAccessEnvKey)
setFromEnvVal(&creds.SecretAccessKey, credSecretEnvKey)
setFromEnvVal(&creds.SessionToken, credSessionEnvKey)
if creds.HasKeys() {
// Require logical grouping of credentials
creds.ProviderName = EnvProviderName
cfg.Creds = creds
}
// Role Metadata
setFromEnvVal(&cfg.RoleARN, roleARNEnvKey)
setFromEnvVal(&cfg.RoleSessionName, roleSessionNameEnvKey)
// Web identity environment variables
setFromEnvVal(&cfg.WebIdentityTokenFilePath, webIdentityTokenFilePathEnvKey)
// CSM environment variables
setFromEnvVal(&cfg.csmEnabled, csmEnabledEnvKey)
......@@ -193,13 +232,6 @@ func envConfigLoad(enableSharedConfig bool) envConfig {
setFromEnvVal(&cfg.CSMClientID, csmClientIDEnvKey)
cfg.CSMEnabled = len(cfg.csmEnabled) > 0
// Require logical grouping of credentials
if len(cfg.Creds.AccessKeyID) == 0 || len(cfg.Creds.SecretAccessKey) == 0 {
cfg.Creds = credentials.Value{}
} else {
cfg.Creds.ProviderName = EnvProviderName
}
regionKeys := regionEnvKeys
profileKeys := profileEnvKeys
if !cfg.EnableSharedConfig {
......
......@@ -376,6 +376,7 @@ func newSession(opts Options, envCfg envConfig, cfgs ...*aws.Config) (*Session,
// credentials were.
userCfg := &aws.Config{}
userCfg.MergeIn(cfgs...)
cfg.MergeIn(userCfg)
// Ordered config files will be loaded in with later files overwriting
// previous config file values.
......@@ -392,9 +393,11 @@ func newSession(opts Options, envCfg envConfig, cfgs ...*aws.Config) (*Session,
}
// Load additional config from file(s)
sharedCfg, err := loadSharedConfig(envCfg.Profile, cfgFiles)
sharedCfg, err := loadSharedConfig(envCfg.Profile, cfgFiles, envCfg.EnableSharedConfig)
if err != nil {
return nil, err
if _, ok := err.(SharedConfigProfileNotExistsError); !ok {
return nil, err
}
}
if err := mergeConfigSrcs(cfg, userCfg, envCfg, sharedCfg, handlers, opts); err != nil {
......@@ -478,8 +481,6 @@ func mergeConfigSrcs(cfg, userCfg *aws.Config,
handlers request.Handlers,
sessOpts Options,
) error {
// Merge in user provided configuration
cfg.MergeIn(userCfg)
// Region if not already set by user
if len(aws.StringValue(cfg.Region)) == 0 {
......
......@@ -27,8 +27,12 @@ const (
// endpoint discovery group
enableEndpointDiscoveryKey = `endpoint_discovery_enabled` // optional
// External Credential Process
credentialProcessKey = `credential_process`
credentialProcessKey = `credential_process` // optional
// Web Identity Token File
webIdentityTokenFileKey = `web_identity_token_file` // optional
// DefaultSharedConfigProfile is the default profile to be used when
// loading configuration from the config files if another profile name
......@@ -36,36 +40,33 @@ const (
DefaultSharedConfigProfile = `default`
)
type assumeRoleConfig struct {
RoleARN string
SourceProfile string
CredentialSource string
ExternalID string
MFASerial string
RoleSessionName string
}
// sharedConfig represents the configuration fields of the SDK config files.
type sharedConfig struct {
// Credentials values from the config file. Both aws_access_key_id
// and aws_secret_access_key must be provided together in the same file
// to be considered valid. The values will be ignored if not a complete group.
// aws_session_token is an optional field that can be provided if both of the
// other two fields are also provided.
// Credentials values from the config file. Both aws_access_key_id and
// aws_secret_access_key must be provided together in the same file to be
// considered valid. The values will be ignored if not a complete group.
// aws_session_token is an optional field that can be provided if both of
// the other two fields are also provided.
//
// aws_access_key_id
// aws_secret_access_key
// aws_session_token
Creds credentials.Value
AssumeRole assumeRoleConfig
AssumeRoleSource *sharedConfig
CredentialSource string
CredentialProcess string
WebIdentityTokenFile string
RoleARN string
RoleSessionName string
ExternalID string
MFASerial string
// An external process to request credentials
CredentialProcess string
SourceProfileName string
SourceProfile *sharedConfig
// Region is the region the SDK should use for looking up AWS service endpoints
// and signing requests.
// Region is the region the SDK should use for looking up AWS service
// endpoints and signing requests.
//
// region
Region string
......@@ -82,17 +83,18 @@ type sharedConfigFile struct {
IniData ini.Sections
}
// loadSharedConfig retrieves the configuration from the list of files
// using the profile provided. The order the files are listed will determine
// loadSharedConfig retrieves the configuration from the list of files using
// the profile provided. The order the files are listed will determine
// precedence. Values in subsequent files will overwrite values defined in
// earlier files.
//
// For example, given two files A and B. Both define credentials. If the order
// of the files are A then B, B's credential values will be used instead of A's.
// of the files are A then B, B's credential values will be used instead of
// A's.
//
// See sharedConfig.setFromFile for information how the config files
// will be loaded.
func loadSharedConfig(profile string, filenames []string) (sharedConfig, error) {
func loadSharedConfig(profile string, filenames []string, exOpts bool) (sharedConfig, error) {
if len(profile) == 0 {
profile = DefaultSharedConfigProfile
}
......@@ -103,16 +105,11 @@ func loadSharedConfig(profile string, filenames []string) (sharedConfig, error)
}
cfg := sharedConfig{}
if err = cfg.setFromIniFiles(profile, files); err != nil {
profiles := map[string]struct{}{}
if err = cfg.setFromIniFiles(profiles, profile, files, exOpts); err != nil {
return sharedConfig{}, err
}
if len(cfg.AssumeRole.SourceProfile) > 0 {
if err := cfg.setAssumeRoleSource(profile, files); err != nil {
return sharedConfig{}, err
}
}
return cfg, nil
}
......@@ -136,71 +133,88 @@ func loadSharedConfigIniFiles(filenames []string) ([]sharedConfigFile, error) {
return files, nil
}
func (cfg *sharedConfig) setAssumeRoleSource(origProfile string, files []sharedConfigFile) error {
var assumeRoleSrc sharedConfig
if len(cfg.AssumeRole.CredentialSource) > 0 {
// setAssumeRoleSource is only called when source_profile is found.
// If both source_profile and credential_source are set, then
// ErrSharedConfigSourceCollision will be returned
return ErrSharedConfigSourceCollision
func (cfg *sharedConfig) setFromIniFiles(profiles map[string]struct{}, profile string, files []sharedConfigFile, exOpts bool) error {
// Trim files from the list that don't exist.
var skippedFiles int
var profileNotFoundErr error
for _, f := range files {
if err := cfg.setFromIniFile(profile, f, exOpts); err != nil {
if _, ok := err.(SharedConfigProfileNotExistsError); ok {
// Ignore profiles not defined in individual files.
profileNotFoundErr = err
skippedFiles++
continue
}
return err
}
}
if skippedFiles == len(files) {
// If all files were skipped because the profile is not found, return
// the original profile not found error.
return profileNotFoundErr
}
// Multiple level assume role chains are not support
if cfg.AssumeRole.SourceProfile == origProfile {
assumeRoleSrc = *cfg
assumeRoleSrc.AssumeRole = assumeRoleConfig{}
if _, ok := profiles[profile]; ok {
// if this is the second instance of the profile the Assume Role
// options must be cleared because they are only valid for the
// first reference of a profile. The self linked instance of the
// profile only have credential provider options.
cfg.clearAssumeRoleOptions()
} else {
err := assumeRoleSrc.setFromIniFiles(cfg.AssumeRole.SourceProfile, files)
if err != nil {
// First time a profile has been seen, It must either be a assume role
// or credentials. Assert if the credential type requires a role ARN,
// the ARN is also set.
if err := cfg.validateCredentialsRequireARN(profile); err != nil {
return err
}
// Chain if profile depends of other profiles
if len(assumeRoleSrc.AssumeRole.SourceProfile) > 0 {
err := assumeRoleSrc.setAssumeRoleSource(cfg.AssumeRole.SourceProfile, files)
if err != nil {
return err
}
}
}
profiles[profile] = struct{}{}
if cfg.AssumeRole.SourceProfile == origProfile || len(assumeRoleSrc.AssumeRole.SourceProfile) == 0 {
//Check if at least either Credential Source, static creds, or credential process is set to retain credentials.
if len(assumeRoleSrc.AssumeRole.CredentialSource) == 0 && len(assumeRoleSrc.Creds.AccessKeyID) == 0 && len(assumeRoleSrc.CredentialProcess) == 0 {
return SharedConfigAssumeRoleError{RoleARN: cfg.AssumeRole.RoleARN}
}
if err := cfg.validateCredentialType(); err != nil {
return err
}
cfg.AssumeRoleSource = &assumeRoleSrc
// Link source profiles for assume roles
if len(cfg.SourceProfileName) != 0 {
// Linked profile via source_profile ignore credential provider
// options, the source profile must provide the credentials.
cfg.clearCredentialOptions()
return nil
}
func (cfg *sharedConfig) setFromIniFiles(profile string, files []sharedConfigFile) error {
// Trim files from the list that don't exist.
for _, f := range files {
if err := cfg.setFromIniFile(profile, f); err != nil {
srcCfg := &sharedConfig{}
err := srcCfg.setFromIniFiles(profiles, cfg.SourceProfileName, files, exOpts)
if err != nil {
// SourceProfile that doesn't exist is an error in configuration.
if _, ok := err.(SharedConfigProfileNotExistsError); ok {
// Ignore proviles missings
continue
err = SharedConfigAssumeRoleError{
RoleARN: cfg.RoleARN,
SourceProfile: cfg.SourceProfileName,
}
}
return err
}
if !srcCfg.hasCredentials() {
return SharedConfigAssumeRoleError{
RoleARN: cfg.RoleARN,
SourceProfile: cfg.SourceProfileName,
}
}
cfg.SourceProfile = srcCfg
}
return nil
}
// setFromFile loads the configuration from the file using
// the profile provided. A sharedConfig pointer type value is used so that
// multiple config file loadings can be chained.
// setFromFile loads the configuration from the file using the profile
// provided. A sharedConfig pointer type value is used so that multiple config
// file loadings can be chained.
//
// Only loads complete logically grouped values, and will not set fields in cfg
// for incomplete grouped values in the config. Such as credentials. For example
// if a config file only includes aws_access_key_id but no aws_secret_access_key
// the aws_access_key_id will be ignored.
func (cfg *sharedConfig) setFromIniFile(profile string, file sharedConfigFile) error {
// for incomplete grouped values in the config. Such as credentials. For
// example if a config file only includes aws_access_key_id but no
// aws_secret_access_key the aws_access_key_id will be ignored.
func (cfg *sharedConfig) setFromIniFile(profile string, file sharedConfigFile, exOpts bool) error {
section, ok := file.IniData.GetSection(profile)
if !ok {
// Fallback to to alternate profile name: profile <name>
......@@ -210,44 +224,30 @@ func (cfg *sharedConfig) setFromIniFile(profile string, file sharedConfigFile) e
}
}
// Shared Credentials
akid := section.String(accessKeyIDKey)
secret := section.String(secretAccessKey)
if len(akid) > 0 && len(secret) > 0 {
cfg.Creds = credentials.Value{
AccessKeyID: akid,
SecretAccessKey: secret,
SessionToken: section.String(sessionTokenKey),
ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", file.Filename),
}
}
if exOpts {
// Assume Role Parameters
updateString(&cfg.RoleARN, section, roleArnKey)
updateString(&cfg.ExternalID, section, externalIDKey)
updateString(&cfg.MFASerial, section, mfaSerialKey)
updateString(&cfg.RoleSessionName, section, roleSessionNameKey)
updateString(&cfg.SourceProfileName, section, sourceProfileKey)
updateString(&cfg.CredentialSource, section, credentialSourceKey)
// Assume Role
roleArn := section.String(roleArnKey)
srcProfile := section.String(sourceProfileKey)
credentialSource := section.String(credentialSourceKey)
credentialProcess := section.String(credentialProcessKey)
//Has source to make sure the Assume Role has at least either srcProfile, credential Source, or credential Process.
hasSource := len(srcProfile) > 0 || len(credentialSource) > 0 || len(credentialProcess) > 0
if len(roleArn) > 0 && hasSource {
cfg.AssumeRole = assumeRoleConfig{
RoleARN: roleArn,
SourceProfile: srcProfile,
CredentialSource: credentialSource,
ExternalID: section.String(externalIDKey),
MFASerial: section.String(mfaSerialKey),
RoleSessionName: section.String(roleSessionNameKey),
}
updateString(&cfg.Region, section, regionKey)
}
// `credential_process`
if credProc := section.String(credentialProcessKey); len(credProc) > 0 {
cfg.CredentialProcess = credProc
}
updateString(&cfg.CredentialProcess, section, credentialProcessKey)
updateString(&cfg.WebIdentityTokenFile, section, webIdentityTokenFileKey)
// Region
if v := section.String(regionKey); len(v) > 0 {
cfg.Region = v
// Shared Credentials
creds := credentials.Value{
AccessKeyID: section.String(accessKeyIDKey),
SecretAccessKey: section.String(secretAccessKey),
SessionToken: section.String(sessionTokenKey),
ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", file.Filename),
}
if creds.HasKeys() {
cfg.Creds = creds
}
// Endpoint discovery
......@@ -259,6 +259,95 @@ func (cfg *sharedConfig) setFromIniFile(profile string, file sharedConfigFile) e
return nil
}
func (cfg *sharedConfig) validateCredentialsRequireARN(profile string) error {
var credSource string
switch {
case len(cfg.SourceProfileName) != 0:
credSource = sourceProfileKey
case len(cfg.CredentialSource) != 0:
credSource = credentialSourceKey
case len(cfg.WebIdentityTokenFile) != 0:
credSource = webIdentityTokenFileKey
}
if len(credSource) != 0 && len(cfg.RoleARN) == 0 {
return CredentialRequiresARNError{
Type: credSource,
Profile: profile,
}
}
return nil
}
func (cfg *sharedConfig) validateCredentialType() error {
// Only one or no credential type can be defined.
if !oneOrNone(
len(cfg.SourceProfileName) != 0,
len(cfg.CredentialSource) != 0,
len(cfg.CredentialProcess) != 0,
len(cfg.WebIdentityTokenFile) != 0,
) {
return ErrSharedConfigSourceCollision
}
return nil
}
func (cfg *sharedConfig) hasCredentials() bool {
switch {
case len(cfg.SourceProfileName) != 0:
case len(cfg.CredentialSource) != 0:
case len(cfg.CredentialProcess) != 0:
case len(cfg.WebIdentityTokenFile) != 0:
case cfg.Creds.HasKeys():
default:
return false
}
return true
}
func (cfg *sharedConfig) clearCredentialOptions() {
cfg.CredentialSource = ""
cfg.CredentialProcess = ""
cfg.WebIdentityTokenFile = ""
cfg.Creds = credentials.Value{}
}
func (cfg *sharedConfig) clearAssumeRoleOptions() {
cfg.RoleARN = ""
cfg.ExternalID = ""
cfg.MFASerial = ""
cfg.RoleSessionName = ""
cfg.SourceProfileName = ""
}
func oneOrNone(bs ...bool) bool {
var count int
for _, b := range bs {
if b {
count++
if count > 1 {
return false
}
}
}
return true
}
// updateString will only update the dst with the value in the section key, key
// is present in the section.
func updateString(dst *string, section ini.Section, key string) {
if !section.Has(key) {
return
}
*dst = section.String(key)
}
// SharedConfigLoadError is an error for the shared config file failed to load.
type SharedConfigLoadError struct {
Filename string
......@@ -316,7 +405,8 @@ func (e SharedConfigProfileNotExistsError) Error() string {
// profile contains assume role information, but that information is invalid
// or not complete.
type SharedConfigAssumeRoleError struct {
RoleARN string
RoleARN string
SourceProfile string
}
// Code is the short id of the error.
......@@ -326,8 +416,10 @@ func (e SharedConfigAssumeRoleError) Code() string {
// Message is the description of the error
func (e SharedConfigAssumeRoleError) Message() string {
return fmt.Sprintf("failed to load assume role for %s, source profile has no shared credentials",
e.RoleARN)
return fmt.Sprintf(
"failed to load assume role for %s, source profile %s has no shared credentials",
e.RoleARN, e.SourceProfile,
)
}
// OrigErr is the underlying error that caused the failure.
......@@ -339,3 +431,36 @@ func (e SharedConfigAssumeRoleError) OrigErr() error {
func (e SharedConfigAssumeRoleError) Error() string {
return awserr.SprintError(e.Code(), e.Message(), "", nil)
}
// CredentialRequiresARNError provides the error for shared config credentials
// that are incorrectly configured in the shared config or credentials file.
type CredentialRequiresARNError struct {
// type of credentials that were configured.
Type string
// Profile name the credentials were in.
Profile string
}
// Code is the short id of the error.
func (e CredentialRequiresARNError) Code() string {
return "CredentialRequiresARNError"
}
// Message is the description of the error
func (e CredentialRequiresARNError) Message() string {
return fmt.Sprintf(
"credential type %s requires role_arn, profile %s",
e.Type, e.Profile,
)
}
// OrigErr is the underlying error that caused the failure.
func (e CredentialRequiresARNError) OrigErr() error {
return nil
}
// Error satisfies the error interface.
func (e CredentialRequiresARNError) Error() string {
return awserr.SprintError(e.Code(), e.Message(), "", nil)
}
......@@ -687,7 +687,11 @@ func (ctx *signingCtx) buildBodyDigest() error {
if !aws.IsReaderSeekable(ctx.Body) {
return fmt.Errorf("cannot use unseekable request body %T, for signed request with body", ctx.Body)
}
hash = hex.EncodeToString(makeSha256Reader(ctx.Body))
hashBytes, err := makeSha256Reader(ctx.Body)
if err != nil {
return err
}
hash = hex.EncodeToString(hashBytes)
}
if includeSHA256Header {
......@@ -734,10 +738,16 @@ func makeSha256(data []byte) []byte {
return hash.Sum(nil)
}
func makeSha256Reader(reader io.ReadSeeker) []byte {
func makeSha256Reader(reader io.ReadSeeker) (hashBytes []byte, err error) {
hash := sha256.New()
start, _ := reader.Seek(0, sdkio.SeekCurrent)
defer reader.Seek(start, sdkio.SeekStart)
start, err := reader.Seek(0, sdkio.SeekCurrent)
if err != nil {
return nil, err
}
defer func() {
// ensure error is return if unable to seek back to start of payload.
_, err = reader.Seek(start, sdkio.SeekStart)
}()
// Use CopyN to avoid allocating the 32KB buffer in io.Copy for bodies
// smaller than 32KB. Fall back to io.Copy if we fail to determine the size.
......@@ -748,7 +758,7 @@ func makeSha256Reader(reader io.ReadSeeker) []byte {
io.CopyN(hash, reader, size)
}
return hash.Sum(nil)
return hash.Sum(nil), nil
}
const doubleSpace = " "
......
......@@ -5,4 +5,4 @@ package aws
const SDKName = "aws-sdk-go"
// SDKVersion is the version of this SDK
const SDKVersion = "1.20.19"
const SDKVersion = "1.21.7"
......@@ -5420,12 +5420,6 @@ func (c *IAM) GetAccessKeyLastUsedRequest(input *GetAccessKeyLastUsedInput) (req
//
// See the AWS API reference guide for AWS Identity and Access Management's
// API operation GetAccessKeyLastUsed for usage and error information.
//
// Returned Error Codes:
// * ErrCodeNoSuchEntityException "NoSuchEntity"
// The request was rejected because it referenced a resource entity that does
// not exist. The error message describes the resource.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/iam-2010-05-08/GetAccessKeyLastUsed
func (c *IAM) GetAccessKeyLastUsed(input *GetAccessKeyLastUsedInput) (*GetAccessKeyLastUsedOutput, error) {
req, out := c.GetAccessKeyLastUsedRequest(input)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment