Update dependencies

This commit is contained in:
bluepython508
2024-11-01 17:33:34 +00:00
parent 033ac0b400
commit 5cdfab398d
3596 changed files with 1033483 additions and 259 deletions

View File

@@ -0,0 +1,48 @@
package client
import (
"context"
"github.com/aws/smithy-go/middleware"
)
type getIdentityMiddleware struct {
options Options
}
func (*getIdentityMiddleware) ID() string {
return "GetIdentity"
}
func (m *getIdentityMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
) {
return next.HandleFinalize(ctx, in)
}
type signRequestMiddleware struct {
}
func (*signRequestMiddleware) ID() string {
return "Signing"
}
func (m *signRequestMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
) {
return next.HandleFinalize(ctx, in)
}
type resolveAuthSchemeMiddleware struct {
operation string
options Options
}
func (*resolveAuthSchemeMiddleware) ID() string {
return "ResolveAuthScheme"
}
func (m *resolveAuthSchemeMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
) {
return next.HandleFinalize(ctx, in)
}

View File

@@ -0,0 +1,164 @@
package client
import (
"context"
"fmt"
"net/http"
"time"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/aws/middleware"
"github.com/aws/aws-sdk-go-v2/aws/retry"
awshttp "github.com/aws/aws-sdk-go-v2/aws/transport/http"
"github.com/aws/smithy-go"
smithymiddleware "github.com/aws/smithy-go/middleware"
smithyhttp "github.com/aws/smithy-go/transport/http"
)
// ServiceID is the client identifer
const ServiceID = "endpoint-credentials"
// HTTPClient is a client for sending HTTP requests
type HTTPClient interface {
Do(*http.Request) (*http.Response, error)
}
// Options is the endpoint client configurable options
type Options struct {
// The endpoint to retrieve credentials from
Endpoint string
// The HTTP client to invoke API calls with. Defaults to client's default HTTP
// implementation if nil.
HTTPClient HTTPClient
// Retryer guides how HTTP requests should be retried in case of recoverable
// failures. When nil the API client will use a default retryer.
Retryer aws.Retryer
// Set of options to modify how the credentials operation is invoked.
APIOptions []func(*smithymiddleware.Stack) error
}
// Copy creates a copy of the API options.
func (o Options) Copy() Options {
to := o
to.APIOptions = make([]func(*smithymiddleware.Stack) error, len(o.APIOptions))
copy(to.APIOptions, o.APIOptions)
return to
}
// Client is an client for retrieving AWS credentials from an endpoint
type Client struct {
options Options
}
// New constructs a new Client from the given options
func New(options Options, optFns ...func(*Options)) *Client {
options = options.Copy()
if options.HTTPClient == nil {
options.HTTPClient = awshttp.NewBuildableClient()
}
if options.Retryer == nil {
// Amazon-owned implementations of this endpoint are known to sometimes
// return plaintext responses (i.e. no Code) like normal, add a few
// additional status codes
options.Retryer = retry.NewStandard(func(o *retry.StandardOptions) {
o.Retryables = append(o.Retryables, retry.RetryableHTTPStatusCode{
Codes: map[int]struct{}{
http.StatusTooManyRequests: {},
},
})
})
}
for _, fn := range optFns {
fn(&options)
}
client := &Client{
options: options,
}
return client
}
// GetCredentialsInput is the input to send with the endpoint service to receive credentials.
type GetCredentialsInput struct {
AuthorizationToken string
}
// GetCredentials retrieves credentials from credential endpoint
func (c *Client) GetCredentials(ctx context.Context, params *GetCredentialsInput, optFns ...func(*Options)) (*GetCredentialsOutput, error) {
stack := smithymiddleware.NewStack("GetCredentials", smithyhttp.NewStackRequest)
options := c.options.Copy()
for _, fn := range optFns {
fn(&options)
}
stack.Serialize.Add(&serializeOpGetCredential{}, smithymiddleware.After)
stack.Build.Add(&buildEndpoint{Endpoint: options.Endpoint}, smithymiddleware.After)
stack.Deserialize.Add(&deserializeOpGetCredential{}, smithymiddleware.After)
addProtocolFinalizerMiddlewares(stack, options, "GetCredentials")
retry.AddRetryMiddlewares(stack, retry.AddRetryMiddlewaresOptions{Retryer: options.Retryer})
middleware.AddSDKAgentKey(middleware.FeatureMetadata, ServiceID)
smithyhttp.AddErrorCloseResponseBodyMiddleware(stack)
smithyhttp.AddCloseResponseBodyMiddleware(stack)
for _, fn := range options.APIOptions {
if err := fn(stack); err != nil {
return nil, err
}
}
handler := smithymiddleware.DecorateHandler(smithyhttp.NewClientHandler(options.HTTPClient), stack)
result, _, err := handler.Handle(ctx, params)
if err != nil {
return nil, err
}
return result.(*GetCredentialsOutput), err
}
// GetCredentialsOutput is the response from the credential endpoint
type GetCredentialsOutput struct {
Expiration *time.Time
AccessKeyID string
SecretAccessKey string
Token string
}
// EndpointError is an error returned from the endpoint service
type EndpointError struct {
Code string `json:"code"`
Message string `json:"message"`
Fault smithy.ErrorFault `json:"-"`
statusCode int `json:"-"`
}
// Error is the error mesage string
func (e *EndpointError) Error() string {
return fmt.Sprintf("%s: %s", e.Code, e.Message)
}
// ErrorCode is the error code returned by the endpoint
func (e *EndpointError) ErrorCode() string {
return e.Code
}
// ErrorMessage is the error message returned by the endpoint
func (e *EndpointError) ErrorMessage() string {
return e.Message
}
// ErrorFault indicates error fault classification
func (e *EndpointError) ErrorFault() smithy.ErrorFault {
return e.Fault
}
// HTTPStatusCode implements retry.HTTPStatusCode.
func (e *EndpointError) HTTPStatusCode() int {
return e.statusCode
}

View File

@@ -0,0 +1,20 @@
package client
import (
"context"
"github.com/aws/smithy-go/middleware"
)
type resolveEndpointV2Middleware struct {
options Options
}
func (*resolveEndpointV2Middleware) ID() string {
return "ResolveEndpointV2"
}
func (m *resolveEndpointV2Middleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
) {
return next.HandleFinalize(ctx, in)
}

View File

@@ -0,0 +1,164 @@
package client
import (
"context"
"encoding/json"
"fmt"
"io"
"net/url"
"github.com/aws/smithy-go"
smithymiddleware "github.com/aws/smithy-go/middleware"
smithyhttp "github.com/aws/smithy-go/transport/http"
)
type buildEndpoint struct {
Endpoint string
}
func (b *buildEndpoint) ID() string {
return "BuildEndpoint"
}
func (b *buildEndpoint) HandleBuild(ctx context.Context, in smithymiddleware.BuildInput, next smithymiddleware.BuildHandler) (
out smithymiddleware.BuildOutput, metadata smithymiddleware.Metadata, err error,
) {
request, ok := in.Request.(*smithyhttp.Request)
if !ok {
return out, metadata, fmt.Errorf("unknown transport, %T", in.Request)
}
if len(b.Endpoint) == 0 {
return out, metadata, fmt.Errorf("endpoint not provided")
}
parsed, err := url.Parse(b.Endpoint)
if err != nil {
return out, metadata, fmt.Errorf("failed to parse endpoint, %w", err)
}
request.URL = parsed
return next.HandleBuild(ctx, in)
}
type serializeOpGetCredential struct{}
func (s *serializeOpGetCredential) ID() string {
return "OperationSerializer"
}
func (s *serializeOpGetCredential) HandleSerialize(ctx context.Context, in smithymiddleware.SerializeInput, next smithymiddleware.SerializeHandler) (
out smithymiddleware.SerializeOutput, metadata smithymiddleware.Metadata, err error,
) {
request, ok := in.Request.(*smithyhttp.Request)
if !ok {
return out, metadata, fmt.Errorf("unknown transport type, %T", in.Request)
}
params, ok := in.Parameters.(*GetCredentialsInput)
if !ok {
return out, metadata, fmt.Errorf("unknown input parameters, %T", in.Parameters)
}
const acceptHeader = "Accept"
request.Header[acceptHeader] = append(request.Header[acceptHeader][:0], "application/json")
if len(params.AuthorizationToken) > 0 {
const authHeader = "Authorization"
request.Header[authHeader] = append(request.Header[authHeader][:0], params.AuthorizationToken)
}
return next.HandleSerialize(ctx, in)
}
type deserializeOpGetCredential struct{}
func (d *deserializeOpGetCredential) ID() string {
return "OperationDeserializer"
}
func (d *deserializeOpGetCredential) HandleDeserialize(ctx context.Context, in smithymiddleware.DeserializeInput, next smithymiddleware.DeserializeHandler) (
out smithymiddleware.DeserializeOutput, metadata smithymiddleware.Metadata, err error,
) {
out, metadata, err = next.HandleDeserialize(ctx, in)
if err != nil {
return out, metadata, err
}
response, ok := out.RawResponse.(*smithyhttp.Response)
if !ok {
return out, metadata, &smithy.DeserializationError{Err: fmt.Errorf("unknown transport type %T", out.RawResponse)}
}
if response.StatusCode < 200 || response.StatusCode >= 300 {
return out, metadata, deserializeError(response)
}
var shape *GetCredentialsOutput
if err = json.NewDecoder(response.Body).Decode(&shape); err != nil {
return out, metadata, &smithy.DeserializationError{Err: fmt.Errorf("failed to deserialize json response, %w", err)}
}
out.Result = shape
return out, metadata, err
}
func deserializeError(response *smithyhttp.Response) error {
// we could be talking to anything, json isn't guaranteed
// see https://github.com/aws/aws-sdk-go-v2/issues/2316
if response.Header.Get("Content-Type") == "application/json" {
return deserializeJSONError(response)
}
msg, err := io.ReadAll(response.Body)
if err != nil {
return &smithy.DeserializationError{
Err: fmt.Errorf("read response, %w", err),
}
}
return &EndpointError{
// no sensible value for Code
Message: string(msg),
Fault: stof(response.StatusCode),
statusCode: response.StatusCode,
}
}
func deserializeJSONError(response *smithyhttp.Response) error {
var errShape *EndpointError
if err := json.NewDecoder(response.Body).Decode(&errShape); err != nil {
return &smithy.DeserializationError{
Err: fmt.Errorf("failed to decode error message, %w", err),
}
}
errShape.Fault = stof(response.StatusCode)
errShape.statusCode = response.StatusCode
return errShape
}
// maps HTTP status code to smithy ErrorFault
func stof(code int) smithy.ErrorFault {
if code >= 500 {
return smithy.FaultServer
}
return smithy.FaultClient
}
func addProtocolFinalizerMiddlewares(stack *smithymiddleware.Stack, options Options, operation string) error {
if err := stack.Finalize.Add(&resolveAuthSchemeMiddleware{operation: operation, options: options}, smithymiddleware.Before); err != nil {
return fmt.Errorf("add ResolveAuthScheme: %w", err)
}
if err := stack.Finalize.Insert(&getIdentityMiddleware{options: options}, "ResolveAuthScheme", smithymiddleware.After); err != nil {
return fmt.Errorf("add GetIdentity: %w", err)
}
if err := stack.Finalize.Insert(&resolveEndpointV2Middleware{options: options}, "GetIdentity", smithymiddleware.After); err != nil {
return fmt.Errorf("add ResolveEndpointV2: %w", err)
}
if err := stack.Finalize.Insert(&signRequestMiddleware{}, "ResolveEndpointV2", smithymiddleware.After); err != nil {
return fmt.Errorf("add Signing: %w", err)
}
return nil
}

View File

@@ -0,0 +1,192 @@
// Package endpointcreds provides support for retrieving credentials from an
// arbitrary HTTP endpoint.
//
// The credentials endpoint Provider can receive both static and refreshable
// credentials that will expire. Credentials are static when an "Expiration"
// value is not provided in the endpoint's response.
//
// Static credentials will never expire once they have been retrieved. The format
// of the static credentials response:
//
// {
// "AccessKeyId" : "MUA...",
// "SecretAccessKey" : "/7PC5om....",
// }
//
// Refreshable credentials will expire within the "ExpiryWindow" of the Expiration
// value in the response. The format of the refreshable credentials response:
//
// {
// "AccessKeyId" : "MUA...",
// "SecretAccessKey" : "/7PC5om....",
// "Token" : "AQoDY....=",
// "Expiration" : "2016-02-25T06:03:31Z"
// }
//
// Errors should be returned in the following format and only returned with 400
// or 500 HTTP status codes.
//
// {
// "code": "ErrorCode",
// "message": "Helpful error message."
// }
package endpointcreds
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/credentials/endpointcreds/internal/client"
"github.com/aws/smithy-go/middleware"
)
// ProviderName is the name of the credentials provider.
const ProviderName = `CredentialsEndpointProvider`
type getCredentialsAPIClient interface {
GetCredentials(context.Context, *client.GetCredentialsInput, ...func(*client.Options)) (*client.GetCredentialsOutput, error)
}
// Provider satisfies the aws.CredentialsProvider interface, and is a client to
// retrieve credentials from an arbitrary endpoint.
type Provider struct {
// The AWS Client to make HTTP requests to the endpoint with. The endpoint
// the request will be made to is provided by the aws.Config's
// EndpointResolver.
client getCredentialsAPIClient
options Options
}
// HTTPClient is a client for sending HTTP requests
type HTTPClient interface {
Do(*http.Request) (*http.Response, error)
}
// Options is structure of configurable options for Provider
type Options struct {
// Endpoint to retrieve credentials from. Required
Endpoint string
// HTTPClient to handle sending HTTP requests to the target endpoint.
HTTPClient HTTPClient
// Set of options to modify how the credentials operation is invoked.
APIOptions []func(*middleware.Stack) error
// The Retryer to be used for determining whether a failed requested should be retried
Retryer aws.Retryer
// Optional authorization token value if set will be used as the value of
// the Authorization header of the endpoint credential request.
//
// When constructed from environment, the provider will use the value of
// AWS_CONTAINER_AUTHORIZATION_TOKEN environment variable as the token
//
// Will be overridden if AuthorizationTokenProvider is configured
AuthorizationToken string
// Optional auth provider func to dynamically load the auth token from a file
// everytime a credential is retrieved
//
// When constructed from environment, the provider will read and use the content
// of the file pointed to by AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE environment variable
// as the auth token everytime credentials are retrieved
//
// Will override AuthorizationToken if configured
AuthorizationTokenProvider AuthTokenProvider
}
// AuthTokenProvider defines an interface to dynamically load a value to be passed
// for the Authorization header of a credentials request.
type AuthTokenProvider interface {
GetToken() (string, error)
}
// TokenProviderFunc is a func type implementing AuthTokenProvider interface
// and enables customizing token provider behavior
type TokenProviderFunc func() (string, error)
// GetToken func retrieves auth token according to TokenProviderFunc implementation
func (p TokenProviderFunc) GetToken() (string, error) {
return p()
}
// New returns a credentials Provider for retrieving AWS credentials
// from arbitrary endpoint.
func New(endpoint string, optFns ...func(*Options)) *Provider {
o := Options{
Endpoint: endpoint,
}
for _, fn := range optFns {
fn(&o)
}
p := &Provider{
client: client.New(client.Options{
HTTPClient: o.HTTPClient,
Endpoint: o.Endpoint,
APIOptions: o.APIOptions,
Retryer: o.Retryer,
}),
options: o,
}
return p
}
// Retrieve will attempt to request the credentials from the endpoint the Provider
// was configured for. And error will be returned if the retrieval fails.
func (p *Provider) Retrieve(ctx context.Context) (aws.Credentials, error) {
resp, err := p.getCredentials(ctx)
if err != nil {
return aws.Credentials{}, fmt.Errorf("failed to load credentials, %w", err)
}
creds := aws.Credentials{
AccessKeyID: resp.AccessKeyID,
SecretAccessKey: resp.SecretAccessKey,
SessionToken: resp.Token,
Source: ProviderName,
}
if resp.Expiration != nil {
creds.CanExpire = true
creds.Expires = *resp.Expiration
}
return creds, nil
}
func (p *Provider) getCredentials(ctx context.Context) (*client.GetCredentialsOutput, error) {
authToken, err := p.resolveAuthToken()
if err != nil {
return nil, fmt.Errorf("resolve auth token: %v", err)
}
return p.client.GetCredentials(ctx, &client.GetCredentialsInput{
AuthorizationToken: authToken,
})
}
func (p *Provider) resolveAuthToken() (string, error) {
authToken := p.options.AuthorizationToken
var err error
if p.options.AuthorizationTokenProvider != nil {
authToken, err = p.options.AuthorizationTokenProvider.GetToken()
if err != nil {
return "", err
}
}
if strings.ContainsAny(authToken, "\r\n") {
return "", fmt.Errorf("authorization token contains invalid newline sequence")
}
return authToken, nil
}