summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/aws/aws-sdk-go/aws/credentials/processcreds/provider.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/aws/aws-sdk-go/aws/credentials/processcreds/provider.go')
-rw-r--r--vendor/github.com/aws/aws-sdk-go/aws/credentials/processcreds/provider.go425
1 files changed, 0 insertions, 425 deletions
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/credentials/processcreds/provider.go b/vendor/github.com/aws/aws-sdk-go/aws/credentials/processcreds/provider.go
deleted file mode 100644
index 1980c8c14..000000000
--- a/vendor/github.com/aws/aws-sdk-go/aws/credentials/processcreds/provider.go
+++ /dev/null
@@ -1,425 +0,0 @@
-/*
-Package processcreds is a credential Provider to retrieve `credential_process`
-credentials.
-
-WARNING: The following describes a method of sourcing credentials from an external
-process. This can potentially be dangerous, so proceed with caution. Other
-credential providers should be preferred if at all possible. If using this
-option, you should make sure that the config file is as locked down as possible
-using security best practices for your operating system.
-
-You can use credentials from a `credential_process` in a variety of ways.
-
-One way is to setup your shared config file, located in the default
-location, with the `credential_process` key and the command you want to be
-called. You also need to set the AWS_SDK_LOAD_CONFIG environment variable
-(e.g., `export AWS_SDK_LOAD_CONFIG=1`) to use the shared config file.
-
- [default]
- credential_process = /command/to/call
-
-Creating a new session will use the credential process to retrieve credentials.
-NOTE: If there are credentials in the profile you are using, the credential
-process will not be used.
-
- // Initialize a session to load credentials.
- sess, _ := session.NewSession(&aws.Config{
- Region: aws.String("us-east-1")},
- )
-
- // Create S3 service client to use the credentials.
- svc := s3.New(sess)
-
-Another way to use the `credential_process` method is by using
-`credentials.NewCredentials()` and providing a command to be executed to
-retrieve credentials:
-
- // Create credentials using the ProcessProvider.
- creds := processcreds.NewCredentials("/path/to/command")
-
- // Create service client value configured for credentials.
- svc := s3.New(sess, &aws.Config{Credentials: creds})
-
-You can set a non-default timeout for the `credential_process` with another
-constructor, `credentials.NewCredentialsTimeout()`, providing the timeout. To
-set a one minute timeout:
-
- // Create credentials using the ProcessProvider.
- creds := processcreds.NewCredentialsTimeout(
- "/path/to/command",
- time.Duration(500) * time.Millisecond)
-
-If you need more control, you can set any configurable options in the
-credentials using one or more option functions. For example, you can set a two
-minute timeout, a credential duration of 60 minutes, and a maximum stdout
-buffer size of 2k.
-
- creds := processcreds.NewCredentials(
- "/path/to/command",
- func(opt *ProcessProvider) {
- opt.Timeout = time.Duration(2) * time.Minute
- opt.Duration = time.Duration(60) * time.Minute
- opt.MaxBufSize = 2048
- })
-
-You can also use your own `exec.Cmd`:
-
- // Create an exec.Cmd
- myCommand := exec.Command("/path/to/command")
-
- // Create credentials using your exec.Cmd and custom timeout
- creds := processcreds.NewCredentialsCommand(
- myCommand,
- func(opt *processcreds.ProcessProvider) {
- opt.Timeout = time.Duration(1) * time.Second
- })
-*/
-package processcreds
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "io"
- "io/ioutil"
- "os"
- "os/exec"
- "runtime"
- "strings"
- "time"
-
- "github.com/aws/aws-sdk-go/aws/awserr"
- "github.com/aws/aws-sdk-go/aws/credentials"
-)
-
-const (
- // ProviderName is the name this credentials provider will label any
- // returned credentials Value with.
- ProviderName = `ProcessProvider`
-
- // ErrCodeProcessProviderParse error parsing process output
- ErrCodeProcessProviderParse = "ProcessProviderParseError"
-
- // ErrCodeProcessProviderVersion version error in output
- ErrCodeProcessProviderVersion = "ProcessProviderVersionError"
-
- // ErrCodeProcessProviderRequired required attribute missing in output
- ErrCodeProcessProviderRequired = "ProcessProviderRequiredError"
-
- // ErrCodeProcessProviderExecution execution of command failed
- ErrCodeProcessProviderExecution = "ProcessProviderExecutionError"
-
- // errMsgProcessProviderTimeout process took longer than allowed
- errMsgProcessProviderTimeout = "credential process timed out"
-
- // errMsgProcessProviderProcess process error
- errMsgProcessProviderProcess = "error in credential_process"
-
- // errMsgProcessProviderParse problem parsing output
- errMsgProcessProviderParse = "parse failed of credential_process output"
-
- // errMsgProcessProviderVersion version error in output
- errMsgProcessProviderVersion = "wrong version in process output (not 1)"
-
- // errMsgProcessProviderMissKey missing access key id in output
- errMsgProcessProviderMissKey = "missing AccessKeyId in process output"
-
- // errMsgProcessProviderMissSecret missing secret acess key in output
- errMsgProcessProviderMissSecret = "missing SecretAccessKey in process output"
-
- // errMsgProcessProviderPrepareCmd prepare of command failed
- errMsgProcessProviderPrepareCmd = "failed to prepare command"
-
- // errMsgProcessProviderEmptyCmd command must not be empty
- errMsgProcessProviderEmptyCmd = "command must not be empty"
-
- // errMsgProcessProviderPipe failed to initialize pipe
- errMsgProcessProviderPipe = "failed to initialize pipe"
-
- // DefaultDuration is the default amount of time in minutes that the
- // credentials will be valid for.
- DefaultDuration = time.Duration(15) * time.Minute
-
- // DefaultBufSize limits buffer size from growing to an enormous
- // amount due to a faulty process.
- DefaultBufSize = 1024
-
- // DefaultTimeout default limit on time a process can run.
- DefaultTimeout = time.Duration(1) * time.Minute
-)
-
-// ProcessProvider satisfies the credentials.Provider interface, and is a
-// client to retrieve credentials from a process.
-type ProcessProvider struct {
- staticCreds bool
- credentials.Expiry
- originalCommand []string
-
- // Expiry duration of the credentials. Defaults to 15 minutes if not set.
- Duration time.Duration
-
- // ExpiryWindow will allow the credentials to trigger refreshing prior to
- // the credentials actually expiring. This is beneficial so race conditions
- // with expiring credentials do not cause request to fail unexpectedly
- // due to ExpiredTokenException exceptions.
- //
- // So a ExpiryWindow of 10s would cause calls to IsExpired() to return true
- // 10 seconds before the credentials are actually expired.
- //
- // If ExpiryWindow is 0 or less it will be ignored.
- ExpiryWindow time.Duration
-
- // A string representing an os command that should return a JSON with
- // credential information.
- command *exec.Cmd
-
- // MaxBufSize limits memory usage from growing to an enormous
- // amount due to a faulty process.
- MaxBufSize int
-
- // Timeout limits the time a process can run.
- Timeout time.Duration
-}
-
-// NewCredentials returns a pointer to a new Credentials object wrapping the
-// ProcessProvider. The credentials will expire every 15 minutes by default.
-func NewCredentials(command string, options ...func(*ProcessProvider)) *credentials.Credentials {
- p := &ProcessProvider{
- command: exec.Command(command),
- Duration: DefaultDuration,
- Timeout: DefaultTimeout,
- MaxBufSize: DefaultBufSize,
- }
-
- for _, option := range options {
- option(p)
- }
-
- return credentials.NewCredentials(p)
-}
-
-// NewCredentialsTimeout returns a pointer to a new Credentials object with
-// the specified command and timeout, and default duration and max buffer size.
-func NewCredentialsTimeout(command string, timeout time.Duration) *credentials.Credentials {
- p := NewCredentials(command, func(opt *ProcessProvider) {
- opt.Timeout = timeout
- })
-
- return p
-}
-
-// NewCredentialsCommand returns a pointer to a new Credentials object with
-// the specified command, and default timeout, duration and max buffer size.
-func NewCredentialsCommand(command *exec.Cmd, options ...func(*ProcessProvider)) *credentials.Credentials {
- p := &ProcessProvider{
- command: command,
- Duration: DefaultDuration,
- Timeout: DefaultTimeout,
- MaxBufSize: DefaultBufSize,
- }
-
- for _, option := range options {
- option(p)
- }
-
- return credentials.NewCredentials(p)
-}
-
-type credentialProcessResponse struct {
- Version int
- AccessKeyID string `json:"AccessKeyId"`
- SecretAccessKey string
- SessionToken string
- Expiration *time.Time
-}
-
-// Retrieve executes the 'credential_process' and returns the credentials.
-func (p *ProcessProvider) Retrieve() (credentials.Value, error) {
- out, err := p.executeCredentialProcess()
- if err != nil {
- return credentials.Value{ProviderName: ProviderName}, err
- }
-
- // Serialize and validate response
- resp := &credentialProcessResponse{}
- if err = json.Unmarshal(out, resp); err != nil {
- return credentials.Value{ProviderName: ProviderName}, awserr.New(
- ErrCodeProcessProviderParse,
- fmt.Sprintf("%s: %s", errMsgProcessProviderParse, string(out)),
- err)
- }
-
- if resp.Version != 1 {
- return credentials.Value{ProviderName: ProviderName}, awserr.New(
- ErrCodeProcessProviderVersion,
- errMsgProcessProviderVersion,
- nil)
- }
-
- if len(resp.AccessKeyID) == 0 {
- return credentials.Value{ProviderName: ProviderName}, awserr.New(
- ErrCodeProcessProviderRequired,
- errMsgProcessProviderMissKey,
- nil)
- }
-
- if len(resp.SecretAccessKey) == 0 {
- return credentials.Value{ProviderName: ProviderName}, awserr.New(
- ErrCodeProcessProviderRequired,
- errMsgProcessProviderMissSecret,
- nil)
- }
-
- // Handle expiration
- p.staticCreds = resp.Expiration == nil
- if resp.Expiration != nil {
- p.SetExpiration(*resp.Expiration, p.ExpiryWindow)
- }
-
- return credentials.Value{
- ProviderName: ProviderName,
- AccessKeyID: resp.AccessKeyID,
- SecretAccessKey: resp.SecretAccessKey,
- SessionToken: resp.SessionToken,
- }, nil
-}
-
-// IsExpired returns true if the credentials retrieved are expired, or not yet
-// retrieved.
-func (p *ProcessProvider) IsExpired() bool {
- if p.staticCreds {
- return false
- }
- return p.Expiry.IsExpired()
-}
-
-// prepareCommand prepares the command to be executed.
-func (p *ProcessProvider) prepareCommand() error {
-
- var cmdArgs []string
- if runtime.GOOS == "windows" {
- cmdArgs = []string{"cmd.exe", "/C"}
- } else {
- cmdArgs = []string{"sh", "-c"}
- }
-
- if len(p.originalCommand) == 0 {
- p.originalCommand = make([]string, len(p.command.Args))
- copy(p.originalCommand, p.command.Args)
-
- // check for empty command because it succeeds
- if len(strings.TrimSpace(p.originalCommand[0])) < 1 {
- return awserr.New(
- ErrCodeProcessProviderExecution,
- fmt.Sprintf(
- "%s: %s",
- errMsgProcessProviderPrepareCmd,
- errMsgProcessProviderEmptyCmd),
- nil)
- }
- }
-
- cmdArgs = append(cmdArgs, p.originalCommand...)
- p.command = exec.Command(cmdArgs[0], cmdArgs[1:]...)
- p.command.Env = os.Environ()
-
- return nil
-}
-
-// executeCredentialProcess starts the credential process on the OS and
-// returns the results or an error.
-func (p *ProcessProvider) executeCredentialProcess() ([]byte, error) {
-
- if err := p.prepareCommand(); err != nil {
- return nil, err
- }
-
- // Setup the pipes
- outReadPipe, outWritePipe, err := os.Pipe()
- if err != nil {
- return nil, awserr.New(
- ErrCodeProcessProviderExecution,
- errMsgProcessProviderPipe,
- err)
- }
-
- p.command.Stderr = os.Stderr // display stderr on console for MFA
- p.command.Stdout = outWritePipe // get creds json on process's stdout
- p.command.Stdin = os.Stdin // enable stdin for MFA
-
- output := bytes.NewBuffer(make([]byte, 0, p.MaxBufSize))
-
- stdoutCh := make(chan error, 1)
- go readInput(
- io.LimitReader(outReadPipe, int64(p.MaxBufSize)),
- output,
- stdoutCh)
-
- execCh := make(chan error, 1)
- go executeCommand(*p.command, execCh)
-
- finished := false
- var errors []error
- for !finished {
- select {
- case readError := <-stdoutCh:
- errors = appendError(errors, readError)
- finished = true
- case execError := <-execCh:
- err := outWritePipe.Close()
- errors = appendError(errors, err)
- errors = appendError(errors, execError)
- if errors != nil {
- return output.Bytes(), awserr.NewBatchError(
- ErrCodeProcessProviderExecution,
- errMsgProcessProviderProcess,
- errors)
- }
- case <-time.After(p.Timeout):
- finished = true
- return output.Bytes(), awserr.NewBatchError(
- ErrCodeProcessProviderExecution,
- errMsgProcessProviderTimeout,
- errors) // errors can be nil
- }
- }
-
- out := output.Bytes()
-
- if runtime.GOOS == "windows" {
- // windows adds slashes to quotes
- out = []byte(strings.Replace(string(out), `\"`, `"`, -1))
- }
-
- return out, nil
-}
-
-// appendError conveniently checks for nil before appending slice
-func appendError(errors []error, err error) []error {
- if err != nil {
- return append(errors, err)
- }
- return errors
-}
-
-func executeCommand(cmd exec.Cmd, exec chan error) {
- // Start the command
- err := cmd.Start()
- if err == nil {
- err = cmd.Wait()
- }
-
- exec <- err
-}
-
-func readInput(r io.Reader, w io.Writer, read chan error) {
- tee := io.TeeReader(r, w)
-
- _, err := ioutil.ReadAll(tee)
-
- if err == io.EOF {
- err = nil
- }
-
- read <- err // will only arrive here when write end of pipe is closed
-}