istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/serviceregistry/kube/controller/ambient/policies.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  // nolint: gocritic
    16  package ambient
    17  
    18  import (
    19  	"strings"
    20  
    21  	v1 "k8s.io/api/core/v1"
    22  
    23  	securityclient "istio.io/client-go/pkg/apis/security/v1beta1"
    24  	"istio.io/istio/pilot/pkg/features"
    25  	"istio.io/istio/pilot/pkg/model"
    26  	"istio.io/istio/pkg/kube/krt"
    27  	"istio.io/istio/pkg/slices"
    28  	"istio.io/istio/pkg/spiffe"
    29  	"istio.io/istio/pkg/workloadapi/security"
    30  )
    31  
    32  func PolicyCollections(
    33  	AuthzPolicies krt.Collection[*securityclient.AuthorizationPolicy],
    34  	PeerAuths krt.Collection[*securityclient.PeerAuthentication],
    35  	MeshConfig krt.Singleton[MeshConfig],
    36  	Waypoints krt.Collection[Waypoint],
    37  	Pods krt.Collection[*v1.Pod],
    38  ) (krt.Collection[model.WorkloadAuthorization], krt.Collection[model.WorkloadAuthorization]) {
    39  	AuthzDerivedPolicies := krt.NewCollection(AuthzPolicies, func(ctx krt.HandlerContext, i *securityclient.AuthorizationPolicy) *model.WorkloadAuthorization {
    40  		meshCfg := krt.FetchOne(ctx, MeshConfig.AsCollection())
    41  		pol := convertAuthorizationPolicy(meshCfg.GetRootNamespace(), i)
    42  		if pol == nil {
    43  			return nil
    44  		}
    45  		return &model.WorkloadAuthorization{Authorization: pol, LabelSelector: model.NewSelector(i.Spec.GetSelector().GetMatchLabels())}
    46  	}, krt.WithName("AuthzDerivedPolicies"))
    47  	PeerAuthDerivedPolicies := krt.NewCollection(PeerAuths, func(ctx krt.HandlerContext, i *securityclient.PeerAuthentication) *model.WorkloadAuthorization {
    48  		meshCfg := krt.FetchOne(ctx, MeshConfig.AsCollection())
    49  		pol := convertPeerAuthentication(meshCfg.GetRootNamespace(), i)
    50  		if pol == nil {
    51  			return nil
    52  		}
    53  		return &model.WorkloadAuthorization{
    54  			Authorization: pol,
    55  			LabelSelector: model.NewSelector(i.Spec.GetSelector().GetMatchLabels()),
    56  		}
    57  	}, krt.WithName("PeerAuthDerivedPolicies"))
    58  	ImplicitWaypointPolicies := krt.NewCollection(Waypoints, implicitWaypointPolicy, krt.WithName("DefaultAllowFromWaypointPolicies"))
    59  	DefaultPolicy := krt.NewSingleton[model.WorkloadAuthorization](func(ctx krt.HandlerContext) *model.WorkloadAuthorization {
    60  		if len(krt.Fetch(ctx, PeerAuths)) == 0 {
    61  			return nil
    62  		}
    63  		meshCfg := krt.FetchOne(ctx, MeshConfig.AsCollection())
    64  		// If there are any PeerAuthentications in our cache, send our static STRICT policy
    65  		return &model.WorkloadAuthorization{
    66  			LabelSelector: model.LabelSelector{},
    67  			Authorization: &security.Authorization{
    68  				Name:      staticStrictPolicyName,
    69  				Namespace: meshCfg.GetRootNamespace(),
    70  				Scope:     security.Scope_WORKLOAD_SELECTOR,
    71  				Action:    security.Action_DENY,
    72  				Groups: []*security.Group{
    73  					{
    74  						Rules: []*security.Rules{
    75  							{
    76  								Matches: []*security.Match{
    77  									{
    78  										NotPrincipals: []*security.StringMatch{
    79  											{
    80  												MatchType: &security.StringMatch_Presence{},
    81  											},
    82  										},
    83  									},
    84  								},
    85  							},
    86  						},
    87  					},
    88  				},
    89  			},
    90  		}
    91  	}, krt.WithName("DefaultPolicy"))
    92  	// Policies contains all of the policies we will send down to clients
    93  	Policies := krt.JoinCollection([]krt.Collection[model.WorkloadAuthorization]{
    94  		AuthzDerivedPolicies,
    95  		PeerAuthDerivedPolicies,
    96  		DefaultPolicy.AsCollection(),
    97  		ImplicitWaypointPolicies,
    98  	}, krt.WithName("Policies"))
    99  	return AuthzDerivedPolicies, Policies
   100  }
   101  
   102  func implicitWaypointPolicyName(waypoint *Waypoint) string {
   103  	if !features.DefaultAllowFromWaypoint || waypoint == nil || len(waypoint.ServiceAccounts) == 0 {
   104  		return ""
   105  	}
   106  	// use '_' character since those are illegal in k8s names
   107  	return "istio_allow_waypoint_" + waypoint.Namespace + "_" + waypoint.Name
   108  }
   109  
   110  func implicitWaypointPolicy(ctx krt.HandlerContext, waypoint Waypoint) *model.WorkloadAuthorization {
   111  	if !features.DefaultAllowFromWaypoint || len(waypoint.ServiceAccounts) == 0 {
   112  		return nil
   113  	}
   114  	return &model.WorkloadAuthorization{
   115  		Authorization: &security.Authorization{
   116  			Name:      implicitWaypointPolicyName(&waypoint),
   117  			Namespace: waypoint.Namespace,
   118  			// note: we don't actually use label selection; the names have an internally well-known format
   119  			// workload generation will append a reference to this
   120  			Scope:  security.Scope_WORKLOAD_SELECTOR,
   121  			Action: security.Action_ALLOW,
   122  			Groups: []*security.Group{{
   123  				Rules: []*security.Rules{
   124  					{
   125  						Matches: []*security.Match{
   126  							{
   127  								Principals: slices.Map(waypoint.ServiceAccounts, func(sa string) *security.StringMatch {
   128  									return &security.StringMatch{MatchType: &security.StringMatch_Exact{
   129  										Exact: strings.TrimPrefix(spiffe.MustGenSpiffeURI(waypoint.Namespace, sa), spiffe.URIPrefix),
   130  									}}
   131  								}),
   132  							},
   133  						},
   134  					},
   135  				},
   136  			}},
   137  		},
   138  	}
   139  }