1package auth
  2
  3import (
  4	"context"
  5	"fmt"
  6
  7	smithy "github.com/aws/smithy-go"
  8	"github.com/aws/smithy-go/middleware"
  9)
 10
 11// SigV4 is a constant representing
 12// Authentication Scheme Signature Version 4
 13const SigV4 = "sigv4"
 14
 15// SigV4A is a constant representing
 16// Authentication Scheme Signature Version 4A
 17const SigV4A = "sigv4a"
 18
 19// SigV4S3Express identifies the S3 S3Express auth scheme.
 20const SigV4S3Express = "sigv4-s3express"
 21
 22// None is a constant representing the
 23// None Authentication Scheme
 24const None = "none"
 25
 26// SupportedSchemes is a data structure
 27// that indicates the list of supported AWS
 28// authentication schemes
 29var SupportedSchemes = map[string]bool{
 30	SigV4:          true,
 31	SigV4A:         true,
 32	SigV4S3Express: true,
 33	None:           true,
 34}
 35
 36// AuthenticationScheme is a representation of
 37// AWS authentication schemes
 38type AuthenticationScheme interface {
 39	isAuthenticationScheme()
 40}
 41
 42// AuthenticationSchemeV4 is a AWS SigV4 representation
 43type AuthenticationSchemeV4 struct {
 44	Name                  string
 45	SigningName           *string
 46	SigningRegion         *string
 47	DisableDoubleEncoding *bool
 48}
 49
 50func (a *AuthenticationSchemeV4) isAuthenticationScheme() {}
 51
 52// AuthenticationSchemeV4A is a AWS SigV4A representation
 53type AuthenticationSchemeV4A struct {
 54	Name                  string
 55	SigningName           *string
 56	SigningRegionSet      []string
 57	DisableDoubleEncoding *bool
 58}
 59
 60func (a *AuthenticationSchemeV4A) isAuthenticationScheme() {}
 61
 62// AuthenticationSchemeNone is a representation for the none auth scheme
 63type AuthenticationSchemeNone struct{}
 64
 65func (a *AuthenticationSchemeNone) isAuthenticationScheme() {}
 66
 67// NoAuthenticationSchemesFoundError is used in signaling
 68// that no authentication schemes have been specified.
 69type NoAuthenticationSchemesFoundError struct{}
 70
 71func (e *NoAuthenticationSchemesFoundError) Error() string {
 72	return fmt.Sprint("No authentication schemes specified.")
 73}
 74
 75// UnSupportedAuthenticationSchemeSpecifiedError is used in
 76// signaling that only unsupported authentication schemes
 77// were specified.
 78type UnSupportedAuthenticationSchemeSpecifiedError struct {
 79	UnsupportedSchemes []string
 80}
 81
 82func (e *UnSupportedAuthenticationSchemeSpecifiedError) Error() string {
 83	return fmt.Sprint("Unsupported authentication scheme specified.")
 84}
 85
 86// GetAuthenticationSchemes extracts the relevant authentication scheme data
 87// into a custom strongly typed Go data structure.
 88func GetAuthenticationSchemes(p *smithy.Properties) ([]AuthenticationScheme, error) {
 89	var result []AuthenticationScheme
 90	if !p.Has("authSchemes") {
 91		return nil, &NoAuthenticationSchemesFoundError{}
 92	}
 93
 94	authSchemes, _ := p.Get("authSchemes").([]interface{})
 95
 96	var unsupportedSchemes []string
 97	for _, scheme := range authSchemes {
 98		authScheme, _ := scheme.(map[string]interface{})
 99
100		version := authScheme["name"].(string)
101		switch version {
102		case SigV4, SigV4S3Express:
103			v4Scheme := AuthenticationSchemeV4{
104				Name:                  version,
105				SigningName:           getSigningName(authScheme),
106				SigningRegion:         getSigningRegion(authScheme),
107				DisableDoubleEncoding: getDisableDoubleEncoding(authScheme),
108			}
109			result = append(result, AuthenticationScheme(&v4Scheme))
110		case SigV4A:
111			v4aScheme := AuthenticationSchemeV4A{
112				Name:                  SigV4A,
113				SigningName:           getSigningName(authScheme),
114				SigningRegionSet:      getSigningRegionSet(authScheme),
115				DisableDoubleEncoding: getDisableDoubleEncoding(authScheme),
116			}
117			result = append(result, AuthenticationScheme(&v4aScheme))
118		case None:
119			noneScheme := AuthenticationSchemeNone{}
120			result = append(result, AuthenticationScheme(&noneScheme))
121		default:
122			unsupportedSchemes = append(unsupportedSchemes, authScheme["name"].(string))
123			continue
124		}
125	}
126
127	if len(result) == 0 {
128		return nil, &UnSupportedAuthenticationSchemeSpecifiedError{
129			UnsupportedSchemes: unsupportedSchemes,
130		}
131	}
132
133	return result, nil
134}
135
136type disableDoubleEncoding struct{}
137
138// SetDisableDoubleEncoding sets or modifies the disable double encoding option
139// on the context.
140//
141// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
142// to clear all stack values.
143func SetDisableDoubleEncoding(ctx context.Context, value bool) context.Context {
144	return middleware.WithStackValue(ctx, disableDoubleEncoding{}, value)
145}
146
147// GetDisableDoubleEncoding retrieves the disable double encoding option
148// from the context.
149//
150// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
151// to clear all stack values.
152func GetDisableDoubleEncoding(ctx context.Context) (value bool, ok bool) {
153	value, ok = middleware.GetStackValue(ctx, disableDoubleEncoding{}).(bool)
154	return value, ok
155}
156
157func getSigningName(authScheme map[string]interface{}) *string {
158	signingName, ok := authScheme["signingName"].(string)
159	if !ok || signingName == "" {
160		return nil
161	}
162	return &signingName
163}
164
165func getSigningRegionSet(authScheme map[string]interface{}) []string {
166	untypedSigningRegionSet, ok := authScheme["signingRegionSet"].([]interface{})
167	if !ok {
168		return nil
169	}
170	signingRegionSet := []string{}
171	for _, item := range untypedSigningRegionSet {
172		signingRegionSet = append(signingRegionSet, item.(string))
173	}
174	return signingRegionSet
175}
176
177func getSigningRegion(authScheme map[string]interface{}) *string {
178	signingRegion, ok := authScheme["signingRegion"].(string)
179	if !ok || signingRegion == "" {
180		return nil
181	}
182	return &signingRegion
183}
184
185func getDisableDoubleEncoding(authScheme map[string]interface{}) *bool {
186	disableDoubleEncoding, ok := authScheme["disableDoubleEncoding"].(bool)
187	if !ok {
188		return nil
189	}
190	return &disableDoubleEncoding
191}