|
|
@@ -15,6 +15,7 @@ import (
|
|
|
const AccessKeyAuthorizerType = "AWSAccessKey"
|
|
|
const ServiceAccountAuthorizerType = "AWSServiceAccount"
|
|
|
const AssumeRoleAuthorizerType = "AWSAssumeRole"
|
|
|
+const WebIdentityAuthorizerType = "WebIdentity"
|
|
|
|
|
|
// Authorizer implementations provide aws.Config for AWS SDK calls
|
|
|
type Authorizer interface {
|
|
|
@@ -31,6 +32,8 @@ func SelectAuthorizerByType(typeStr string) (Authorizer, error) {
|
|
|
return &ServiceAccount{}, nil
|
|
|
case AssumeRoleAuthorizerType:
|
|
|
return &AssumeRole{}, nil
|
|
|
+ case WebIdentityAuthorizerType:
|
|
|
+ return &WebIdentity{}, nil
|
|
|
default:
|
|
|
return nil, fmt.Errorf("AWS: provider authorizer type '%s' is not valid", typeStr)
|
|
|
}
|
|
|
@@ -129,11 +132,7 @@ func (sa *ServiceAccount) Equals(config cloud.Config) bool {
|
|
|
return false
|
|
|
}
|
|
|
_, ok := config.(*ServiceAccount)
|
|
|
- if !ok {
|
|
|
- return false
|
|
|
- }
|
|
|
-
|
|
|
- return true
|
|
|
+ return ok
|
|
|
}
|
|
|
|
|
|
func (sa *ServiceAccount) Sanitize() cloud.Config {
|
|
|
@@ -204,7 +203,7 @@ func (ara *AssumeRole) CreateAWSConfig(region string) (aws.Config, error) {
|
|
|
|
|
|
func (ara *AssumeRole) Validate() error {
|
|
|
if ara.Authorizer == nil {
|
|
|
- return fmt.Errorf("AssumeRole: misisng base Authorizer")
|
|
|
+ return fmt.Errorf("AssumeRole: missing base Authorizer")
|
|
|
}
|
|
|
err := ara.Authorizer.Validate()
|
|
|
if err != nil {
|
|
|
@@ -212,7 +211,7 @@ func (ara *AssumeRole) Validate() error {
|
|
|
}
|
|
|
|
|
|
if ara.RoleARN == "" {
|
|
|
- return fmt.Errorf("AssumeRole: misisng RoleARN configuration")
|
|
|
+ return fmt.Errorf("AssumeRole: missing RoleARN configuration")
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
@@ -249,3 +248,114 @@ func (ara *AssumeRole) Sanitize() cloud.Config {
|
|
|
RoleARN: ara.RoleARN,
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+type WebIdentity struct {
|
|
|
+ RoleARN string `json:"roleARN"`
|
|
|
+ IdentityProvider string `json:"identityProvider"`
|
|
|
+ TokenRetriever IDTokenRetriever `json:"tokenRetriever"`
|
|
|
+}
|
|
|
+
|
|
|
+func (wea *WebIdentity) CreateAWSConfig(region string) (aws.Config, error) {
|
|
|
+ cfg, err := awsconfig.LoadDefaultConfig(context.TODO(), awsconfig.WithRegion(region))
|
|
|
+ if err != nil {
|
|
|
+ return cfg, fmt.Errorf("failed to initialize AWS SDK config for region from annotation %s: %s", region, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ stsSvc := sts.NewFromConfig(cfg)
|
|
|
+ creds := stscreds.NewWebIdentityRoleProvider(stsSvc, wea.RoleARN, wea.TokenRetriever)
|
|
|
+
|
|
|
+ cfg.Credentials = aws.NewCredentialsCache(creds)
|
|
|
+ return cfg, nil
|
|
|
+}
|
|
|
+
|
|
|
+func (wea *WebIdentity) MarshalJSON() ([]byte, error) {
|
|
|
+ fmap := make(map[string]any, 1)
|
|
|
+ fmap[cloud.AuthorizerTypeProperty] = WebIdentityAuthorizerType
|
|
|
+ fmap["roleARN"] = wea.RoleARN
|
|
|
+ fmap["identityProvider"] = wea.IdentityProvider
|
|
|
+ fmap["tokenRetriever"] = wea.TokenRetriever
|
|
|
+ return json.Marshal(fmap)
|
|
|
+}
|
|
|
+
|
|
|
+func (wea *WebIdentity) UnmarshalJSON(b []byte) error {
|
|
|
+ var f interface{}
|
|
|
+ err := json.Unmarshal(b, &f)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ fmap := f.(map[string]interface{})
|
|
|
+
|
|
|
+ roleARN, err := cloud.GetInterfaceValue[string](fmap, "roleARN")
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("WebIdentity: UnmarshalJSON: %s", err.Error())
|
|
|
+ }
|
|
|
+ wea.RoleARN = roleARN
|
|
|
+
|
|
|
+ idp, err := cloud.GetInterfaceValue[string](fmap, "identityProvider")
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("WebIdentity: UnmarshalJSON: %s", err.Error())
|
|
|
+ }
|
|
|
+ wea.IdentityProvider = idp
|
|
|
+
|
|
|
+ var tr interface{}
|
|
|
+
|
|
|
+ tr, err = cloud.GetInterfaceValue[interface{}](fmap, "tokenRetriever")
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("WebIdentity: UnmarshalJSON: %s", err.Error())
|
|
|
+ }
|
|
|
+
|
|
|
+ trb, err := json.Marshal(tr)
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("WebIdentity: UnmarshalJSON: %s", err.Error())
|
|
|
+ }
|
|
|
+
|
|
|
+ var tokenRetriever IDTokenRetriever
|
|
|
+ switch idp {
|
|
|
+ case "Google":
|
|
|
+ tokenRetriever = &GoogleIDTokenRetriever{}
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ err = json.Unmarshal(trb, &tokenRetriever)
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("WebIdentity: UnmarshalJSON: %s", err.Error())
|
|
|
+ }
|
|
|
+
|
|
|
+ wea.TokenRetriever = tokenRetriever
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func (wea *WebIdentity) Validate() error {
|
|
|
+
|
|
|
+ if wea.RoleARN == "" {
|
|
|
+ return fmt.Errorf("WebIdentity: missing RoleARN configuration")
|
|
|
+ }
|
|
|
+
|
|
|
+ if wea.TokenRetriever == nil {
|
|
|
+ return fmt.Errorf("WebIdentity: missing TokenRetriever configuration")
|
|
|
+ }
|
|
|
+
|
|
|
+ return wea.TokenRetriever.Validate()
|
|
|
+}
|
|
|
+
|
|
|
+func (wea *WebIdentity) Equals(config cloud.Config) bool {
|
|
|
+ if config == nil {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ thatConfig, ok := config.(*WebIdentity)
|
|
|
+ if !ok {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+
|
|
|
+ return wea.RoleARN == thatConfig.RoleARN && wea.IdentityProvider == thatConfig.IdentityProvider && wea.TokenRetriever.Equals(thatConfig.TokenRetriever)
|
|
|
+}
|
|
|
+
|
|
|
+func (wea *WebIdentity) Sanitize() cloud.Config {
|
|
|
+ return &WebIdentity{
|
|
|
+ RoleARN: wea.RoleARN,
|
|
|
+ IdentityProvider: wea.IdentityProvider,
|
|
|
+ TokenRetriever: wea.TokenRetriever.Sanitize(),
|
|
|
+ }
|
|
|
+}
|