istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/model/authorization.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package model
    16  
    17  import (
    18  	"k8s.io/apimachinery/pkg/types"
    19  
    20  	authpb "istio.io/api/security/v1beta1"
    21  	"istio.io/istio/pkg/config/schema/gvk"
    22  )
    23  
    24  type AuthorizationPolicy struct {
    25  	Name        string                      `json:"name"`
    26  	Namespace   string                      `json:"namespace"`
    27  	Annotations map[string]string           `json:"annotations"`
    28  	Spec        *authpb.AuthorizationPolicy `json:"spec"`
    29  }
    30  
    31  func (ap *AuthorizationPolicy) NamespacedName() types.NamespacedName {
    32  	return types.NamespacedName{Name: ap.Name, Namespace: ap.Namespace}
    33  }
    34  
    35  // AuthorizationPolicies organizes AuthorizationPolicy by namespace.
    36  type AuthorizationPolicies struct {
    37  	// Maps from namespace to the Authorization policies.
    38  	NamespaceToPolicies map[string][]AuthorizationPolicy `json:"namespace_to_policies"`
    39  
    40  	// The name of the root namespace. Policy in the root namespace applies to workloads in all namespaces.
    41  	RootNamespace string `json:"root_namespace"`
    42  }
    43  
    44  // GetAuthorizationPolicies returns the AuthorizationPolicies for the given environment.
    45  func GetAuthorizationPolicies(env *Environment) *AuthorizationPolicies {
    46  	policy := &AuthorizationPolicies{
    47  		NamespaceToPolicies: map[string][]AuthorizationPolicy{},
    48  		RootNamespace:       env.Mesh().GetRootNamespace(),
    49  	}
    50  
    51  	policies := env.List(gvk.AuthorizationPolicy, NamespaceAll)
    52  	sortConfigByCreationTime(policies)
    53  	for _, config := range policies {
    54  		authzConfig := AuthorizationPolicy{
    55  			Name:        config.Name,
    56  			Namespace:   config.Namespace,
    57  			Annotations: config.Annotations,
    58  			Spec:        config.Spec.(*authpb.AuthorizationPolicy),
    59  		}
    60  		policy.NamespaceToPolicies[config.Namespace] = append(policy.NamespaceToPolicies[config.Namespace], authzConfig)
    61  	}
    62  
    63  	return policy
    64  }
    65  
    66  type AuthorizationPoliciesResult struct {
    67  	Custom []AuthorizationPolicy
    68  	Deny   []AuthorizationPolicy
    69  	Allow  []AuthorizationPolicy
    70  	Audit  []AuthorizationPolicy
    71  }
    72  
    73  // ListAuthorizationPolicies returns authorization policies applied to the workload in the given namespace.
    74  func (policy *AuthorizationPolicies) ListAuthorizationPolicies(selectionOpts WorkloadPolicyMatcher) AuthorizationPoliciesResult {
    75  	configs := AuthorizationPoliciesResult{}
    76  	if policy == nil {
    77  		return configs
    78  	}
    79  	rootNamespace := policy.RootNamespace
    80  	namespace := selectionOpts.Namespace
    81  	var lookupInNamespaces []string
    82  
    83  	if namespace != rootNamespace {
    84  		// Only check the root namespace if the (workload) namespace is not already the root namespace
    85  		// to avoid double inclusion.
    86  		lookupInNamespaces = []string{rootNamespace, namespace}
    87  	} else {
    88  		lookupInNamespaces = []string{namespace}
    89  	}
    90  
    91  	for _, ns := range lookupInNamespaces {
    92  		for _, config := range policy.NamespaceToPolicies[ns] {
    93  			spec := config.Spec
    94  
    95  			if selectionOpts.ShouldAttachPolicy(gvk.AuthorizationPolicy, config.NamespacedName(), spec) {
    96  				configs = updateAuthorizationPoliciesResult(configs, config)
    97  			}
    98  		}
    99  	}
   100  
   101  	return configs
   102  }
   103  
   104  func updateAuthorizationPoliciesResult(configs AuthorizationPoliciesResult, config AuthorizationPolicy) AuthorizationPoliciesResult {
   105  	log.Debugf("applying authorization policy %s.%s",
   106  		config.Namespace, config.Name)
   107  	switch config.Spec.GetAction() {
   108  	case authpb.AuthorizationPolicy_ALLOW:
   109  		configs.Allow = append(configs.Allow, config)
   110  	case authpb.AuthorizationPolicy_DENY:
   111  		configs.Deny = append(configs.Deny, config)
   112  	case authpb.AuthorizationPolicy_AUDIT:
   113  		configs.Audit = append(configs.Audit, config)
   114  	case authpb.AuthorizationPolicy_CUSTOM:
   115  		configs.Custom = append(configs.Custom, config)
   116  	default:
   117  		log.Errorf("ignored authorization policy %s.%s with unsupported action: %s",
   118  			config.Namespace, config.Name, config.Spec.GetAction())
   119  	}
   120  	return configs
   121  }