Skip to content

Commit 027f4ce

Browse files
committed
santactl/sync: Add ability to ingest CEL rules.
This covers `santactl rule`, syncing, and StaticRules.
1 parent f2fd267 commit 027f4ce

11 files changed

Lines changed: 79 additions & 24 deletions

File tree

MODULE.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ bazel_dep(name = "xxhash", version = "0.8.2")
1515
bazel_dep(name = "protos", version = "1.0.1", repo_name = "northpolesec_protos")
1616
git_override(
1717
module_name = "protos",
18-
commit = "bd61ba67c96bb8983e1b1ecf51f0af0d9308ac63",
18+
commit = "547a10d6b2e0502af11d54368a74c3b128715223",
1919
remote = "https://github.com/northpolesec/protos",
2020
)
2121

Source/common/SNTRule.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@
8282
state:(SNTRuleState)state
8383
type:(SNTRuleType)type
8484
customMsg:(NSString *)customMsg
85-
customURL:(NSString *)customURL;
85+
customURL:(NSString *)customURL
86+
celExpr:(NSString *)celExpr;
8687

8788
///
8889
/// Initialize with a default timestamp: current time if rule state is transitive, 0 otherwise.

Source/common/SNTRule.m

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,15 +166,16 @@ - (instancetype)initWithIdentifier:(NSString *)identifier
166166
state:(SNTRuleState)state
167167
type:(SNTRuleType)type
168168
customMsg:(NSString *)customMsg
169-
customURL:(NSString *)customURL {
169+
customURL:(NSString *)customURL
170+
celExpr:(NSString *)celExpr {
170171
self = [self initWithIdentifier:identifier
171172
state:state
172173
type:type
173174
customMsg:customMsg
174175
customURL:customURL
175176
timestamp:0
176177
comment:nil
177-
celExpr:nil
178+
celExpr:celExpr
178179
error:nil];
179180
// Initialize timestamp to current time if rule is transitive.
180181
if (self && state == SNTRuleStateAllowTransitive) {
@@ -186,7 +187,15 @@ - (instancetype)initWithIdentifier:(NSString *)identifier
186187
- (instancetype)initWithIdentifier:(NSString *)identifier
187188
state:(SNTRuleState)state
188189
type:(SNTRuleType)type {
189-
return [self initWithIdentifier:identifier state:state type:type customMsg:nil customURL:nil];
190+
return [self initWithIdentifier:identifier
191+
state:state
192+
type:type
193+
customMsg:nil
194+
customURL:nil
195+
timestamp:0
196+
comment:nil
197+
celExpr:nil
198+
error:nil];
190199
}
191200

192201
// lowercase policy keys and upper case the policy decision.
@@ -254,6 +263,8 @@ - (instancetype)initWithDictionary:(NSDictionary *)rawDict error:(NSError **)err
254263
state = SNTRuleStateSilentBlock;
255264
} else if ([policyString isEqual:kRulePolicyRemove]) {
256265
state = SNTRuleStateRemove;
266+
} else if ([policyString isEqual:kRulePolicyCEL]) {
267+
state = SNTRuleStateCEL;
257268
} else {
258269
[SNTError populateError:error
259270
withCode:SNTErrorCodeRuleInvalidPolicy
@@ -301,14 +312,19 @@ - (instancetype)initWithDictionary:(NSDictionary *)rawDict error:(NSError **)err
301312
comment = nil;
302313
}
303314

315+
NSString *celExpr = dict[kRuleCELExpr];
316+
if (![celExpr isKindOfClass:[NSString class]] || celExpr.length == 0) {
317+
celExpr = nil;
318+
}
319+
304320
return [self initWithIdentifier:identifier
305321
state:state
306322
type:type
307323
customMsg:customMsg
308324
customURL:customURL
309325
timestamp:0
310326
comment:comment
311-
celExpr:nil
327+
celExpr:celExpr
312328
error:error];
313329
}
314330

@@ -354,6 +370,7 @@ - (NSString *)ruleStateToPolicyString:(SNTRuleState)state {
354370
case SNTRuleStateAllowTransitive: return @"AllowTransitive";
355371
case SNTRuleStateAllowLocalBinary: return kRulePolicyAllowlistLocalBinary;
356372
case SNTRuleStateAllowLocalSigningID: return kRulePolicyAllowlistLocalSigningID;
373+
case SNTRuleStateCEL: return kRulePolicyCEL;
357374
// This should never be hit. But is here for completion.
358375
default: return @"Unknown";
359376
}
@@ -381,6 +398,7 @@ - (NSDictionary *)dictionaryRepresentation {
381398
kRuleCustomMsg : self.customMsg ?: @"",
382399
kRuleCustomURL : self.customURL ?: @"",
383400
kRuleComment : self.comment ?: @"",
401+
kRuleCELExpr : self.celExpr ?: @"",
384402
};
385403
}
386404

@@ -399,6 +417,7 @@ - (NSUInteger)hash {
399417
result = prime * result + self.state;
400418
result = prime * result + self.type;
401419
result = prime * result + [self.celExpr hash];
420+
result = prime * result + [self.celExpr hash];
402421
return result;
403422
}
404423

Source/common/SNTSyncConstants.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ extern NSString *const kRulePolicyBlocklistDeprecated;
126126
extern NSString *const kRulePolicySilentBlocklist;
127127
extern NSString *const kRulePolicySilentBlocklistDeprecated;
128128
extern NSString *const kRulePolicyRemove;
129+
extern NSString *const kRulePolicyCEL;
129130
extern NSString *const kRuleType;
130131
extern NSString *const kRuleTypeBinary;
131132
extern NSString *const kRuleTypeCertificate;
@@ -135,6 +136,7 @@ extern NSString *const kRuleTypeCDHash;
135136
extern NSString *const kRuleCustomMsg;
136137
extern NSString *const kRuleCustomURL;
137138
extern NSString *const kRuleComment;
139+
extern NSString *const kRuleCELExpr;
138140
extern NSString *const kCursor;
139141

140142
extern NSString *const kBackoffInterval;

Source/common/SNTSyncConstants.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
NSString *const kRulePolicySilentBlocklist = @"SILENT_BLOCKLIST";
128128
NSString *const kRulePolicySilentBlocklistDeprecated = @"SILENT_BLACKLIST";
129129
NSString *const kRulePolicyRemove = @"REMOVE";
130+
NSString *const kRulePolicyCEL = @"CEL";
130131
NSString *const kRuleType = @"rule_type";
131132
NSString *const kRuleTypeBinary = @"BINARY";
132133
NSString *const kRuleTypeCertificate = @"CERTIFICATE";
@@ -136,6 +137,7 @@
136137
NSString *const kRuleCustomMsg = @"custom_msg";
137138
NSString *const kRuleCustomURL = @"custom_url";
138139
NSString *const kRuleComment = @"comment";
140+
NSString *const kRuleCELExpr = @"cel_expr";
139141
NSString *const kCursor = @"cursor";
140142

141143
NSString *const kBackoffInterval = @"backoff";

Source/common/cel/Activation.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,23 @@
3232
#include "eval/public/activation.h"
3333
#pragma clang diagnostic pop
3434

35-
namespace cel_runtime = ::google::api::expr::runtime;
36-
namespace pbv1 = ::santa::cel::v1;
37-
3835
namespace santa {
3936
namespace cel {
4037

4138
// SantaActivation is a CEL activation that provides lookups of values from the
4239
// santa.pb.cel.v1.Context message, and easy access to variables for return values.
43-
class Activation : public ::cel_runtime::BaseActivation {
40+
class Activation : public ::google::api::expr::runtime::BaseActivation {
4441
public:
45-
Activation(std::unique_ptr<::pbv1::ExecutableFile> file, std::vector<std::string> (^args)(),
46-
std::map<std::string, std::string> (^envs)())
42+
Activation(std::unique_ptr<::santa::cel::v1::ExecutableFile> file,
43+
std::vector<std::string> (^args)(), std::map<std::string, std::string> (^envs)())
4744
: file_(std::move(file)), args_(args), envs_(envs) {};
4845
~Activation() = default;
4946

50-
std::optional<cel_runtime::CelValue> FindValue(absl::string_view name,
51-
google::protobuf::Arena *arena) const override;
47+
std::optional<::google::api::expr::runtime::CelValue> FindValue(
48+
absl::string_view name, google::protobuf::Arena *arena) const override;
5249

5350
// Activation does not support lazy-loaded functions.
54-
std::vector<const cel_runtime::CelFunction *> FindFunctionOverloads(
51+
std::vector<const ::google::api::expr::runtime::CelFunction *> FindFunctionOverloads(
5552
absl::string_view) const override {
5653
return {};
5754
}
@@ -72,11 +69,14 @@ class Activation : public ::cel_runtime::BaseActivation {
7269
const google::protobuf::Descriptor *messageType);
7370

7471
template <typename T>
75-
static cel_runtime::CelValue CELValue(const T &v, google::protobuf::Arena *arena);
72+
static ::google::api::expr::runtime::CelValue CELValue(const T &v,
73+
google::protobuf::Arena *arena);
7674
template <typename T>
77-
static cel_runtime::CelValue CELValue(const std::vector<T> &v, google::protobuf::Arena *arena);
75+
static ::google::api::expr::runtime::CelValue CELValue(const std::vector<T> &v,
76+
google::protobuf::Arena *arena);
7877
template <typename K, typename V>
79-
static cel_runtime::CelValue CELValue(const std::map<K, V> &v, google::protobuf::Arena *arena);
78+
static ::google::api::expr::runtime::CelValue CELValue(const std::map<K, V> &v,
79+
google::protobuf::Arena *arena);
8080
};
8181

8282
} // namespace cel

Source/common/cel/Activation.mm

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
std::optional<cel_runtime::CelValue> Activation::FindValue(absl::string_view name,
8585
google::protobuf::Arena *arena) const {
8686
// Handle the ReturnValue values.
87-
auto retDescriptor = pbv1::ReturnValue_descriptor();
87+
auto retDescriptor = santa::cel::v1::ReturnValue_descriptor();
8888
auto retValue = retDescriptor->FindValueByName(name);
8989
if (retValue != nullptr) {
9090
return CELValue(retValue->number(), arena);
@@ -109,14 +109,14 @@
109109
// ALLOWLIST or BLOCKLIST in their CEL expressions without having to use the
110110
// proto package name prefix. Start from value number 1 to avoid the
111111
// UNSPECIFIED value.
112-
auto retDescriptor = pbv1::ReturnValue_descriptor();
112+
auto retDescriptor = ::santa::cel::v1::ReturnValue_descriptor();
113113
for (int i = 1; i < retDescriptor->value_count(); i++) {
114114
auto value = retDescriptor->value(i);
115115
v.push_back({value->name(), ::cel::IntType()});
116116
}
117117

118118
// Now add all the fields from the CELContext message.
119-
auto ctxDescriptor = pbv1::ExecutionContext::descriptor();
119+
auto ctxDescriptor = santa::cel::v1::ExecutionContext::descriptor();
120120
for (int i = 0; i < ctxDescriptor->field_count(); i++) {
121121
auto field = ctxDescriptor->field(i);
122122

Source/santactl/Commands/SNTCommandRule.m

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ + (NSString *)longHelpText {
5454
@" --block: add to block\n"
5555
@" --silent-block: add to silent block\n"
5656
@" --compiler: allow and mark as a compiler\n"
57+
@" --cel {cel_expr}: add a CEL rule\n"
5758
@" --remove: remove existing rule\n"
5859
@" --check: check for an existing rule\n"
5960
@" --import {path}: import rules from a JSON file\n"
@@ -153,6 +154,12 @@ - (void)runWithArguments:(NSArray *)arguments {
153154
newRule.state = SNTRuleStateSilentBlock;
154155
} else if ([arg caseInsensitiveCompare:@"--compiler"] == NSOrderedSame) {
155156
newRule.state = SNTRuleStateAllowCompiler;
157+
} else if ([arg caseInsensitiveCompare:@"--cel"] == NSOrderedSame) {
158+
if (++i > arguments.count - 1) {
159+
[self printErrorUsageAndExit:@"--cel requires an argument"];
160+
}
161+
newRule.state = SNTRuleStateCEL;
162+
newRule.celExpr = arguments[i];
156163
} else if ([arg caseInsensitiveCompare:@"--remove"] == NSOrderedSame) {
157164
newRule.state = SNTRuleStateRemove;
158165
} else if ([arg caseInsensitiveCompare:@"--check"] == NSOrderedSame) {

Source/santad/SNTPolicyProcessor.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ - (BOOL)decision:(SNTCachedDecision *)cd
127127
break;
128128
default: break;
129129
}
130-
if (!(*evalResult).second) {
130+
if (!evalResult->second) {
131131
cd.cacheable = NO;
132132
}
133133
}

Source/santasyncservice/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ objc_library(
124124
"//Source/common:SNTXPCControlInterface",
125125
"//Source/common:SNTXPCSyncServiceInterface",
126126
"//Source/common:String",
127+
"//Source/common/cel:CEL",
127128
"@northpolesec_protos//sync:v1_cc_proto",
128129
"@protobuf//src/google/protobuf/json",
129130
],

0 commit comments

Comments
 (0)