scheme.go raw

   1  package auth
   2  
   3  import (
   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
  13  const SigV4 = "sigv4"
  14  
  15  // SigV4A is a constant representing
  16  // Authentication Scheme Signature Version 4A
  17  const SigV4A = "sigv4a"
  18  
  19  // SigV4S3Express identifies the S3 S3Express auth scheme.
  20  const SigV4S3Express = "sigv4-s3express"
  21  
  22  // None is a constant representing the
  23  // None Authentication Scheme
  24  const None = "none"
  25  
  26  // SupportedSchemes is a data structure
  27  // that indicates the list of supported AWS
  28  // authentication schemes
  29  var 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
  38  type AuthenticationScheme interface {
  39  	isAuthenticationScheme()
  40  }
  41  
  42  // AuthenticationSchemeV4 is a AWS SigV4 representation
  43  type AuthenticationSchemeV4 struct {
  44  	Name                  string
  45  	SigningName           *string
  46  	SigningRegion         *string
  47  	DisableDoubleEncoding *bool
  48  }
  49  
  50  func (a *AuthenticationSchemeV4) isAuthenticationScheme() {}
  51  
  52  // AuthenticationSchemeV4A is a AWS SigV4A representation
  53  type AuthenticationSchemeV4A struct {
  54  	Name                  string
  55  	SigningName           *string
  56  	SigningRegionSet      []string
  57  	DisableDoubleEncoding *bool
  58  }
  59  
  60  func (a *AuthenticationSchemeV4A) isAuthenticationScheme() {}
  61  
  62  // AuthenticationSchemeNone is a representation for the none auth scheme
  63  type AuthenticationSchemeNone struct{}
  64  
  65  func (a *AuthenticationSchemeNone) isAuthenticationScheme() {}
  66  
  67  // NoAuthenticationSchemesFoundError is used in signaling
  68  // that no authentication schemes have been specified.
  69  type NoAuthenticationSchemesFoundError struct{}
  70  
  71  func (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.
  78  type UnSupportedAuthenticationSchemeSpecifiedError struct {
  79  	UnsupportedSchemes []string
  80  }
  81  
  82  func (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.
  88  func 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  
 136  type 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.
 143  func 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.
 152  func GetDisableDoubleEncoding(ctx context.Context) (value bool, ok bool) {
 153  	value, ok = middleware.GetStackValue(ctx, disableDoubleEncoding{}).(bool)
 154  	return value, ok
 155  }
 156  
 157  func 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  
 165  func 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  
 177  func 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  
 185  func getDisableDoubleEncoding(authScheme map[string]interface{}) *bool {
 186  	disableDoubleEncoding, ok := authScheme["disableDoubleEncoding"].(bool)
 187  	if !ok {
 188  		return nil
 189  	}
 190  	return &disableDoubleEncoding
 191  }
 192