Skip to content

Commit ebf9131

Browse files
CEL Dev Teamcopybara-github
authored andcommitted
<to be removed> this is not a CEL CL.
PiperOrigin-RevId: 971054056
1 parent c0ebb06 commit ebf9131

4 files changed

Lines changed: 140 additions & 4 deletions

File tree

tools/proto_to_predicate.cc

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,17 @@ class ProtoToPredicateBuilder final : private ExprFactory {
103103
}
104104
return e;
105105
}
106+
107+
// Returns either the path specified by the "match_path" annotation,
108+
// or the default path derived from the field name.
109+
Expr GetFieldPath(const Expr& base_expr,
110+
const ::google::protobuf::FieldDescriptor* field) {
111+
std::string match_path_val = GetMatchPath(field);
112+
if (!match_path_val.empty()) {
113+
return ParseAndBuildPath(match_path_val);
114+
}
115+
return NewSelect(NextId(), base_expr, field->name());
116+
}
106117
ExprId NextId() { return id_++; }
107118

108119
// ---------------------------------------------------------------------------
@@ -246,7 +257,7 @@ class ProtoToPredicateBuilder final : private ExprFactory {
246257
const FieldDescriptor* const value_field =
247258
field->message_type()->FindFieldByName("value");
248259

249-
Expr map_path = NewSelect(NextId(), base_expr, field->name());
260+
Expr map_path = GetFieldPath(base_expr, field);
250261

251262
struct MapEntry {
252263
const Message* message;
@@ -355,7 +366,7 @@ class ProtoToPredicateBuilder final : private ExprFactory {
355366
const Message& sub_message =
356367
reflection->GetRepeatedMessage(message, field, i);
357368
std::vector<Expr> sub_predicates;
358-
Expr sub_base = NewSelect(NextId(), base_expr, field->name());
369+
Expr sub_base = GetFieldPath(base_expr, field);
359370
CEL_RETURN_IF_ERROR(Walk(sub_message, sub_base, sub_predicates));
360371
message_asts.push_back(LogicalAnd(sub_predicates));
361372
}
@@ -426,11 +437,11 @@ class ProtoToPredicateBuilder final : private ExprFactory {
426437
}
427438
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
428439
const Message& sub_message = reflection->GetMessage(message, field);
429-
Expr field_path = NewSelect(NextId(), base_expr, field->name());
440+
Expr field_path = GetFieldPath(base_expr, field);
430441
CEL_RETURN_IF_ERROR(Walk(sub_message, field_path, predicates));
431442
} else {
432443
// Primitive field: base_expr.field == <value>
433-
Expr field_path = NewSelect(NextId(), base_expr, field->name());
444+
Expr field_path = GetFieldPath(base_expr, field);
434445
predicates.push_back(
435446
ConstructEquality(std::move(field_path),
436447
PrimitiveToExpr(message, reflection, field)));

tools/proto_to_predicate_test.cc

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,103 @@ INSTANTIATE_TEST_SUITE_P(
549549
.json_input = R"({ "destinations": [ { "tool": { } } ] })",
550550
.expected_unparsed = "true",
551551
},
552+
PolicyTestCase{
553+
.name = "AnnotatedSingularFieldInMessage",
554+
.json_input =
555+
R"({ "destinations": [ {
556+
"agent": {
557+
"id": "agent-007",
558+
"location": "us-central1"
559+
}
560+
} ] })",
561+
.expected_unparsed = "dest.agent.name == \"agent-007\" && "
562+
"custom.agent.location == \"us-central1\"",
563+
},
564+
PolicyTestCase{
565+
.name = "AnnotatedOneofPrimitiveField",
566+
.json_input =
567+
R"({ "destinations": [ {
568+
"ip": "192.168.1.1"
569+
} ] })",
570+
.expected_unparsed = "custom.ip == \"192.168.1.1\"",
571+
},
572+
PolicyTestCase{
573+
.name = "AnnotatedMapFieldPrimitive",
574+
.json_input =
575+
R"({ "destinations": [ {
576+
"tool": {
577+
"annotated_labels": {
578+
"cluster": "us-central1"
579+
}
580+
}
581+
} ] })",
582+
.expected_unparsed =
583+
"\"cluster\" in custom.labels && "
584+
"custom.labels[\"cluster\"] == \"us-central1\"",
585+
},
586+
PolicyTestCase{
587+
.name = "AnnotatedMapFieldMessage",
588+
.json_input =
589+
R"({ "destinations": [ {
590+
"tool": {
591+
"annotated_role_members": {
592+
"admin": {
593+
"all_users": true,
594+
"principals": ["alice_user"],
595+
"leader": "alice",
596+
"leaders": ["bob"]
597+
}
598+
}
599+
}
600+
} ] })",
601+
.expected_unparsed =
602+
"\"admin\" in custom.role_members && "
603+
"\"alice_user\" in custom.role_members[\"admin\"].principals "
604+
"&& "
605+
"custom.role_members[\"admin\"].all_users == true && "
606+
"custom.member.leader == \"alice\" && "
607+
"custom.member.leaders in [\"bob\"]",
608+
},
609+
PolicyTestCase{
610+
.name = "AnnotatedMessageField",
611+
.json_input =
612+
R"({ "destinations": [ {
613+
"tool": {
614+
"annotated_annotations": {
615+
"read_only_hint": true
616+
}
617+
}
618+
} ] })",
619+
.expected_unparsed =
620+
"custom.tool_annotations.read_only_hint == true",
621+
},
622+
PolicyTestCase{
623+
.name = "AnnotatedRepeatedMessageFieldSingle",
624+
.json_input =
625+
R"({ "destinations": [ {
626+
"tool": {
627+
"backup_agents": [
628+
{ "id": "agent-007" }
629+
]
630+
}
631+
} ] })",
632+
.expected_unparsed = "custom.backup_agents.name == \"agent-007\"",
633+
},
634+
PolicyTestCase{
635+
.name = "AnnotatedRepeatedMessageFieldMultiple",
636+
.json_input =
637+
R"({ "destinations": [ {
638+
"tool": {
639+
"backup_agents": [
640+
{ "id": "agent-007" },
641+
{ "id": "agent-008" }
642+
]
643+
}
644+
} ] })",
645+
.expected_unparsed =
646+
"custom.backup_agents.name == \"agent-007\" || "
647+
"custom.backup_agents.name == \"agent-008\"",
648+
},
552649
PolicyTestCase{
553650
.name = "MapEquality",
554651
.json_input =

tools/testdata/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ proto_library(
3232
name = "test_policy_proto",
3333
srcs = ["test_policy.proto"],
3434
visibility = ["//tools:__subpackages__"],
35+
deps = ["@com_google_protobuf//:descriptor_proto"],
3536
)
3637

3738
cc_proto_library(

tools/testdata/test_policy.proto

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,18 @@ edition = "2023";
1919

2020
package cel.cpp.tools;
2121

22+
import "google/protobuf/descriptor.proto";
23+
2224
option cc_enable_arenas = true;
2325

26+
extend google.protobuf.FieldOptions {
27+
string match_path = 51074;
28+
}
29+
2430
// Represents the targeted client agent.
2531
message Agent {
2632
string name = 1 [json_name = "id"];
33+
string location = 2 [(match_path) = "custom.agent.location"];
2734
}
2835

2936
// Specifies additional metadata tool annotations.
@@ -40,6 +47,10 @@ message Members {
4047
bool all_users = 3;
4148

4249
bool all_authenticated_users = 4;
50+
51+
string leader = 5 [(match_path) = "custom.member.leader"];
52+
53+
repeated string leaders = 6 [(match_path) = "custom.member.leaders"];
4354
}
4455

4556
// Represents a metadata tool block.
@@ -56,13 +67,29 @@ message Tool {
5667

5768
// A map with string keys representing roles and Member instances as values.
5869
map<string, Members> role_members = 4;
70+
71+
// A map with string keys representing roles and Member instances as values,
72+
// annotated with a match_path.
73+
map<string, Members> annotated_role_members = 5
74+
[(match_path) = "custom.role_members"];
75+
76+
// A string-to-string map, annotated with a match_path.
77+
map<string, string> annotated_labels = 6 [(match_path) = "custom.labels"];
78+
79+
// A non-repeated message field, annotated with a match_path.
80+
ToolAnnotations annotated_annotations = 7
81+
[(match_path) = "custom.tool_annotations"];
82+
83+
// A repeated message field, annotated with a match_path.
84+
repeated Agent backup_agents = 8 [(match_path) = "custom.backup_agents"];
5985
}
6086

6187
// Represents a policy mapping destination block.
6288
message Target {
6389
oneof kind {
6490
Agent agent = 1;
6591
Tool tool = 2;
92+
string ip = 3 [(match_path) = "custom.ip"];
6693
}
6794
}
6895

0 commit comments

Comments
 (0)