istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/security/authz/model/generator.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 "fmt" 19 "strings" 20 21 rbacpb "github.com/envoyproxy/go-control-plane/envoy/config/rbac/v3" 22 matcherpb "github.com/envoyproxy/go-control-plane/envoy/type/matcher/v3" 23 24 "istio.io/istio/pilot/pkg/networking/util" 25 "istio.io/istio/pilot/pkg/security/authz/matcher" 26 "istio.io/istio/pilot/pkg/xds/filters" 27 "istio.io/istio/pkg/config/security" 28 "istio.io/istio/pkg/spiffe" 29 ) 30 31 type generator interface { 32 permission(key, value string, forTCP bool) (*rbacpb.Permission, error) 33 principal(key, value string, forTCP bool, useAuthenticated bool) (*rbacpb.Principal, error) 34 } 35 36 type extendedGenerator interface { 37 extendedPermission(key string, value []string, forTCP bool) (*rbacpb.Permission, error) 38 extendedPrincipal(key string, value []string, forTCP bool) (*rbacpb.Principal, error) 39 } 40 41 type destIPGenerator struct{} 42 43 func (destIPGenerator) permission(_, value string, _ bool) (*rbacpb.Permission, error) { 44 cidrRange, err := util.AddrStrToCidrRange(value) 45 if err != nil { 46 return nil, err 47 } 48 return permissionDestinationIP(cidrRange), nil 49 } 50 51 func (destIPGenerator) principal(_, _ string, _ bool, _ bool) (*rbacpb.Principal, error) { 52 return nil, fmt.Errorf("unimplemented") 53 } 54 55 type destPortGenerator struct{} 56 57 func (destPortGenerator) permission(_, value string, _ bool) (*rbacpb.Permission, error) { 58 portValue, err := convertToPort(value) 59 if err != nil { 60 return nil, err 61 } 62 return permissionDestinationPort(portValue), nil 63 } 64 65 func (destPortGenerator) principal(_, _ string, _ bool, _ bool) (*rbacpb.Principal, error) { 66 return nil, fmt.Errorf("unimplemented") 67 } 68 69 type connSNIGenerator struct{} 70 71 func (connSNIGenerator) permission(_, value string, _ bool) (*rbacpb.Permission, error) { 72 m := matcher.StringMatcher(value) 73 return permissionRequestedServerName(m), nil 74 } 75 76 func (connSNIGenerator) principal(_, _ string, _ bool, _ bool) (*rbacpb.Principal, error) { 77 return nil, fmt.Errorf("unimplemented") 78 } 79 80 type envoyFilterGenerator struct{} 81 82 func (efg envoyFilterGenerator) permission(key, value string, _ bool) (*rbacpb.Permission, error) { 83 // Split key of format "experimental.envoy.filters.a.b[c]" to "envoy.filters.a.b" and "c". 84 parts := strings.SplitN(strings.TrimSuffix(strings.TrimPrefix(key, "experimental."), "]"), "[", 2) 85 86 if len(parts) != 2 { 87 return nil, fmt.Errorf("invalid key: %v", key) 88 } 89 90 // If value is of format [v], create a list matcher. 91 // Else, if value is of format v, create a string matcher. 92 if strings.HasPrefix(value, "[") && strings.HasSuffix(value, "]") { 93 m := matcher.MetadataListMatcher(parts[0], parts[1:], matcher.StringMatcher(strings.Trim(value, "[]")), false) 94 return permissionMetadata(m), nil 95 } 96 m := matcher.MetadataStringMatcher(parts[0], parts[1], matcher.StringMatcher(value)) 97 return permissionMetadata(m), nil 98 } 99 100 func (efg envoyFilterGenerator) extendedPermission(key string, values []string, _ bool) (*rbacpb.Permission, error) { 101 // Split key of format "experimental.envoy.filters.a.b[c]" to "envoy.filters.a.b" and "c". 102 parts := strings.SplitN(strings.TrimSuffix(strings.TrimPrefix(key, "experimental."), "]"), "[", 2) 103 104 if len(parts) != 2 { 105 return nil, fmt.Errorf("invalid key: %v", key) 106 } 107 108 matchers := []*matcherpb.ValueMatcher{} 109 for _, value := range values { 110 if strings.HasPrefix(value, "[") && strings.HasSuffix(value, "]") { 111 matchers = append(matchers, &matcherpb.ValueMatcher{ 112 MatchPattern: &matcherpb.ValueMatcher_ListMatch{ 113 ListMatch: &matcherpb.ListMatcher{ 114 MatchPattern: &matcherpb.ListMatcher_OneOf{ 115 OneOf: &matcherpb.ValueMatcher{ 116 MatchPattern: &matcherpb.ValueMatcher_StringMatch{ 117 StringMatch: matcher.StringMatcher(strings.Trim(value, "[]")), 118 }, 119 }, 120 }, 121 }, 122 }, 123 }) 124 } else { 125 matchers = append(matchers, &matcherpb.ValueMatcher{ 126 MatchPattern: &matcherpb.ValueMatcher_StringMatch{ 127 StringMatch: matcher.StringMatcher(value), 128 }, 129 }) 130 } 131 } 132 m := matcher.MetadataValueMatcher(parts[0], parts[1], matcher.OrMatcher(matchers)) 133 return permissionMetadata(m), nil 134 } 135 136 func (envoyFilterGenerator) principal(_, _ string, _ bool, _ bool) (*rbacpb.Principal, error) { 137 return nil, fmt.Errorf("unimplemented") 138 } 139 140 func (envoyFilterGenerator) extendedPrincipal(_ string, _ []string, _ bool) (*rbacpb.Principal, error) { 141 return nil, fmt.Errorf("unimplemented") 142 } 143 144 type srcIPGenerator struct{} 145 146 func (srcIPGenerator) permission(_, _ string, _ bool) (*rbacpb.Permission, error) { 147 return nil, fmt.Errorf("unimplemented") 148 } 149 150 func (srcIPGenerator) principal(_, value string, _ bool, _ bool) (*rbacpb.Principal, error) { 151 cidr, err := util.AddrStrToCidrRange(value) 152 if err != nil { 153 return nil, err 154 } 155 return principalDirectRemoteIP(cidr), nil 156 } 157 158 type remoteIPGenerator struct{} 159 160 func (remoteIPGenerator) permission(_, _ string, _ bool) (*rbacpb.Permission, error) { 161 return nil, fmt.Errorf("unimplemented") 162 } 163 164 func (remoteIPGenerator) principal(_, value string, _ bool, _ bool) (*rbacpb.Principal, error) { 165 cidr, err := util.AddrStrToCidrRange(value) 166 if err != nil { 167 return nil, err 168 } 169 return principalRemoteIP(cidr), nil 170 } 171 172 type srcNamespaceGenerator struct{} 173 174 func (srcNamespaceGenerator) permission(_, _ string, _ bool) (*rbacpb.Permission, error) { 175 return nil, fmt.Errorf("unimplemented") 176 } 177 178 func (srcNamespaceGenerator) principal(_, value string, _ bool, useAuthenticated bool) (*rbacpb.Principal, error) { 179 v := strings.Replace(value, "*", ".*", -1) 180 m := matcher.StringMatcherRegex(fmt.Sprintf(".*/ns/%s/.*", v)) 181 return principalAuthenticated(m, useAuthenticated), nil 182 } 183 184 type srcPrincipalGenerator struct{} 185 186 func (srcPrincipalGenerator) permission(_, _ string, _ bool) (*rbacpb.Permission, error) { 187 return nil, fmt.Errorf("unimplemented") 188 } 189 190 func (srcPrincipalGenerator) principal(key, value string, _ bool, useAuthenticated bool) (*rbacpb.Principal, error) { 191 m := matcher.StringMatcherWithPrefix(value, spiffe.URIPrefix) 192 return principalAuthenticated(m, useAuthenticated), nil 193 } 194 195 type requestPrincipalGenerator struct{} 196 197 func (requestPrincipalGenerator) permission(_, _ string, _ bool) (*rbacpb.Permission, error) { 198 return nil, fmt.Errorf("unimplemented") 199 } 200 201 func (requestPrincipalGenerator) extendedPermission(_ string, _ []string, _ bool) (*rbacpb.Permission, error) { 202 return nil, fmt.Errorf("unimplemented") 203 } 204 205 func (rpg requestPrincipalGenerator) principal(key, value string, forTCP bool, _ bool) (*rbacpb.Principal, error) { 206 if forTCP { 207 return nil, fmt.Errorf("%q is HTTP only", key) 208 } 209 m := matcher.MetadataStringMatcher(filters.AuthnFilterName, key, matcher.StringMatcher(value)) 210 return principalMetadata(m), nil 211 } 212 213 var matchAny = matcher.StringMatcherRegex(".+") 214 215 func (rpg requestPrincipalGenerator) extendedPrincipal(key string, values []string, forTCP bool) (*rbacpb.Principal, error) { 216 if forTCP { 217 return nil, fmt.Errorf("%q is HTTP only", key) 218 } 219 var or []*rbacpb.Principal 220 for _, value := range values { 221 // Use the last index of "/" since issuer may be an URL 222 idx := strings.LastIndex(value, "/") 223 found := idx >= 0 224 iss, sub := "", "" 225 if found { 226 iss, sub = value[:idx], value[idx+1:] 227 } else { 228 iss = value 229 } 230 var matchIss, matchSub *matcherpb.StringMatcher 231 switch { 232 case value == "*": 233 matchIss = matchAny 234 matchSub = matchAny 235 case strings.HasPrefix(value, "*"): 236 if found { 237 if iss == "*" { 238 matchIss = matchAny 239 } else { 240 matchIss = matcher.StringMatcherSuffix(strings.TrimPrefix(iss, "*"), false) 241 } 242 matchSub = matcher.StringMatcherExact(sub, false) 243 } else { 244 matchIss = matchAny 245 matchSub = matcher.StringMatcherSuffix(strings.TrimPrefix(value, "*"), false) 246 } 247 case strings.HasSuffix(value, "*"): 248 if found { 249 matchIss = matcher.StringMatcherExact(iss, false) 250 if sub == "*" { 251 matchSub = matchAny 252 } else { 253 matchSub = matcher.StringMatcherPrefix(strings.TrimSuffix(sub, "*"), false) 254 } 255 } else { 256 matchIss = matcher.StringMatcherPrefix(strings.TrimSuffix(value, "*"), false) 257 matchSub = matchAny 258 } 259 default: 260 matchSub = matcher.StringMatcherExact(sub, false) 261 matchIss = matcher.StringMatcherExact(iss, false) 262 } 263 im := MetadataStringMatcherForJWTClaim("iss", matchIss) 264 sm := MetadataStringMatcherForJWTClaim("sub", matchSub) 265 or = append(or, principalAnd([]*rbacpb.Principal{principalMetadata(im), principalMetadata(sm)})) 266 } 267 if len(or) == 1 { 268 return or[0], nil 269 } else if len(or) > 0 { 270 return principalOr(or), nil 271 } 272 return nil, nil 273 } 274 275 type requestAudiencesGenerator struct{} 276 277 func (requestAudiencesGenerator) permission(key, value string, forTCP bool) (*rbacpb.Permission, error) { 278 return requestPrincipalGenerator{}.permission(key, value, forTCP) 279 } 280 281 func (requestAudiencesGenerator) extendedPermission(key string, values []string, forTCP bool) (*rbacpb.Permission, error) { 282 return requestPrincipalGenerator{}.extendedPermission(key, values, forTCP) 283 } 284 285 func (rag requestAudiencesGenerator) principal(key, value string, forTCP bool, useAuthenticated bool) (*rbacpb.Principal, error) { 286 if forTCP { 287 return nil, fmt.Errorf("%q is HTTP only", key) 288 } 289 m := matcher.MetadataStringMatcher(filters.AuthnFilterName, key, matcher.StringMatcher(value)) 290 return principalMetadata(m), nil 291 } 292 293 func (rag requestAudiencesGenerator) extendedPrincipal(key string, values []string, forTCP bool) (*rbacpb.Principal, error) { 294 if forTCP { 295 return nil, fmt.Errorf("%q is HTTP only", key) 296 } 297 return principalMetadata(MetadataListValueMatcherForJWTClaims([]string{"aud"}, matcher.StringOrMatcher(values))), nil 298 } 299 300 type requestPresenterGenerator struct{} 301 302 func (requestPresenterGenerator) permission(key, value string, forTCP bool) (*rbacpb.Permission, error) { 303 return requestPrincipalGenerator{}.permission(key, value, forTCP) 304 } 305 306 func (requestPresenterGenerator) extendedPermission(key string, values []string, forTCP bool) (*rbacpb.Permission, error) { 307 return requestPrincipalGenerator{}.extendedPermission(key, values, forTCP) 308 } 309 310 func (rpg requestPresenterGenerator) principal(key, value string, forTCP bool, useAuthenticated bool) (*rbacpb.Principal, error) { 311 if forTCP { 312 return nil, fmt.Errorf("%q is HTTP only", key) 313 } 314 m := matcher.MetadataStringMatcher(filters.AuthnFilterName, key, matcher.StringMatcher(value)) 315 return principalMetadata(m), nil 316 } 317 318 func (rpg requestPresenterGenerator) extendedPrincipal(key string, values []string, forTCP bool) (*rbacpb.Principal, error) { 319 if forTCP { 320 return nil, fmt.Errorf("%q is HTTP only", key) 321 } 322 return principalMetadata(MetadataListValueMatcherForJWTClaims([]string{"azp"}, matcher.StringOrMatcher(values))), nil 323 } 324 325 type requestHeaderGenerator struct{} 326 327 func (requestHeaderGenerator) permission(_, _ string, _ bool) (*rbacpb.Permission, error) { 328 return nil, fmt.Errorf("unimplemented") 329 } 330 331 func (requestHeaderGenerator) principal(key, value string, forTCP bool, _ bool) (*rbacpb.Principal, error) { 332 if forTCP { 333 return nil, fmt.Errorf("%q is HTTP only", key) 334 } 335 336 header, err := extractNameInBrackets(strings.TrimPrefix(key, attrRequestHeader)) 337 if err != nil { 338 return nil, err 339 } 340 m := matcher.HeaderMatcher(header, value) 341 return principalHeader(m), nil 342 } 343 344 type requestClaimGenerator struct{} 345 346 func (requestClaimGenerator) permission(_, _ string, _ bool) (*rbacpb.Permission, error) { 347 return nil, fmt.Errorf("unimplemented") 348 } 349 350 func (requestClaimGenerator) extendedPermission(_ string, _ []string, _ bool) (*rbacpb.Permission, error) { 351 return nil, fmt.Errorf("unimplemented") 352 } 353 354 func (rcg requestClaimGenerator) principal(key, value string, forTCP bool, _ bool) (*rbacpb.Principal, error) { 355 if forTCP { 356 return nil, fmt.Errorf("%q is HTTP only", key) 357 } 358 359 claims, err := extractNameInNestedBrackets(strings.TrimPrefix(key, attrRequestClaims)) 360 if err != nil { 361 return nil, err 362 } 363 // Generate a metadata list matcher for the given path keys and value. 364 // On proxy side, the value should be of list type. 365 m := MetadataMatcherForJWTClaims(claims, matcher.StringMatcher(value), false) 366 return principalMetadata(m), nil 367 } 368 369 func (rcg requestClaimGenerator) extendedPrincipal(key string, values []string, forTCP bool) (*rbacpb.Principal, error) { 370 if forTCP { 371 return nil, fmt.Errorf("%q is HTTP only", key) 372 } 373 374 claims, err := extractNameInNestedBrackets(strings.TrimPrefix(key, attrRequestClaims)) 375 if err != nil { 376 return nil, err 377 } 378 m := MetadataListValueMatcherForJWTClaims(claims, matcher.StringOrMatcher(values)) 379 return principalMetadata(m), nil 380 } 381 382 type hostGenerator struct{} 383 384 func (hg hostGenerator) permission(key, value string, forTCP bool) (*rbacpb.Permission, error) { 385 if forTCP { 386 return nil, fmt.Errorf("%q is HTTP only", key) 387 } 388 389 return permissionHeader(matcher.HostMatcher(hostHeader, value)), nil 390 } 391 392 func (hostGenerator) principal(key, value string, forTCP bool, _ bool) (*rbacpb.Principal, error) { 393 return nil, fmt.Errorf("unimplemented") 394 } 395 396 type pathGenerator struct{} 397 398 func (g pathGenerator) permission(key, value string, forTCP bool) (*rbacpb.Permission, error) { 399 if forTCP { 400 return nil, fmt.Errorf("%q is HTTP only", key) 401 } 402 403 if security.ContainsPathTemplate(value) { 404 m := matcher.PathTemplateMatcher(value) 405 return permissionPathTemplate(m), nil 406 } 407 408 m := matcher.PathMatcher(value) 409 return permissionPath(m), nil 410 } 411 412 func (pathGenerator) principal(key, value string, forTCP bool, _ bool) (*rbacpb.Principal, error) { 413 return nil, fmt.Errorf("unimplemented") 414 } 415 416 type methodGenerator struct{} 417 418 func (methodGenerator) permission(key, value string, forTCP bool) (*rbacpb.Permission, error) { 419 if forTCP { 420 return nil, fmt.Errorf("%q is HTTP only", key) 421 } 422 423 m := matcher.HeaderMatcher(methodHeader, value) 424 return permissionHeader(m), nil 425 } 426 427 func (methodGenerator) principal(key, value string, forTCP bool, _ bool) (*rbacpb.Principal, error) { 428 return nil, fmt.Errorf("unimplemented") 429 }