Skip to content

Commit

Permalink
Run credentials validation only once (#2949)
Browse files Browse the repository at this point in the history
This should address the error duplication reported in
#2285 as suggested by @t0yv0.

We now have a global counter which guard the credentials check and makes
sure we only run it once.

For testing, I ran a few programs both with and without errors and it
does seem to do the right thing.


```
Previewing update (dedev)

View in Browser (Ctrl+O): https://app.pulumi.com/venelin-pulumi-corp/aws_bucket_go/dedev/previews/88831526-f63f-42f2-98d9-957fbea78fc0

     Type                     Name                 Plan     Info
     pulumi:pulumi:Stack      aws_bucket_go-dedev           4 war
     └─ pulumi:providers:aws  default                       1 err

Diagnostics:
  pulumi:providers:aws (default):
    error: rpc error: code = Unknown desc = unable to validate AWS credentials.
    Details: No valid credential sources found. Please see https://www.pulumi.com/registry/packages/aws/installation-configuration/
    for more information about providing credentials.

    Error: failed to refresh cached credentials, failed to read cached SSO token file, open /Users/vvm/.aws/sso/cache/55357933a7310d2db90c3fa1ed0970a7bb34ed39.json: no such file or directory

    Make sure you have set your AWS region, e.g. `pulumi config set aws:region us-west-2`.

  pulumi:pulumi:Stack (aws_bucket_go-dedev):
    warning: using pulumi-language-go from $PATH at /opt/homebrew/bin/pulumi-language-go
    warning: using pulumi-resource-aws from $PATH at /Users/vvm/code/pulumi-aws/bin/pulumi-resource-aws
    warning: using pulumi-language-go from $PATH at /opt/homebrew/bin/pulumi-language-go
    warning: using pulumi-resource-aws from $PATH at /Users/vvm/code/pulumi-aws/bin/pulumi-resource-aws
```
  • Loading branch information
VenelinMartinov authored Nov 3, 2023
2 parents 5d0f69c + 9d7fc9c commit c776901
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 13 deletions.
10 changes: 10 additions & 0 deletions examples/bucket-yaml/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: bucket-yaml
runtime: yaml
description: A minimal Pulumi YAML program
resources:
bucket:
type: aws:s3:Bucket
properties:
tags:
Environment: Dev
Name: My bucket
30 changes: 30 additions & 0 deletions examples/diagnostic_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package examples

import (
"bytes"
"path/filepath"
"strings"
"testing"

"github.com/pulumi/pulumi/pkg/v3/testing/integration"
"github.com/stretchr/testify/assert"
)

func TestCredentialsErrorNotDuplicated(t *testing.T) {
var outputBuf bytes.Buffer
test := integration.ProgramTestOptions{
Dir: filepath.Join(getCwd(t), "bucket-yaml"),
Quick: true,
Stderr: &outputBuf,
ExpectFailure: true,
Env: []string{
"AWS_ACCESS_KEY_ID=INVALID",
"AWS_SECRET_ACCESS_KEY=INVALID",
},
ExtraRuntimeValidation: func(t *testing.T, stackInfo integration.RuntimeValidationStackInfo) {
assert.Equal(t, 1, strings.Count(outputBuf.String(), "The security token included in the request is invalid"))
},
}

integration.ProgramTest(t, &test)
}
38 changes: 25 additions & 13 deletions provider/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"path/filepath"
"strconv"
"strings"
"sync"
"unicode"

"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
Expand Down Expand Up @@ -531,19 +532,7 @@ func arrayValue(vars resource.PropertyMap, prop resource.PropertyKey, envs []str
return vals
}

// preConfigureCallback validates that AWS credentials can be successfully discovered. This emulates the credentials
// configuration subset of `github.com/terraform-providers/terraform-provider-aws/aws.providerConfigure`. We do this
// before passing control to the TF provider to ensure we can report actionable errors.
func preConfigureCallback(vars resource.PropertyMap, c shim.ResourceConfig) error {
skipCredentialsValidation := boolValue(vars, "skipCredentialsValidation",
[]string{"AWS_SKIP_CREDENTIALS_VALIDATION"})

// if we skipCredentialsValidation then we don't need to do anything in
// preConfigureCallback as this is an explicit operation
if skipCredentialsValidation {
return nil
}

func validateCredentials(vars resource.PropertyMap, c shim.ResourceConfig) error {
config := &awsbase.Config{
AccessKey: stringValue(vars, "accessKey", []string{"AWS_ACCESS_KEY_ID"}),
SecretKey: stringValue(vars, "secretKey", []string{"AWS_SECRET_ACCESS_KEY"}),
Expand Down Expand Up @@ -626,6 +615,29 @@ func preConfigureCallback(vars resource.PropertyMap, c shim.ResourceConfig) erro
return nil
}

// We should only run the validation once to avoid duplicating the reported errors.
var credentialsValidationOnce sync.Once

// preConfigureCallback validates that AWS credentials can be successfully discovered. This emulates the credentials
// configuration subset of `github.com/terraform-providers/terraform-provider-aws/aws.providerConfigure`. We do this
// before passing control to the TF provider to ensure we can report actionable errors.
func preConfigureCallback(vars resource.PropertyMap, c shim.ResourceConfig) error {
skipCredentialsValidation := boolValue(vars, "skipCredentialsValidation",
[]string{"AWS_SKIP_CREDENTIALS_VALIDATION"})

// if we skipCredentialsValidation then we don't need to do anything in
// preConfigureCallback as this is an explicit operation
if skipCredentialsValidation {
return nil
}

var err error
credentialsValidationOnce.Do(func() {
err = validateCredentials(vars, c)
})
return err
}

// managedByPulumi is a default used for some managed resources, in the absence of something more meaningful.
var managedByPulumi = &tfbridge.DefaultInfo{Value: "Managed by Pulumi"}

Expand Down

0 comments on commit c776901

Please sign in to comment.