From 74094056ef78dbfe426f52fcb1ca48a4b43723e6 Mon Sep 17 00:00:00 2001 From: Shantanu Kotambkar <52007797+skotambkar@users.noreply.github.com> Date: Fri, 20 Sep 2019 10:55:38 -0700 Subject: [PATCH] aws: Remove plugin credential providers (#391) Removing plugin credential provider from the v2 SDK developer preview. This feature may be made available as a separate module. --- CHANGELOG_PENDING.md | 5 + aws/plugincreds/doc_1_7.go | 5 - aws/plugincreds/provider.go | 190 ------------------ aws/plugincreds/provider_test.go | 77 ------- example/aws/credentials/plugincreds/README.md | 49 ----- example/aws/credentials/plugincreds/main.go | 85 -------- .../credentials/plugincreds/plugin/plugin.go | 61 ------ 7 files changed, 5 insertions(+), 467 deletions(-) delete mode 100644 aws/plugincreds/doc_1_7.go delete mode 100644 aws/plugincreds/provider.go delete mode 100644 aws/plugincreds/provider_test.go delete mode 100644 example/aws/credentials/plugincreds/README.md delete mode 100644 example/aws/credentials/plugincreds/main.go delete mode 100644 example/aws/credentials/plugincreds/plugin/plugin.go diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 4eecca5078a..75735d4540c 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -1,6 +1,11 @@ Services --- +Deprecations +--- +* `aws`: Removes plugin credential provider ([#391](https://github.com/aws/aws-sdk-go-v2/pull/391)) + * Removing plugin credential provider from the v2 SDK developer preview. This feature may be made available as a separate module. + SDK Features --- diff --git a/aws/plugincreds/doc_1_7.go b/aws/plugincreds/doc_1_7.go deleted file mode 100644 index 5b269feeba6..00000000000 --- a/aws/plugincreds/doc_1_7.go +++ /dev/null @@ -1,5 +0,0 @@ -// +build !go1.8 - -// Package plugincreds provides usage of Go plugins for providing credentials -// to the SDK. Only available with Go 1.8 and above. -package plugincreds diff --git a/aws/plugincreds/provider.go b/aws/plugincreds/provider.go deleted file mode 100644 index cae8142c362..00000000000 --- a/aws/plugincreds/provider.go +++ /dev/null @@ -1,190 +0,0 @@ -// +build go1.8 - -/* -Package plugincreds implements a credentials provider sourced from a Go -plugin. This package allows you to use a Go plugin to retrieve AWS credentials -for the SDK to use for service API calls. - -As of Go 1.8 plugins are only supported on the Linux platform. - -Plugin Symbol Name - -The "AWSSDKRetrieveCredentials" is the symbol name that will be used to -lookup the credentials provider getter from the plugin. If you want to use a -custom symbol name you should use GetRetrieveFnByName to lookup the -symbol by a custom name. - -This symbol is a function that returns two additional functions. One to -retrieve the credentials, and another to determine if the credentials have -expired. - -Plugin Symbol Signature - -The plugin credential provider requires the symbol to match the -following signature. - - func() (key, secret, token string, exp time.Time, err error) - -Plugin Implementation Exmaple - -The following is an example implementation of a SDK credential provider using -the plugin provider in this package. See the SDK's example/aws/credential/plugincreds/plugin -folder for a runnable example of this. - - func main() {} - - var myCredProvider provider - - // Build: go build -o plugin.so -buildmode=plugin plugin.go - func init() { - // Initialize a mock credential provider with stubs - myCredProvider = provider{"a","b","c"} - } - - // AWSSDKRetrieveCredentials is the symbol SDK will lookup and use to - // retrieve AWS credentials with. - func AWSSDKRetrieveCredentials() (key, secret, token string, exp time.Time, err error) { - key, secret, token, err = getCreds() - if err != nil { - return "", "", "", time.Time{}, err - } - - return key, secrete, token, time.Now().Add(2 * time.Hour), nil - } - - func getCreds() (key, secret, token string, err error){ - // Get credentials - return key, secret, token, err - } - -Configuring SDK for Plugin Credentials - -To configure the SDK to use a plugin's credential provider you'll need to first -open the plugin file using the plugin standard library package. Once you have a -handle to the plugin you can use the NewCredentials function of this package to -create a new credentials.Credentials value that can be set as the credentials -loader of a Session or Config. See the SDK's example/aws/credential/plugincreds -folder for a runnable example of this. - - // Open plugin, and load it into the process. - p, err := plugin.Open("somefile.so") - if err != nil { - return nil, err - } - - // Create a new Credentials value which will source the provider's Retrieve - // and IsExpired functions from the plugin. - creds, err := plugincreds.New(p) - if err != nil { - return nil, err - } - - cfg.Credentails = creds -*/ -package plugincreds - -import ( - "fmt" - "plugin" - "time" - - "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/aws/awserr" -) - -// ProviderSymbolName the symbol name the SDK will use to retrieve the -// credentials from. -const ProviderSymbolName = `AWSSDKRetrieveCredentials` - -// ProviderName is the name this credentials provider will label any returned -// credentials Value with. -const ProviderName = `PluginCredentialsProvider` - -const ( - // ErrCodeLookupSymbolError failed to lookup symbol - ErrCodeLookupSymbolError = "LookupSymbolError" - - // ErrCodeInvalidSymbolError symbol invalid - ErrCodeInvalidSymbolError = "InvalidSymbolError" - - // ErrCodePluginRetrieveNil Retrieve function was nil - ErrCodePluginRetrieveNil = "PluginRetrieveNilError" - - // ErrCodePluginIsExpiredNil IsExpired Function was nil - ErrCodePluginIsExpiredNil = "PluginIsExpiredNilError" - - // ErrCodePluginProviderRetrieve plugin provider's retrieve returned error - ErrCodePluginProviderRetrieve = "PluginProviderRetrieveError" -) - -// Provider is the credentials provider that will use the plugin provided -// Retrieve and IsExpired functions to retrieve credentials. -type Provider struct { - aws.SafeCredentialsProvider -} - -// New returns a new Credentials loader using the plugin provider. -// If the symbol isn't found or is invalid in the plugin an error will be -// returned. -func New(p *plugin.Plugin) (*Provider, error) { - fn, err := GetRetrieveFn(p) - if err != nil { - return nil, err - } - - provider := &Provider{} - provider.RetrieveFn = buildRetrieveFn(fn) - - return provider, nil -} - -func buildRetrieveFn(fn func() (k, s, t string, ext time.Time, err error)) func() (aws.Credentials, error) { - return func() (aws.Credentials, error) { - k, s, t, exp, err := fn() - if err != nil { - return aws.Credentials{}, awserr.New(ErrCodePluginProviderRetrieve, - "failed to retrieve credentials with plugin provider", err) - } - - creds := aws.Credentials{ - AccessKeyID: k, - SecretAccessKey: s, - SessionToken: t, - Source: ProviderName, - - CanExpire: !exp.IsZero(), - Expires: exp, - } - - return creds, nil - } -} - -// GetRetrieveFn returns the plugin's Retrieve and IsExpired functions -// returned by the plugin's credential provider getter. -// -// Uses ProviderSymbolName as the symbol name when lookup up the symbol. If you -// want to use a different symbol name, use GetRetrieveFnByName. -func GetRetrieveFn(p *plugin.Plugin) (func() (key, secret, token string, exp time.Time, err error), error) { - return GetRetrieveFnByName(p, ProviderSymbolName) -} - -// GetRetrieveFnByName returns the plugin's Retrieve and IsExpired functions -// returned by the plugin's credential provider getter. -// -// Same as GetRetrieveFn, but takes a custom symbolName to lookup with. -func GetRetrieveFnByName(p *plugin.Plugin, symbolName string) (func() (key, secret, token string, exp time.Time, err error), error) { - sym, err := p.Lookup(symbolName) - if err != nil { - return nil, awserr.New(ErrCodeLookupSymbolError, - fmt.Sprintf("failed to lookup %s plugin provider symbol", symbolName), err) - } - - fn, ok := sym.(func() (key, secret, token string, exp time.Time, err error)) - if !ok { - return nil, awserr.New(ErrCodeInvalidSymbolError, - fmt.Sprintf("symbol %T, does not match the 'func() (key, secret, token string, exp time.Time, err error)' type", sym), nil) - } - - return fn, nil -} diff --git a/aws/plugincreds/provider_test.go b/aws/plugincreds/provider_test.go deleted file mode 100644 index b385a61b148..00000000000 --- a/aws/plugincreds/provider_test.go +++ /dev/null @@ -1,77 +0,0 @@ -// +build go1.8,awsinclude - -package plugincreds - -import ( - "fmt" - "testing" - "time" - - "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/aws/awserr" - "github.com/aws/aws-sdk-go-v2/internal/sdk" -) - -func TestProvider_Passthrough(t *testing.T) { - p := Provider{} - p.RetrieveFn = buildRetrieveFn( - func() (k, s, t string, ext time.Time, err error) { - return "key", "secret", "session", - sdk.NowTime().Add(2 * time.Hour), - nil - }, - ) - - creds, err := p.Retrieve() - if err != nil { - t.Fatalf("expect no error, got %v", err) - } - - if e, a := "key", creds.AccessKeyID; e != a { - t.Errorf("expect %v, got %v", e, a) - } - if e, a := "secret", creds.SecretAccessKey; e != a { - t.Errorf("expect %v, got %v", e, a) - } - if e, a := "session", creds.SessionToken; e != a { - t.Errorf("expect %v, got %v", e, a) - } - if e, a := true, creds.CanExpire; e != a { - t.Errorf("expect %v, got %v", e, a) - } - if creds.Expired() { - t.Errorf("expect not to be expired") - } -} - -func TestProvider_Error(t *testing.T) { - expectErr := fmt.Errorf("expect error") - - p := Provider{} - p.RetrieveFn = buildRetrieveFn( - func() (k, s, t string, ext time.Time, err error) { - return "", "", "", - time.Time{}, - expectErr - }, - ) - - creds, err := p.Retrieve() - if err == nil { - t.Fatalf("expect error, got none") - } - - aerr := err.(awserr.Error) - if e, a := ErrCodePluginProviderRetrieve, aerr.Code(); e != a { - t.Errorf("expect %s error code, got %s", e, a) - } - - if e, a := expectErr, aerr.OrigErr(); e != a { - t.Errorf("expect %v cause error, got %v", e, a) - } - - expect := aws.Credentials{} - if expect != creds { - t.Errorf("expect %+v credentials, got %+v", expect, creds) - } -} diff --git a/example/aws/credentials/plugincreds/README.md b/example/aws/credentials/plugincreds/README.md deleted file mode 100644 index 47c6ab34818..00000000000 --- a/example/aws/credentials/plugincreds/README.md +++ /dev/null @@ -1,49 +0,0 @@ -Retrieve Credentials with Go Plugin -=== - -This example demonstrates how you can take advantage of Go 1.8's new Plugin -functionality to retrieve AWS credentials dynamically from a plugin compiled -separate from your application. - -Usage ---- - -Example Plugin ---- - -You can find the plugin at `plugin/plugin.go` nested within this example. The plugin -demonstrates what symbol the SDK will use when lookup up the credential provider -and the type signature that needs to be implemented. - -Compile the plugin with: - - go build -tags example -o myPlugin.so -buildmode=plugin plugin/plugin.go - -JSON Credentials File ---- - -This example plugin will read the credentials from a JSON file pointed to by -the `PLUGIN_CREDS_FILE` environment variable. The contents of the file are -the credentials, Key, Secret, and Token. The `Token` filed does not need to be -set if your credentials do not have one. - -```json -{ - "Key": "MyAWSCredAccessKeyID", - "Secret": "MyAWSCredSecretKey", - "Token": "MyAWSCredToken" -} -``` - -Example Application ---- - -The `main.go` file in this folder demonstrates how you can configure the SDK to -use a plugin to retrieve credentials with. - -Compile and run application: - - go build -tags example -o myApp main.go - - PLUGIN_CREDS_FILE=pathToCreds.json ./myApp myPlugin.so myBucket myObjectKey - diff --git a/example/aws/credentials/plugincreds/main.go b/example/aws/credentials/plugincreds/main.go deleted file mode 100644 index 956b3495f9c..00000000000 --- a/example/aws/credentials/plugincreds/main.go +++ /dev/null @@ -1,85 +0,0 @@ -// +build example,go18 - -package main - -import ( - "context" - "fmt" - "os" - "plugin" - - "github.com/aws/aws-sdk-go-v2/aws" - "github.com/aws/aws-sdk-go-v2/aws/endpoints" - "github.com/aws/aws-sdk-go-v2/aws/external" - "github.com/aws/aws-sdk-go-v2/aws/plugincreds" - "github.com/aws/aws-sdk-go-v2/service/s3" - "github.com/aws/aws-sdk-go-v2/service/s3/s3manager" -) - -// Example application which loads a Go Plugin file, and uses the credential -// provider defined within the plugin to get credentials for making a S3 -// request. -// -// The example will derive the bucket's region automatically if a AWS_REGION -// environment variable is not defined. -// -// Build: -// go build -tags example -o myApp main.go -// -// Usage: -// ./myApp -func main() { - if len(os.Args) < 4 { - exitErrorf("Usage: myApp , ") - } - - pluginFilename := os.Args[1] - bucket := os.Args[2] - key := os.Args[3] - - // Open plugin, and load it into the process. - p, err := plugin.Open(pluginFilename) - if err != nil { - exitErrorf("failed to open plugin, %s, %v", pluginFilename, err) - } - - // Create a new Credentials value which will source the provider's Retrieve - // and IsExpired functions from the plugin. - creds, err := plugincreds.NewCredentials(p) - if err != nil { - exitErrorf("failed to load plugin provider, %v", err) - } - - // Example to load the config and set with the newly created credentials that - // will be sourced using the plugin's functionality. - cfg, err := external.LoadDefaultAWSConfig() - if err != nil { - exitErrorf("failed to load config, %v", err) - } - cfg.Credentials = creds - - // If the region is not available attempt to derive the bucket's region - // from a query to S3 for the bucket's metadata - region := cfg.Region - if len(region) == 0 { - region, err = s3manager.GetBucketRegion(context.Background(), cfg, bucket, endpoints.UsEast1RegionID) - if err != nil { - exitErrorf("failed to get bucket region, %v", err) - } - } - - // Create the S3 service client for the target region - svc := s3.New(cfg, aws.NewConfig().WithRegion(region)) - - // Get the object's details - result, err := svc.HeadObject(&s3.HeadObjectInput{ - Bucket: aws.String(bucket), - Key: aws.String(key), - }) - fmt.Println(result, err) -} - -func exitErrorf(format string, args ...interface{}) { - fmt.Fprintf(os.Stderr, format+"\n", args...) - os.Exit(1) -} diff --git a/example/aws/credentials/plugincreds/plugin/plugin.go b/example/aws/credentials/plugincreds/plugin/plugin.go deleted file mode 100644 index dabfa1f6b01..00000000000 --- a/example/aws/credentials/plugincreds/plugin/plugin.go +++ /dev/null @@ -1,61 +0,0 @@ -// +build example,go18 - -package main - -import ( - "encoding/json" - "os" - - "github.com/pkg/errors" -) - -// Example plugin that will retrieve credentials from a JSON file that the -// "PLUGIN_CREDS_FILE" environment variable points to -// -// Build with: -// go build -tags example -o plugin.so -buildmode=plugin plugin.go -func main() {} - -var myCredProvider provider - -func init() { - // Initialize a mock credential provider with stubs - myCredProvider = provider{Filename: os.Getenv("PLUGIN_CREDS_FILE")} -} - -// GetAWSSDKCredentialProvider is the symbol SDK will lookup and use to -// get the credential provider's retrieve and isExpired functions. -func GetAWSSDKCredentialProvider() (func() (key, secret, token string, err error), func() bool) { - return myCredProvider.Retrieve, myCredProvider.IsExpired -} - -// mock implementation of a type that returns retrieves credentials and -// returns if they have expired. -type provider struct { - Filename string - - loaded bool -} - -func (p *provider) Retrieve() (key, secret, token string, err error) { - f, err := os.Open(p.Filename) - if err != nil { - return "", "", "", errors.Wrapf(err, "failed to open credentials file, %q", p.Filename) - } - decoder := json.NewDecoder(f) - - creds := struct { - Key, Secret, Token string - }{} - - if err := decoder.Decode(&creds); err != nil { - return "", "", "", errors.Wrap(err, "failed to decode credentials file") - } - - p.loaded = true - return creds.Key, creds.Secret, creds.Token, nil -} - -func (p *provider) IsExpired() bool { - return !p.loaded -}