github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/pkg/inputvalidation/validators_cert_subject_mappings.go (about)

     1  package inputvalidation
     2  
     3  import (
     4  	"strings"
     5  
     6  	"github.com/kyma-incubator/compass/components/director/pkg/cert"
     7  	tenantEntity "github.com/kyma-incubator/compass/components/director/pkg/tenant"
     8  	"github.com/pkg/errors"
     9  )
    10  
    11  const (
    12  	// RuntimeType represents a runtime consumer type
    13  	RuntimeType = "Runtime"
    14  	// IntegrationSystemType represents a integration system consumer type
    15  	IntegrationSystemType = "Integration System"
    16  	// ApplicationType represents an application consumer type
    17  	ApplicationType = "Application"
    18  	// SuperAdminType represents a super admin consumer type, mainly used in local setup and E2E tests
    19  	SuperAdminType = "Super Admin"
    20  	// BusinessIntegrationType represents a business integration consumer type
    21  	BusinessIntegrationType = "Business Integration"
    22  	// ManagedApplicationProviderOperatorType represents a managed application provider operator consumer type
    23  	ManagedApplicationProviderOperatorType = "Managed Application Provider Operator"
    24  	// ManagedApplicationConsumerType represents a managed application consumer type
    25  	ManagedApplicationConsumerType = "Managed Application Consumer"
    26  	// LandscapeResourceOperatorType represents a landscape resource operator consumer type
    27  	LandscapeResourceOperatorType = "Landscape Resource Operator"
    28  	// TechnicalClient represents a technical client consumer type
    29  	TechnicalClient = "Technical Client"
    30  
    31  	// GlobalAccessLevel is an access level that is not tied to a specific tenant entity but rather it's used globally
    32  	GlobalAccessLevel = "global"
    33  )
    34  
    35  // SupportedConsumerTypes is a map of all supported consumer types
    36  var SupportedConsumerTypes = map[string]bool{
    37  	RuntimeType:                            true,
    38  	IntegrationSystemType:                  true,
    39  	ApplicationType:                        true,
    40  	SuperAdminType:                         true,
    41  	BusinessIntegrationType:                true,
    42  	ManagedApplicationProviderOperatorType: true,
    43  	ManagedApplicationConsumerType:         true,
    44  	LandscapeResourceOperatorType:          true,
    45  	TechnicalClient:                        true,
    46  }
    47  
    48  // SupportedAccessLevels is a map of all supported tenant access levels
    49  var SupportedAccessLevels = map[string]bool{
    50  	string(tenantEntity.Customer):      true,
    51  	string(tenantEntity.Account):       true,
    52  	string(tenantEntity.Subaccount):    true,
    53  	string(tenantEntity.Organization):  true,
    54  	string(tenantEntity.Folder):        true,
    55  	string(tenantEntity.ResourceGroup): true,
    56  	string(GlobalAccessLevel):          true,
    57  }
    58  
    59  type certMappingSubjectValidator struct{}
    60  type certMappingConsumerTypeValidator struct{}
    61  type certMappingTenantAccessLevelValidator struct{}
    62  
    63  // IsValidCertSubject is a custom validation rule that validates certificate subject mapping's subject input
    64  var IsValidCertSubject = &certMappingSubjectValidator{}
    65  
    66  // IsValidConsumerType is a custom validation rule that validates certificate subject mapping's consumer type input
    67  var IsValidConsumerType = &certMappingConsumerTypeValidator{}
    68  
    69  // AreTenantAccessLevelsValid  is a custom validation rule that validates certificate subject mapping's tenant access levels input
    70  var AreTenantAccessLevelsValid = &certMappingTenantAccessLevelValidator{}
    71  
    72  func (v *certMappingSubjectValidator) Validate(value interface{}) error {
    73  	s, isNil, err := ensureIsString(value)
    74  	if err != nil {
    75  		return err
    76  	}
    77  	if isNil {
    78  		return nil
    79  	}
    80  
    81  	expectedSubjectComponents := strings.Split(s, ",")
    82  	if len(expectedSubjectComponents) < 5 { // 5 because that's the number of certificate relative distinguished names that we expect - CountryName(C), Organization(O), OrganizationalUnit(OU), Locality(L) and CommonName(CN)
    83  		return errors.Errorf("the number of certificate attributes are different than the expected ones. We got: %d and we need at least 5 - C, O, OU, L and CN", len(expectedSubjectComponents))
    84  	}
    85  
    86  	if country := cert.GetCountry(s); country == "" {
    87  		return errors.New("missing Country property in the subject")
    88  	}
    89  
    90  	if org := cert.GetOrganization(s); org == "" {
    91  		return errors.New("missing Organization property in the subject")
    92  	}
    93  
    94  	OUs := cert.GetAllOrganizationalUnits(s)
    95  	if len(OUs) < 1 {
    96  		return errors.New("missing Organization Unit property in the subject")
    97  	}
    98  
    99  	if locality := cert.GetLocality(s); locality == "" {
   100  		return errors.New("missing Locality property in the subject")
   101  	}
   102  
   103  	if cm := cert.GetCommonName(s); cm == "" {
   104  		return errors.New("missing Common Name property in the subject")
   105  	}
   106  
   107  	return nil
   108  }
   109  
   110  func (v certMappingConsumerTypeValidator) Validate(value interface{}) error {
   111  	consumerType, isNil, err := ensureIsString(value)
   112  	if err != nil {
   113  		return err
   114  	}
   115  	if isNil {
   116  		return nil
   117  	}
   118  
   119  	if !SupportedConsumerTypes[consumerType] {
   120  		return errors.Errorf("consumer type %s is not valid", consumerType)
   121  	}
   122  
   123  	return nil
   124  }
   125  
   126  func (v certMappingTenantAccessLevelValidator) Validate(value interface{}) error {
   127  	tenantAccessLevels, ok := value.([]string)
   128  	if !ok {
   129  		return errors.Errorf("invalid type, expected []string, got: %T", value)
   130  	}
   131  
   132  	for _, al := range tenantAccessLevels {
   133  		if !SupportedAccessLevels[al] {
   134  			return errors.Errorf("tenant access level %s is not valid", al)
   135  		}
   136  	}
   137  
   138  	return nil
   139  }