github.com/verrazzano/verrazzano@v1.7.0/tools/oam-converter/pkg/resources/authorizationpolicy/authoizationpolicy.go (about)

     1  // Copyright (c) 2023, Oracle and/or its affiliates.
     2  // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
     3  
     4  package authorizationpolicy
     5  
     6  import (
     7  	"fmt"
     8  	vzapi "github.com/verrazzano/verrazzano/application-operator/apis/oam/v1alpha1"
     9  	"github.com/verrazzano/verrazzano/application-operator/constants"
    10  	consts "github.com/verrazzano/verrazzano/tools/oam-converter/pkg/constants"
    11  	"istio.io/api/security/v1beta1"
    12  	v1beta12 "istio.io/api/type/v1beta1"
    13  	clisecurity "istio.io/client-go/pkg/apis/security/v1beta1"
    14  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    15  	"strings"
    16  )
    17  
    18  // creates Authorization Policy
    19  func CreateAuthorizationPolicies(trait *vzapi.IngressTrait, rule vzapi.IngressRule, namePrefix string, hosts []string) (*clisecurity.AuthorizationPolicy, error) {
    20  
    21  	// If any path needs an AuthorizationPolicy then add one for every path
    22  	var addAuthPolicy bool
    23  	for _, path := range rule.Paths {
    24  		if path.Policy != nil {
    25  			addAuthPolicy = true
    26  		}
    27  	}
    28  	for _, path := range rule.Paths {
    29  		if addAuthPolicy {
    30  			requireFrom := true
    31  
    32  			// Add a policy rule if one is missing
    33  			if path.Policy == nil {
    34  				path.Policy = &vzapi.AuthorizationPolicy{
    35  					Rules: []*vzapi.AuthorizationRule{{}},
    36  				}
    37  				// No from field required, this is just a path being added
    38  				requireFrom = false
    39  			}
    40  
    41  			pathSuffix := strings.Replace(path.Path, "/", "", -1)
    42  			policyName := namePrefix
    43  			if pathSuffix != "" {
    44  				policyName = fmt.Sprintf("%s-%s", policyName, pathSuffix)
    45  			}
    46  
    47  			authzPolicy := &clisecurity.AuthorizationPolicy{
    48  				TypeMeta: metav1.TypeMeta{
    49  					Kind:       "AuthorizationPolicy",
    50  					APIVersion: consts.AuthorizationAPIVersion,
    51  				},
    52  				ObjectMeta: metav1.ObjectMeta{
    53  					Name:      policyName,
    54  					Namespace: constants.IstioSystemNamespace,
    55  					Labels:    map[string]string{constants.LabelIngressTraitNsn: getIngressTraitNsn(trait.Namespace, trait.Name)},
    56  				},
    57  			}
    58  			return mutateAuthorizationPolicy(authzPolicy, path.Policy, path.Path, hosts, requireFrom)
    59  		}
    60  	}
    61  	return nil, nil
    62  }
    63  
    64  // mutateAuthorizationPolicy changes the destination rule based upon a trait's configuration
    65  func mutateAuthorizationPolicy(authzPolicy *clisecurity.AuthorizationPolicy, vzPolicy *vzapi.AuthorizationPolicy, path string, hosts []string, requireFrom bool) (*clisecurity.AuthorizationPolicy, error) {
    66  	policyRules := make([]*v1beta1.Rule, len(vzPolicy.Rules))
    67  	var err error
    68  	for i, authzRule := range vzPolicy.Rules {
    69  		policyRules[i], err = createAuthorizationPolicyRule(authzRule, path, hosts, requireFrom)
    70  		if err != nil {
    71  			print(err)
    72  			return nil, err
    73  		}
    74  	}
    75  
    76  	authzPolicy.Spec = v1beta1.AuthorizationPolicy{
    77  		Selector: &v1beta12.WorkloadSelector{
    78  			MatchLabels: map[string]string{"istio": "ingressgateway"},
    79  		},
    80  		Rules: policyRules,
    81  	}
    82  
    83  	return authzPolicy, nil
    84  }
    85  
    86  // createAuthorizationPolicyRule uses the provided information to create an istio authorization policy rule
    87  func createAuthorizationPolicyRule(rule *vzapi.AuthorizationRule, path string, hosts []string, requireFrom bool) (*v1beta1.Rule, error) {
    88  	authzRule := v1beta1.Rule{}
    89  
    90  	if requireFrom && rule.From == nil {
    91  		return nil, fmt.Errorf("Authorization Policy requires 'From' clause")
    92  	}
    93  	if rule.From != nil {
    94  		authzRule.From = []*v1beta1.Rule_From{
    95  			{Source: &v1beta1.Source{
    96  				RequestPrincipals: rule.From.RequestPrincipals},
    97  			},
    98  		}
    99  	}
   100  
   101  	if len(path) > 0 {
   102  		authzRule.To = []*v1beta1.Rule_To{{
   103  			Operation: &v1beta1.Operation{
   104  				Hosts: hosts,
   105  				Paths: []string{path},
   106  			},
   107  		}}
   108  	}
   109  
   110  	if rule.When != nil {
   111  		conditions := []*v1beta1.Condition{}
   112  		for _, vzCondition := range rule.When {
   113  			condition := &v1beta1.Condition{
   114  				Key:    vzCondition.Key,
   115  				Values: vzCondition.Values,
   116  			}
   117  			conditions = append(conditions, condition)
   118  		}
   119  		authzRule.When = conditions
   120  	}
   121  
   122  	return &authzRule, nil
   123  }
   124  
   125  // Get Ingress Trait Namespace and name appended with "-"
   126  func getIngressTraitNsn(namespace string, name string) string {
   127  	return fmt.Sprintf("%s-%s", namespace, name)
   128  }