sigs.k8s.io/cluster-api-provider-aws@v1.5.5/pkg/cloud/services/iamauth/crd.go (about)

     1  /*
     2  Copyright 2020 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package iamauth
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  
    23  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    24  	kerrors "k8s.io/apimachinery/pkg/util/errors"
    25  	iamauthv1 "sigs.k8s.io/aws-iam-authenticator/pkg/mapper/crd/apis/iamauthenticator/v1alpha1"
    26  	crclient "sigs.k8s.io/controller-runtime/pkg/client"
    27  
    28  	ekscontrolplanev1 "sigs.k8s.io/cluster-api-provider-aws/controlplane/eks/api/v1beta1"
    29  )
    30  
    31  type crdBackend struct {
    32  	client crclient.Client
    33  }
    34  
    35  func (b *crdBackend) MapRole(mapping ekscontrolplanev1.RoleMapping) error {
    36  	ctx := context.TODO()
    37  
    38  	if errs := mapping.Validate(); errs != nil {
    39  		return kerrors.NewAggregate(errs)
    40  	}
    41  
    42  	mappingList := iamauthv1.IAMIdentityMappingList{}
    43  
    44  	if err := b.client.List(ctx, &mappingList); err != nil {
    45  		return fmt.Errorf("getting list of mappings: %w", err)
    46  	}
    47  
    48  	for _, existingMapping := range mappingList.Items {
    49  		existing := existingMapping
    50  		if roleMappingMatchesIAMMap(mapping, &existing) {
    51  			// We already have a mapping so do nothing
    52  			return nil
    53  		}
    54  	}
    55  
    56  	iamMapping := &iamauthv1.IAMIdentityMapping{
    57  		ObjectMeta: metav1.ObjectMeta{
    58  			Namespace:    metav1.NamespaceSystem,
    59  			GenerateName: "capa-iamauth-",
    60  		},
    61  		Spec: iamauthv1.IAMIdentityMappingSpec{
    62  			ARN:      mapping.RoleARN,
    63  			Username: mapping.UserName,
    64  			Groups:   mapping.Groups,
    65  		},
    66  	}
    67  
    68  	return b.client.Create(ctx, iamMapping)
    69  }
    70  
    71  func (b *crdBackend) MapUser(mapping ekscontrolplanev1.UserMapping) error {
    72  	ctx := context.TODO()
    73  
    74  	if errs := mapping.Validate(); errs != nil {
    75  		return kerrors.NewAggregate(errs)
    76  	}
    77  
    78  	mappingList := iamauthv1.IAMIdentityMappingList{}
    79  
    80  	if err := b.client.List(ctx, &mappingList); err != nil {
    81  		return fmt.Errorf("getting list of mappings: %w", err)
    82  	}
    83  
    84  	for _, existingMapping := range mappingList.Items {
    85  		existing := existingMapping
    86  		if userMappingMatchesIAMMap(mapping, &existing) {
    87  			// We already have a mapping so do nothing
    88  			return nil
    89  		}
    90  	}
    91  
    92  	iamMapping := &iamauthv1.IAMIdentityMapping{
    93  		ObjectMeta: metav1.ObjectMeta{
    94  			Namespace:    metav1.NamespaceSystem,
    95  			GenerateName: "capa-iamauth-",
    96  		},
    97  		Spec: iamauthv1.IAMIdentityMappingSpec{
    98  			ARN:      mapping.UserARN,
    99  			Username: mapping.UserName,
   100  			Groups:   mapping.Groups,
   101  		},
   102  	}
   103  
   104  	return b.client.Create(ctx, iamMapping)
   105  }
   106  
   107  func roleMappingMatchesIAMMap(mapping ekscontrolplanev1.RoleMapping, iamMapping *iamauthv1.IAMIdentityMapping) bool {
   108  	if mapping.RoleARN != iamMapping.Spec.ARN {
   109  		return false
   110  	}
   111  
   112  	if mapping.UserName != iamMapping.Spec.Username {
   113  		return false
   114  	}
   115  
   116  	if len(mapping.Groups) != len(iamMapping.Spec.Groups) {
   117  		return false
   118  	}
   119  
   120  	for _, mappingGroup := range mapping.Groups {
   121  		found := false
   122  		for _, iamGroup := range iamMapping.Spec.Groups {
   123  			if iamGroup == mappingGroup {
   124  				found = true
   125  			}
   126  		}
   127  		if !found {
   128  			return false
   129  		}
   130  	}
   131  
   132  	return true
   133  }
   134  
   135  func userMappingMatchesIAMMap(mapping ekscontrolplanev1.UserMapping, iamMapping *iamauthv1.IAMIdentityMapping) bool {
   136  	if mapping.UserARN != iamMapping.Spec.ARN {
   137  		return false
   138  	}
   139  
   140  	if mapping.UserName != iamMapping.Spec.Username {
   141  		return false
   142  	}
   143  
   144  	if len(mapping.Groups) != len(iamMapping.Spec.Groups) {
   145  		return false
   146  	}
   147  
   148  	for _, mappingGroup := range mapping.Groups {
   149  		found := false
   150  		for _, iamGroup := range iamMapping.Spec.Groups {
   151  			if iamGroup == mappingGroup {
   152  				found = true
   153  			}
   154  		}
   155  		if !found {
   156  			return false
   157  		}
   158  	}
   159  
   160  	return true
   161  }