Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/stable-website'
Browse files Browse the repository at this point in the history
  • Loading branch information
jocgir committed Aug 14, 2018
2 parents ffc7c0a + e56ded8 commit 2fe6ce2
Show file tree
Hide file tree
Showing 98 changed files with 23,423 additions and 2,685 deletions.
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,34 @@
## 1.31.0 (August 09, 2018)

FEATURES:

* **New Data Source:** `aws_db_cluster_snapshot` ([#4526](https://github.com/terraform-providers/terraform-provider-aws/issues/4526))
* **New Resource:** `aws_db_cluster_snapshot` ([#4526](https://github.com/terraform-providers/terraform-provider-aws/issues/4526))
* **New Resource:** `aws_neptune_event_subscription` ([#5480](https://github.com/terraform-providers/terraform-provider-aws/issues/5480))
* **New Resource:** `aws_storagegateway_cache` ([#5282](https://github.com/terraform-providers/terraform-provider-aws/issues/5282))
* **New Resource:** `aws_storagegateway_smb_file_share` ([#5276](https://github.com/terraform-providers/terraform-provider-aws/issues/5276))

ENHANCEMENTS:

* provider: Allow provider configuration AssumeRoleARN and sts:GetCallerIdentity credential validation call to shortcut account ID and partition lookup ([#5177](https://github.com/terraform-providers/terraform-provider-aws/issues/5177))
* provider: Improved output for multiple error handler ([#5442](https://github.com/terraform-providers/terraform-provider-aws/issues/5442))
* data-source/aws_instance: Add `arn` attribute ([#5432](https://github.com/terraform-providers/terraform-provider-aws/issues/5432))
* resource/aws_elasticsearch_domain: Support `ES_APPLICATION_LOGS` `log_type` in plan-time validation ([#5474](https://github.com/terraform-providers/terraform-provider-aws/issues/5474))
* resource/aws_instance: Add `arn` attribute ([#5432](https://github.com/terraform-providers/terraform-provider-aws/issues/5432))
* resource/aws_storagegateway_gateway: Add `smb_active_directory_settings` and `smb_guest_password` arguments ([#5269](https://github.com/terraform-providers/terraform-provider-aws/issues/5269))

BUG FIXES:

* provider: Prefer `USERPROFILE` over `HOMEPATH` for home directory expansion on Windows ([#5443](https://github.com/terraform-providers/terraform-provider-aws/issues/5443))
* resource/aws_ami_copy: Prevent `ena_support` attribute incorrectly reporting force new resource ([#5433](https://github.com/terraform-providers/terraform-provider-aws/issues/5433))
* resource/aws_ami_from_instance: Prevent `ena_support` attribute incorrectly reporting force new resource ([#5433](https://github.com/terraform-providers/terraform-provider-aws/issues/5433))
* resource/aws_elasticsearch_domain: Prevent crash when missing `AutomatedSnapshotStartHour` in API response ([#5451](https://github.com/terraform-providers/terraform-provider-aws/issues/5451))
* resource/aws_elasticsearch_domain: Suppress plan differences for `dedicated_master_count` and `dedicated_master_type` when `dedicated_master_enabled` is disabled ([#5423](https://github.com/terraform-providers/terraform-provider-aws/issues/5423))
* resource/aws_rds_cluster: Prevent error when restoring cluster from snapshot with tagging enabled ([#5479](https://github.com/terraform-providers/terraform-provider-aws/issues/5479))
* resource/aws_ssm_maintenance_window: Properly recreate resource when deleted outside Terraform ([#5416](https://github.com/terraform-providers/terraform-provider-aws/issues/5416))
* resource/aws_ssm_patch_baseline: Properly recreate resource when deleted outside Terraform ([#5438](https://github.com/terraform-providers/terraform-provider-aws/issues/5438))
* resource/aws_vpn_gateway: Allow legacy `amazon_side_asn` in plan-time validation (ASNs 10124 and 17493) ([#5441](https://github.com/terraform-providers/terraform-provider-aws/issues/5441))

## 1.30.0 (August 02, 2018)

FEATURES:
Expand Down
158 changes: 102 additions & 56 deletions aws/auth_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,91 +18,137 @@ import (
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/aws/aws-sdk-go/service/sts"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/go-cleanhttp"
"github.com/hashicorp/go-multierror"
)

func GetAccountID(iamconn *iam.IAM, stsconn *sts.STS, authProviderName string) (string, error) {
var errors error
// If we have creds from instance profile, we can use metadata API
func GetAccountIDAndPartition(iamconn *iam.IAM, stsconn *sts.STS, authProviderName string) (string, string, error) {
var accountID, partition string
var err, errors error

if authProviderName == ec2rolecreds.ProviderName {
log.Println("[DEBUG] Trying to get account ID via AWS Metadata API")
accountID, partition, err = GetAccountIDAndPartitionFromEC2Metadata()
} else {
accountID, partition, err = GetAccountIDAndPartitionFromIAMGetUser(iamconn)
}
if accountID != "" {
return accountID, partition, nil
}
errors = multierror.Append(errors, err)

cfg := &aws.Config{}
setOptionalEndpoint(cfg)
sess, err := session.NewSession(cfg)
if err != nil {
return "", errwrap.Wrapf("Error creating AWS session: {{err}}", err)
}
accountID, partition, err = GetAccountIDAndPartitionFromSTSGetCallerIdentity(stsconn)
if accountID != "" {
return accountID, partition, nil
}
errors = multierror.Append(errors, err)

metadataClient := ec2metadata.New(sess)
info, err := metadataClient.IAMInfo()
if err == nil {
return parseAccountIDFromArn(info.InstanceProfileArn)
}
log.Printf("[DEBUG] Failed to get account info from metadata service: %s", err)
errors = multierror.Append(errors, err)
accountID, partition, err = GetAccountIDAndPartitionFromIAMListRoles(iamconn)
if accountID != "" {
return accountID, partition, nil
}
errors = multierror.Append(errors, err)

return accountID, partition, errors
}

func GetAccountIDAndPartitionFromEC2Metadata() (string, string, error) {
log.Println("[DEBUG] Trying to get account information via EC2 Metadata")

cfg := &aws.Config{}
setOptionalEndpoint(cfg)
sess, err := session.NewSession(cfg)
if err != nil {
return "", "", fmt.Errorf("error creating EC2 Metadata session: %s", err)
}

metadataClient := ec2metadata.New(sess)
info, err := metadataClient.IAMInfo()
if err != nil {
// We can end up here if there's an issue with the instance metadata service
// or if we're getting credentials from AdRoll's Hologram (in which case IAMInfo will
// error out). In any event, if we can't get account info here, we should try
// the other methods available.
// If we have creds from something that looks like an IAM instance profile, but
// we were unable to retrieve account info from the instance profile, it's probably
// a safe assumption that we're not an IAM user
} else {
// Creds aren't from an IAM instance profile, so try try iam:GetUser
log.Println("[DEBUG] Trying to get account ID via iam:GetUser")
outUser, err := iamconn.GetUser(nil)
if err == nil {
return parseAccountIDFromArn(*outUser.User.Arn)
}
errors = multierror.Append(errors, err)
awsErr, ok := err.(awserr.Error)
// error out).
err = fmt.Errorf("failed getting account information via EC2 Metadata IAM information: %s", err)
log.Printf("[DEBUG] %s", err)
return "", "", err
}

return parseAccountIDAndPartitionFromARN(info.InstanceProfileArn)
}

func GetAccountIDAndPartitionFromIAMGetUser(iamconn *iam.IAM) (string, string, error) {
log.Println("[DEBUG] Trying to get account information via iam:GetUser")

output, err := iamconn.GetUser(&iam.GetUserInput{})
if err != nil {
// AccessDenied and ValidationError can be raised
// if credentials belong to federated profile, so we ignore these
if !ok || (awsErr.Code() != "AccessDenied" && awsErr.Code() != "ValidationError" && awsErr.Code() != "InvalidClientTokenId") {
return "", fmt.Errorf("Failed getting account ID via 'iam:GetUser': %s", err)
if isAWSErr(err, "AccessDenied", "") {
return "", "", nil
}
log.Printf("[DEBUG] Getting account ID via iam:GetUser failed: %s", err)
if isAWSErr(err, "InvalidClientTokenId", "") {
return "", "", nil
}
if isAWSErr(err, "ValidationError", "") {
return "", "", nil
}
err = fmt.Errorf("failed getting account information via iam:GetUser: %s", err)
log.Printf("[DEBUG] %s", err)
return "", "", err
}

// Then try STS GetCallerIdentity
log.Println("[DEBUG] Trying to get account ID via sts:GetCallerIdentity")
outCallerIdentity, err := stsconn.GetCallerIdentity(&sts.GetCallerIdentityInput{})
if err == nil {
return parseAccountIDFromArn(*outCallerIdentity.Arn)
if output == nil || output.User == nil {
err = errors.New("empty iam:GetUser response")
log.Printf("[DEBUG] %s", err)
return "", "", err
}
log.Printf("[DEBUG] Getting account ID via sts:GetCallerIdentity failed: %s", err)
errors = multierror.Append(errors, err)

// Then try IAM ListRoles
log.Println("[DEBUG] Trying to get account ID via iam:ListRoles")
outRoles, err := iamconn.ListRoles(&iam.ListRolesInput{
return parseAccountIDAndPartitionFromARN(aws.StringValue(output.User.Arn))
}

func GetAccountIDAndPartitionFromIAMListRoles(iamconn *iam.IAM) (string, string, error) {
log.Println("[DEBUG] Trying to get account information via iam:ListRoles")

output, err := iamconn.ListRoles(&iam.ListRolesInput{
MaxItems: aws.Int64(int64(1)),
})
if err != nil {
log.Printf("[DEBUG] Failed to get account ID via iam:ListRoles: %s", err)
errors = multierror.Append(errors, err)
return "", fmt.Errorf("Failed getting account ID via all available methods. Errors: %s", errors)
err = fmt.Errorf("failed getting account information via iam:ListRoles: %s", err)
log.Printf("[DEBUG] %s", err)
return "", "", err
}

if output == nil || len(output.Roles) < 1 {
err = fmt.Errorf("empty iam:ListRoles response")
log.Printf("[DEBUG] %s", err)
return "", "", err
}

return parseAccountIDAndPartitionFromARN(aws.StringValue(output.Roles[0].Arn))
}

func GetAccountIDAndPartitionFromSTSGetCallerIdentity(stsconn *sts.STS) (string, string, error) {
log.Println("[DEBUG] Trying to get account information via sts:GetCallerIdentity")

output, err := stsconn.GetCallerIdentity(&sts.GetCallerIdentityInput{})
if err != nil {
return "", "", fmt.Errorf("error calling sts:GetCallerIdentity: %s", err)
}

if len(outRoles.Roles) < 1 {
err = fmt.Errorf("Failed to get account ID via iam:ListRoles: No roles available")
if output == nil || output.Arn == nil {
err = errors.New("empty sts:GetCallerIdentity response")
log.Printf("[DEBUG] %s", err)
errors = multierror.Append(errors, err)
return "", fmt.Errorf("Failed getting account ID via all available methods. Errors: %s", errors)
return "", "", err
}

return parseAccountIDFromArn(*outRoles.Roles[0].Arn)
return parseAccountIDAndPartitionFromARN(aws.StringValue(output.Arn))
}

func parseAccountIDFromArn(inputARN string) (string, error) {
func parseAccountIDAndPartitionFromARN(inputARN string) (string, string, error) {
arn, err := arn.Parse(inputARN)
if err != nil {
return "", fmt.Errorf("Unable to parse ID from invalid ARN: %q", arn)
return "", "", fmt.Errorf("error parsing ARN (%s): %s", inputARN, err)
}
return arn.AccountID, nil
return arn.AccountID, arn.Partition, nil
}

// This function is responsible for reading credentials from the
Expand Down
Loading

0 comments on commit 2fe6ce2

Please sign in to comment.