ceph-csi/vendor/github.com/aws/aws-sdk-go-v2/service/internal/presigned-url/middleware.go
Rakshith R 4f0bb2315b rbd: add aws-sts-metdata encryption type
With Amazon STS and kubernetes cluster is configured with
OIDC identity provider, credentials to access Amazon KMS
can be fetched using oidc-token(serviceaccount token).
Each tenant/namespace needs to create a secret with aws region,
role and CMK ARN.
Ceph-CSI will assume the given role with oidc token and access
aws KMS, with given CMK to encrypt/decrypt DEK which will stored
in the image metdata.

Refer: https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html
Resolves: #2879

Signed-off-by: Rakshith R <rar@redhat.com>
2022-03-16 07:29:56 +00:00

111 lines
3.9 KiB
Go

package presignedurl
import (
"context"
"fmt"
awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware"
v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
"github.com/aws/smithy-go/middleware"
)
// URLPresigner provides the interface to presign the input parameters in to a
// presigned URL.
type URLPresigner interface {
// PresignURL presigns a URL.
PresignURL(ctx context.Context, srcRegion string, params interface{}) (*v4.PresignedHTTPRequest, error)
}
// ParameterAccessor provides an collection of accessor to for retrieving and
// setting the values needed to PresignedURL generation
type ParameterAccessor struct {
// GetPresignedURL accessor points to a function that retrieves a presigned url if present
GetPresignedURL func(interface{}) (string, bool, error)
// GetSourceRegion accessor points to a function that retrieves source region for presigned url
GetSourceRegion func(interface{}) (string, bool, error)
// CopyInput accessor points to a function that takes in an input, and returns a copy.
CopyInput func(interface{}) (interface{}, error)
// SetDestinationRegion accessor points to a function that sets destination region on api input struct
SetDestinationRegion func(interface{}, string) error
// SetPresignedURL accessor points to a function that sets presigned url on api input struct
SetPresignedURL func(interface{}, string) error
}
// Options provides the set of options needed by the presigned URL middleware.
type Options struct {
// Accessor are the parameter accessors used by this middleware
Accessor ParameterAccessor
// Presigner is the URLPresigner used by the middleware
Presigner URLPresigner
}
// AddMiddleware adds the Presign URL middleware to the middleware stack.
func AddMiddleware(stack *middleware.Stack, opts Options) error {
return stack.Initialize.Add(&presign{options: opts}, middleware.Before)
}
// RemoveMiddleware removes the Presign URL middleware from the stack.
func RemoveMiddleware(stack *middleware.Stack) error {
_, err := stack.Initialize.Remove((*presign)(nil).ID())
return err
}
type presign struct {
options Options
}
func (m *presign) ID() string { return "Presign" }
func (m *presign) HandleInitialize(
ctx context.Context, input middleware.InitializeInput, next middleware.InitializeHandler,
) (
out middleware.InitializeOutput, metadata middleware.Metadata, err error,
) {
// If PresignedURL is already set ignore middleware.
if _, ok, err := m.options.Accessor.GetPresignedURL(input.Parameters); err != nil {
return out, metadata, fmt.Errorf("presign middleware failed, %w", err)
} else if ok {
return next.HandleInitialize(ctx, input)
}
// If have source region is not set ignore middleware.
srcRegion, ok, err := m.options.Accessor.GetSourceRegion(input.Parameters)
if err != nil {
return out, metadata, fmt.Errorf("presign middleware failed, %w", err)
} else if !ok || len(srcRegion) == 0 {
return next.HandleInitialize(ctx, input)
}
// Create a copy of the original input so the destination region value can
// be added. This ensures that value does not leak into the original
// request parameters.
paramCpy, err := m.options.Accessor.CopyInput(input.Parameters)
if err != nil {
return out, metadata, fmt.Errorf("unable to create presigned URL, %w", err)
}
// Destination region is the API client's configured region.
dstRegion := awsmiddleware.GetRegion(ctx)
if err = m.options.Accessor.SetDestinationRegion(paramCpy, dstRegion); err != nil {
return out, metadata, fmt.Errorf("presign middleware failed, %w", err)
}
presignedReq, err := m.options.Presigner.PresignURL(ctx, srcRegion, paramCpy)
if err != nil {
return out, metadata, fmt.Errorf("unable to create presigned URL, %w", err)
}
// Update the original input with the presigned URL value.
if err = m.options.Accessor.SetPresignedURL(input.Parameters, presignedReq.URL); err != nil {
return out, metadata, fmt.Errorf("presign middleware failed, %w", err)
}
return next.HandleInitialize(ctx, input)
}