Skip to content

Commit

Permalink
add a configurable option to switch yaml parser between yaml and util…
Browse files Browse the repository at this point in the history
…yaml
  • Loading branch information
nnmin-aws committed Oct 11, 2022
1 parent f15f0fd commit f5b6e04
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 24 deletions.
1 change: 1 addition & 0 deletions cmd/aws-iam-authenticator/root.go
Expand Up @@ -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)
Expand Down
5 changes: 3 additions & 2 deletions pkg/config/types.go
Expand Up @@ -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
Expand Down Expand Up @@ -169,4 +169,5 @@ type Config struct {
// understand we don't need to change
EC2DescribeInstancesQps int
EC2DescribeInstancesBurst int
EKSYaml bool
}
33 changes: 21 additions & 12 deletions pkg/mapper/configmap/configmap.go
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions pkg/mapper/configmap/configmap_test.go
Expand Up @@ -17,6 +17,7 @@ import (

func init() {
config.SSORoleMatchEnabled = true
EKSYaml = true
}

var (
Expand Down
3 changes: 3 additions & 0 deletions pkg/mapper/configmap/mapper.go
Expand Up @@ -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
Expand Down
35 changes: 25 additions & 10 deletions pkg/mapper/configmap/yaml_test.go
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit f5b6e04

Please sign in to comment.