diff --git a/cmd/aws-iam-authenticator/root.go b/cmd/aws-iam-authenticator/root.go index ac741936f..435ad1630 100644 --- a/cmd/aws-iam-authenticator/root.go +++ b/cmd/aws-iam-authenticator/root.go @@ -102,6 +102,7 @@ func getConfig() (config.Config, error) { EC2DescribeInstancesQps: viper.GetInt("server.ec2DescribeInstancesQps"), EC2DescribeInstancesBurst: viper.GetInt("server.ec2DescribeInstancesBurst"), ScrubbedAWSAccounts: viper.GetStringSlice("server.scrubbedAccounts"), + EKSYaml: viper.GetBool("server.eksyaml"), } if err := viper.UnmarshalKey("server.mapRoles", &cfg.RoleMappings); err != nil { return cfg, fmt.Errorf("invalid server role mappings: %v", err) diff --git a/pkg/config/types.go b/pkg/config/types.go index 5d056aafe..16da2cc36 100644 --- a/pkg/config/types.go +++ b/pkg/config/types.go @@ -32,8 +32,8 @@ type IdentityMapping struct { // list of Kubernetes groups. The username and groups are specified as templates // that may optionally contain two template parameters: // -// 1) "{{AccountID}}" is the 12 digit AWS ID. -// 2) "{{SessionName}}" is the role session name. +// 1. "{{AccountID}}" is the 12 digit AWS ID. +// 2. "{{SessionName}}" is the role session name. // // The meaning of SessionName depends on the type of entity assuming the role. // In the case of an EC2 instance role this will be the EC2 instance ID. In the @@ -169,4 +169,5 @@ type Config struct { // understand we don't need to change EC2DescribeInstancesQps int EC2DescribeInstancesBurst int + EKSYaml bool } diff --git a/pkg/mapper/configmap/configmap.go b/pkg/mapper/configmap/configmap.go index 350cab0c6..6edbea783 100644 --- a/pkg/mapper/configmap/configmap.go +++ b/pkg/mapper/configmap/configmap.go @@ -115,15 +115,19 @@ func ParseMap(m map[string]string) (userMappings []config.UserMapping, roleMappi rawUserMappings := make([]config.UserMapping, 0) userMappings = make([]config.UserMapping, 0) if userData, ok := m["mapUsers"]; ok { - userJson, err := utilyaml.ToJSON([]byte(userData)) + if EKSYaml { + //use Lenient Yaml Parser + err = yaml.Unmarshal([]byte(userData), &rawUserMappings) + } else { + //use Strict Yaml Parser + userJson, err := utilyaml.ToJSON([]byte(userData)) + if err == nil { + err = json.Unmarshal(userJson, &rawUserMappings) + } + } if err != nil { errs = append(errs, err) } else { - err = json.Unmarshal(userJson, &rawUserMappings) - if err != nil { - errs = append(errs, err) - } - for _, userMapping := range rawUserMappings { err = userMapping.Validate() if err != nil { @@ -138,15 +142,20 @@ func ParseMap(m map[string]string) (userMappings []config.UserMapping, roleMappi rawRoleMappings := make([]config.RoleMapping, 0) roleMappings = make([]config.RoleMapping, 0) if roleData, ok := m["mapRoles"]; ok { - roleJson, err := utilyaml.ToJSON([]byte(roleData)) - if err != nil { - errs = append(errs, err) + if EKSYaml { + //use Lenient Yaml Parser + err = yaml.Unmarshal([]byte(roleData), &rawRoleMappings) } else { - err = json.Unmarshal(roleJson, &rawRoleMappings) - if err != nil { - errs = append(errs, err) + //use Strict Yaml Parser + roleJson, err := utilyaml.ToJSON([]byte(roleData)) + if err == nil { + err = json.Unmarshal(roleJson, &rawRoleMappings) } + } + if err != nil { + errs = append(errs, err) + } else { for _, roleMapping := range rawRoleMappings { err = roleMapping.Validate() if err != nil { diff --git a/pkg/mapper/configmap/configmap_test.go b/pkg/mapper/configmap/configmap_test.go index ff6bb64fd..d0103ae41 100644 --- a/pkg/mapper/configmap/configmap_test.go +++ b/pkg/mapper/configmap/configmap_test.go @@ -17,6 +17,7 @@ import ( func init() { config.SSORoleMatchEnabled = true + EKSYaml = true } var ( diff --git a/pkg/mapper/configmap/mapper.go b/pkg/mapper/configmap/mapper.go index 6088bd34c..ff0c33c4d 100644 --- a/pkg/mapper/configmap/mapper.go +++ b/pkg/mapper/configmap/mapper.go @@ -13,7 +13,10 @@ type ConfigMapMapper struct { var _ mapper.Mapper = &ConfigMapMapper{} +var EKSYaml = false + func NewConfigMapMapper(cfg config.Config) (*ConfigMapMapper, error) { + EKSYaml = cfg.EKSYaml ms, err := New(cfg.Master, cfg.Kubeconfig) if err != nil { return nil, err diff --git a/pkg/mapper/configmap/yaml_test.go b/pkg/mapper/configmap/yaml_test.go index 81222b4fc..1a9e15ca5 100644 --- a/pkg/mapper/configmap/yaml_test.go +++ b/pkg/mapper/configmap/yaml_test.go @@ -21,6 +21,11 @@ import ( var log = logrus.New() +func init() { + config.SSORoleMatchEnabled = true + EKSYaml = true +} + func TestConfigMap(t *testing.T) { log.Level = logrus.DebugLevel @@ -56,16 +61,6 @@ func TestConfigMap(t *testing.T) { // Valid aws-auth.yaml based on one in EKS documentation. "aws-auth.yaml", validRoleMappings, validUserMappings, validAWSAccounts, false, }, - { - // RoLeArN instead of rolearn - // parsing succeeds, values are case-insensitive for compatibility with upstream - "aws-auth-crazy-case-keys.yaml", validRoleMappings, validUserMappings, validAWSAccounts, false, - }, - { - // roleARN instead of rolearn - // parsing succeeds, values are case-insensitive for compatibility with upstream - "aws-auth-open-source-case-keys.yaml", validRoleMappings, validUserMappings, validAWSAccounts, false, - }, // Fail cases -- ideally, validation should reject these before they reach us { // mapusers instead of mapUsers @@ -94,6 +89,26 @@ func TestConfigMap(t *testing.T) { "aws-auth-missing-bar.yaml", nil, nil, nil, true, }, } + if !EKSYaml { + tests = append(tests, []struct { + configMapYaml string + expectedRoleMappings []config.RoleMapping + expectedUserMappings []config.UserMapping + expectedAWSAccounts map[string]bool + expectCreateError bool + }{ + { + // RoLeArN instead of rolearn + // parsing succeeds, values are case-insensitive for compatibility with upstream + "aws-auth-crazy-case-keys.yaml", validRoleMappings, validUserMappings, validAWSAccounts, false, + }, + { + // roleARN instead of rolearn + // parsing succeeds, values are case-insensitive for compatibility with upstream + "aws-auth-open-source-case-keys.yaml", validRoleMappings, validUserMappings, validAWSAccounts, false, + }, + }...) + } for _, tt := range tests { t.Run(tt.configMapYaml, func(t *testing.T) {