k8s.io/apiserver@v0.31.1/pkg/authentication/cel/mapper.go (about) 1 /* 2 Copyright 2023 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package cel 18 19 import ( 20 "context" 21 "fmt" 22 23 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 24 ) 25 26 var _ ClaimsMapper = &mapper{} 27 var _ UserMapper = &mapper{} 28 29 // mapper implements the ClaimsMapper and UserMapper interface. 30 type mapper struct { 31 compilationResults []CompilationResult 32 } 33 34 // CELMapper is a struct that holds the compiled expressions for 35 // username, groups, uid, extra, claimValidation and userValidation 36 type CELMapper struct { 37 Username ClaimsMapper 38 Groups ClaimsMapper 39 UID ClaimsMapper 40 Extra ClaimsMapper 41 ClaimValidationRules ClaimsMapper 42 UserValidationRules UserMapper 43 } 44 45 // NewClaimsMapper returns a new ClaimsMapper. 46 func NewClaimsMapper(compilationResults []CompilationResult) ClaimsMapper { 47 return &mapper{ 48 compilationResults: compilationResults, 49 } 50 } 51 52 // NewUserMapper returns a new UserMapper. 53 func NewUserMapper(compilationResults []CompilationResult) UserMapper { 54 return &mapper{ 55 compilationResults: compilationResults, 56 } 57 } 58 59 // EvalClaimMapping evaluates the given claim mapping expression and returns a EvaluationResult. 60 func (m *mapper) EvalClaimMapping(ctx context.Context, claims *unstructured.Unstructured) (EvaluationResult, error) { 61 results, err := m.eval(ctx, map[string]interface{}{claimsVarName: claims.Object}) 62 if err != nil { 63 return EvaluationResult{}, err 64 } 65 if len(results) != 1 { 66 return EvaluationResult{}, fmt.Errorf("expected 1 evaluation result, got %d", len(results)) 67 } 68 return results[0], nil 69 } 70 71 // EvalClaimMappings evaluates the given expressions and returns a list of EvaluationResult. 72 func (m *mapper) EvalClaimMappings(ctx context.Context, claims *unstructured.Unstructured) ([]EvaluationResult, error) { 73 return m.eval(ctx, map[string]interface{}{claimsVarName: claims.Object}) 74 } 75 76 // EvalUser evaluates the given user expressions and returns a list of EvaluationResult. 77 func (m *mapper) EvalUser(ctx context.Context, userInfo *unstructured.Unstructured) ([]EvaluationResult, error) { 78 return m.eval(ctx, map[string]interface{}{userVarName: userInfo.Object}) 79 } 80 81 func (m *mapper) eval(ctx context.Context, input map[string]interface{}) ([]EvaluationResult, error) { 82 evaluations := make([]EvaluationResult, len(m.compilationResults)) 83 84 for i, compilationResult := range m.compilationResults { 85 var evaluation = &evaluations[i] 86 evaluation.ExpressionAccessor = compilationResult.ExpressionAccessor 87 88 evalResult, _, err := compilationResult.Program.ContextEval(ctx, input) 89 if err != nil { 90 return nil, fmt.Errorf("expression '%s' resulted in error: %w", compilationResult.ExpressionAccessor.GetExpression(), err) 91 } 92 93 evaluation.EvalResult = evalResult 94 } 95 96 return evaluations, nil 97 }