debian-forge-composer/vendor/github.com/aws/aws-sdk-go-v2/credentials/processcreds/provider.go
dependabot[bot] 6bb45ef9d1 build(deps): bump the go-deps group across 1 directory with 13 updates
Bumps the go-deps group with 8 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [github.com/aws/aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2) | `1.30.3` | `1.30.4` |
| [github.com/aws/aws-sdk-go-v2/config](https://github.com/aws/aws-sdk-go-v2) | `1.27.9` | `1.27.31` |
| [github.com/aws/aws-sdk-go-v2/feature/s3/manager](https://github.com/aws/aws-sdk-go-v2) | `1.16.9` | `1.17.16` |
| [github.com/aws/aws-sdk-go-v2/service/autoscaling](https://github.com/aws/aws-sdk-go-v2) | `1.43.3` | `1.43.5` |
| [github.com/aws/aws-sdk-go-v2/service/ec2](https://github.com/aws/aws-sdk-go-v2) | `1.173.0` | `1.177.0` |
| [github.com/openshift-online/ocm-sdk-go](https://github.com/openshift-online/ocm-sdk-go) | `0.1.432` | `0.1.438` |
| [github.com/osbuild/images](https://github.com/osbuild/images) | `0.79.0` | `0.80.0` |
| [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) | `1.19.1` | `1.20.2` |



Updates `github.com/aws/aws-sdk-go-v2` from 1.30.3 to 1.30.4
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.30.3...v1.30.4)

Updates `github.com/aws/aws-sdk-go-v2/config` from 1.27.9 to 1.27.31
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.27.9...config/v1.27.31)

Updates `github.com/aws/aws-sdk-go-v2/credentials` from 1.17.9 to 1.17.30
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/config/v1.17.9...credentials/v1.17.30)

Updates `github.com/aws/aws-sdk-go-v2/feature/ec2/imds` from 1.16.0 to 1.16.12
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.16.0...v1.16.12)

Updates `github.com/aws/aws-sdk-go-v2/feature/s3/manager` from 1.16.9 to 1.17.16
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.16.9...credentials/v1.17.16)

Updates `github.com/aws/aws-sdk-go-v2/service/autoscaling` from 1.43.3 to 1.43.5
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/fsx/v1.43.3...service/fsx/v1.43.5)

Updates `github.com/aws/aws-sdk-go-v2/service/ec2` from 1.173.0 to 1.177.0
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/ec2/v1.173.0...service/ec2/v1.177.0)

Updates `github.com/aws/aws-sdk-go-v2/service/s3` from 1.51.4 to 1.61.0
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/s3/v1.51.4...service/s3/v1.61.0)

Updates `github.com/aws/smithy-go` from 1.20.3 to 1.20.4
- [Release notes](https://github.com/aws/smithy-go/releases)
- [Changelog](https://github.com/aws/smithy-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/aws/smithy-go/compare/v1.20.3...v1.20.4)

Updates `github.com/openshift-online/ocm-sdk-go` from 0.1.432 to 0.1.438
- [Release notes](https://github.com/openshift-online/ocm-sdk-go/releases)
- [Changelog](https://github.com/openshift-online/ocm-sdk-go/blob/main/CHANGES.md)
- [Commits](https://github.com/openshift-online/ocm-sdk-go/compare/v0.1.432...v0.1.438)

Updates `github.com/osbuild/images` from 0.79.0 to 0.80.0
- [Release notes](https://github.com/osbuild/images/releases)
- [Commits](https://github.com/osbuild/images/compare/v0.79.0...v0.80.0)

Updates `github.com/prometheus/client_golang` from 1.19.1 to 1.20.2
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.19.1...v1.20.2)

Updates `google.golang.org/api` from 0.193.0 to 0.194.0
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.193.0...v0.194.0)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: github.com/aws/aws-sdk-go-v2/config
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: github.com/aws/aws-sdk-go-v2/credentials
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/ec2/imds
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: github.com/aws/aws-sdk-go-v2/feature/s3/manager
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/aws/aws-sdk-go-v2/service/autoscaling
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: github.com/aws/aws-sdk-go-v2/service/ec2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/aws/aws-sdk-go-v2/service/s3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/aws/smithy-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: github.com/openshift-online/ocm-sdk-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
- dependency-name: github.com/osbuild/images
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: github.com/prometheus/client_golang
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-30 14:19:01 +02:00

285 lines
7.8 KiB
Go

package processcreds
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"os"
"os/exec"
"runtime"
"time"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/internal/sdkio"
)
const (
// ProviderName is the name this credentials provider will label any
// returned credentials Value with.
ProviderName = `ProcessProvider`
// DefaultTimeout default limit on time a process can run.
DefaultTimeout = time.Duration(1) * time.Minute
)
// ProviderError is an error indicating failure initializing or executing the
// process credentials provider
type ProviderError struct {
Err error
}
// Error returns the error message.
func (e *ProviderError) Error() string {
return fmt.Sprintf("process provider error: %v", e.Err)
}
// Unwrap returns the underlying error the provider error wraps.
func (e *ProviderError) Unwrap() error {
return e.Err
}
// Provider satisfies the credentials.Provider interface, and is a
// client to retrieve credentials from a process.
type Provider struct {
// Provides a constructor for exec.Cmd that are invoked by the provider for
// retrieving credentials. Use this to provide custom creation of exec.Cmd
// with things like environment variables, or other configuration.
//
// The provider defaults to the DefaultNewCommand function.
commandBuilder NewCommandBuilder
options Options
}
// Options is the configuration options for configuring the Provider.
type Options struct {
// Timeout limits the time a process can run.
Timeout time.Duration
}
// NewCommandBuilder provides the interface for specifying how command will be
// created that the Provider will use to retrieve credentials with.
type NewCommandBuilder interface {
NewCommand(context.Context) (*exec.Cmd, error)
}
// NewCommandBuilderFunc provides a wrapper type around a function pointer to
// satisfy the NewCommandBuilder interface.
type NewCommandBuilderFunc func(context.Context) (*exec.Cmd, error)
// NewCommand calls the underlying function pointer the builder was initialized with.
func (fn NewCommandBuilderFunc) NewCommand(ctx context.Context) (*exec.Cmd, error) {
return fn(ctx)
}
// DefaultNewCommandBuilder provides the default NewCommandBuilder
// implementation used by the provider. It takes a command and arguments to
// invoke. The command will also be initialized with the current process
// environment variables, stderr, and stdin pipes.
type DefaultNewCommandBuilder struct {
Args []string
}
// NewCommand returns an initialized exec.Cmd with the builder's initialized
// Args. The command is also initialized current process environment variables,
// stderr, and stdin pipes.
func (b DefaultNewCommandBuilder) NewCommand(ctx context.Context) (*exec.Cmd, error) {
var cmdArgs []string
if runtime.GOOS == "windows" {
cmdArgs = []string{"cmd.exe", "/C"}
} else {
cmdArgs = []string{"sh", "-c"}
}
if len(b.Args) == 0 {
return nil, &ProviderError{
Err: fmt.Errorf("failed to prepare command: command must not be empty"),
}
}
cmdArgs = append(cmdArgs, b.Args...)
cmd := exec.CommandContext(ctx, cmdArgs[0], cmdArgs[1:]...)
cmd.Env = os.Environ()
cmd.Stderr = os.Stderr // display stderr on console for MFA
cmd.Stdin = os.Stdin // enable stdin for MFA
return cmd, nil
}
// NewProvider returns a pointer to a new Credentials object wrapping the
// Provider.
//
// The provider defaults to the DefaultNewCommandBuilder for creating command
// the Provider will use to retrieve credentials with.
func NewProvider(command string, options ...func(*Options)) *Provider {
var args []string
// Ensure that the command arguments are not set if the provided command is
// empty. This will error out when the command is executed since no
// arguments are specified.
if len(command) > 0 {
args = []string{command}
}
commanBuilder := DefaultNewCommandBuilder{
Args: args,
}
return NewProviderCommand(commanBuilder, options...)
}
// NewProviderCommand returns a pointer to a new Credentials object with the
// specified command, and default timeout duration. Use this to provide custom
// creation of exec.Cmd for options like environment variables, or other
// configuration.
func NewProviderCommand(builder NewCommandBuilder, options ...func(*Options)) *Provider {
p := &Provider{
commandBuilder: builder,
options: Options{
Timeout: DefaultTimeout,
},
}
for _, option := range options {
option(&p.options)
}
return p
}
// A CredentialProcessResponse is the AWS credentials format that must be
// returned when executing an external credential_process.
type CredentialProcessResponse struct {
// As of this writing, the Version key must be set to 1. This might
// increment over time as the structure evolves.
Version int
// The access key ID that identifies the temporary security credentials.
AccessKeyID string `json:"AccessKeyId"`
// The secret access key that can be used to sign requests.
SecretAccessKey string
// The token that users must pass to the service API to use the temporary credentials.
SessionToken string
// The date on which the current credentials expire.
Expiration *time.Time
// The ID of the account for credentials
AccountID string `json:"AccountId"`
}
// Retrieve executes the credential process command and returns the
// credentials, or error if the command fails.
func (p *Provider) Retrieve(ctx context.Context) (aws.Credentials, error) {
out, err := p.executeCredentialProcess(ctx)
if err != nil {
return aws.Credentials{Source: ProviderName}, err
}
// Serialize and validate response
resp := &CredentialProcessResponse{}
if err = json.Unmarshal(out, resp); err != nil {
return aws.Credentials{Source: ProviderName}, &ProviderError{
Err: fmt.Errorf("parse failed of process output: %s, error: %w", out, err),
}
}
if resp.Version != 1 {
return aws.Credentials{Source: ProviderName}, &ProviderError{
Err: fmt.Errorf("wrong version in process output (not 1)"),
}
}
if len(resp.AccessKeyID) == 0 {
return aws.Credentials{Source: ProviderName}, &ProviderError{
Err: fmt.Errorf("missing AccessKeyId in process output"),
}
}
if len(resp.SecretAccessKey) == 0 {
return aws.Credentials{Source: ProviderName}, &ProviderError{
Err: fmt.Errorf("missing SecretAccessKey in process output"),
}
}
creds := aws.Credentials{
Source: ProviderName,
AccessKeyID: resp.AccessKeyID,
SecretAccessKey: resp.SecretAccessKey,
SessionToken: resp.SessionToken,
AccountID: resp.AccountID,
}
// Handle expiration
if resp.Expiration != nil {
creds.CanExpire = true
creds.Expires = *resp.Expiration
}
return creds, nil
}
// executeCredentialProcess starts the credential process on the OS and
// returns the results or an error.
func (p *Provider) executeCredentialProcess(ctx context.Context) ([]byte, error) {
if p.options.Timeout >= 0 {
var cancelFunc func()
ctx, cancelFunc = context.WithTimeout(ctx, p.options.Timeout)
defer cancelFunc()
}
cmd, err := p.commandBuilder.NewCommand(ctx)
if err != nil {
return nil, err
}
// get creds json on process's stdout
output := bytes.NewBuffer(make([]byte, 0, int(8*sdkio.KibiByte)))
if cmd.Stdout != nil {
cmd.Stdout = io.MultiWriter(cmd.Stdout, output)
} else {
cmd.Stdout = output
}
execCh := make(chan error, 1)
go executeCommand(cmd, execCh)
select {
case execError := <-execCh:
if execError == nil {
break
}
select {
case <-ctx.Done():
return output.Bytes(), &ProviderError{
Err: fmt.Errorf("credential process timed out: %w", execError),
}
default:
return output.Bytes(), &ProviderError{
Err: fmt.Errorf("error in credential_process: %w", execError),
}
}
}
out := output.Bytes()
if runtime.GOOS == "windows" {
// windows adds slashes to quotes
out = bytes.ReplaceAll(out, []byte(`\"`), []byte(`"`))
}
return out, nil
}
func executeCommand(cmd *exec.Cmd, exec chan error) {
// Start the command
err := cmd.Start()
if err == nil {
err = cmd.Wait()
}
exec <- err
}