| 271 | } |
| 272 | |
| 273 | func doEvalBindingCondition(expr string, input map[string]any) (bool, error) { |
| 274 | if expr == "" { |
| 275 | return true, nil |
| 276 | } |
| 277 | |
| 278 | e, err := cel.NewEnv(IAMPolicyConditionCELAttributes...) |
| 279 | if err != nil { |
| 280 | return false, errors.Wrapf(err, "failed to new cel env") |
| 281 | } |
| 282 | ast, iss := e.Compile(expr) |
| 283 | if iss != nil && iss.Err() != nil { |
| 284 | return false, errors.Wrapf(iss.Err(), "failed to compile expr %q", expr) |
| 285 | } |
| 286 | // enable partial evaluation because the input only has request.time |
| 287 | // but the expression can have more. |
| 288 | prg, err := e.Program(ast, cel.EvalOptions(cel.OptPartialEval)) |
| 289 | if err != nil { |
| 290 | return false, errors.Wrapf(err, "failed to construct program") |
| 291 | } |
| 292 | vars, err := e.PartialVars(input) |
| 293 | if err != nil { |
| 294 | return false, errors.Wrapf(err, "failed to get vars") |
| 295 | } |
| 296 | out, _, err := prg.Eval(vars) |
| 297 | if err != nil { |
| 298 | return false, errors.Wrapf(err, "failed to eval cel expr") |
| 299 | } |
| 300 | // `out` is one of |
| 301 | // - True |
| 302 | // - False |
| 303 | // - a residual expression. |
| 304 | |
| 305 | // return true if the result is a residual expression |
| 306 | // which means that it passes "the request.time < xxx" check. |
| 307 | if !celtypes.IsBool(out) { |
| 308 | return true, nil |
| 309 | } |
| 310 | |
| 311 | res, ok := out.Equal(celtypes.True).Value().(bool) |
| 312 | if !ok { |
| 313 | return false, errors.Errorf("failed to convert cel result to bool") |
| 314 | } |
| 315 | return res, nil |
| 316 | } |