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 }