mirror of
https://github.com/google/santa.git
synced 2026-04-24 03:00:12 -04:00
* Initial structure for ES wrappers, enriched types, logging * Basic working ES and logging functionality * Add in oneTBB and thread-safe-lru deps * Added a bunch of enriched types * Auto-mute self when establishing ES client * Basic auth, tamper client. Syslog of all events. Basic compiler tracking. * Update copyright header blobs, convert some tabs to spaces * Auth result cache. Fix getting translocation path. * Added remaining cache methods * Add AuthResultCache to Recorder client. Cache now operates on es_file_t. * Hooked up SNTPrefixTree * Fix CompilerController for RENAME. Fix AllowList logging missing path. * Block loading Santa kext * Added device manager client * Properly log DiskAppear events * Fix build to adopt new adhoc build * Handle clearing cache on UNMOUNT events * Ignore other ES clients if configured * Remove SNTAllowlistInfo. Rename AllowList to Allowlist. Minor cleanup. * Recorder now logs asynchronously. Enricher now returns shared_ptrs. * Added File writer. Added timestamps to BasicStream serializer. * Skip calling stat in SNTFileInfo when path given by ES. * Fix build issue * Address draft PR feedback * santactl integrated, XPC works, fix file writer bug * Integrate syncservice. Start observing some config changes. * Add metrics service wrapper * Add metrics config observers and metrics interval reset. * Start better dependency control. Add Null logger support. * Added more deps * Added more deps * Fix issue where metric service wasn't starting * Add missing variant include * Fix missing parent proc name * Added googletest and new unit test macro * Started expanding AuthResultCacheTest * Properly mock EndpointSecurityAPI * Finished AuthResultCacheTest * bazelrc now builds all C++ as C++17. Added LoggerTest. * Add FileTest. Abstract some File constants to Logger. * Added Empty serializer test * Started work on BasicStringTest. Fixed some BasicString serialization bugs. * Added Unlink BasicString serialization test * Added some more tests. Commonized some test code * Finished BasicStringTest. Converted to XCTest. * Standardize esapi variable naming * Bubble up gTest expect failures to XCTest failures * AuthResultCacheTest now uses XCTest. Added common TestUtils.h * EmptyTest now uses XCTest. * FileTest now uses XCTest * LoggerTest now uses XCTest. Removed santa_unit_gtest bazel macro. * Added ClientTest * Add basic Enricher tests * Add MessageTest. Make more TestUtils. * Rename metrics to Metrics * Add MetricsTest. * Apply template pattern to Serializer * Add SNTDecisionCacheTest. * Add SNTCachedDecisionTest. * Testing with coveralls debug mode * Allow manual CI runs * Remove unused property * Started work on SNTEndpointSecurityClientTest. * WIP SNTEndpointSecurityClientTest, fix test run issue * Added more base ES client tests * Add more base ES client tests * Base ES client tests done. Added serializer utils/tests. Expanded basic string tests. * Add utils test to test suite * Add copy ctor. Add test output to bazel coverage. * Single thread bazel coverage * Updaload coverage file * Updaload coverage file * Old gen cov test * Restructure message handlers to enable better testability * Added enable tests for all ES clients * Made a single MockEndpointSecurityAPI class to share everywhere * Added most of SNTCompilerControllerTest * Cleanup SNTCompilerControllerTest * Started expanding Auth client test * Finished up the Authorizer tests * Move to using enum class for notify/auth instead of bool * WIP for tamper resistance test. ASAN issues. * Add OCMock patch to fix test issue on ARM Macs * Changed patches directory name to external_patches * Update WORKSPACE path * Finished up Tamper Resistance tests * Finished up Recorder tests. * Move SNTExecutionControllerTest to ObjC++ * Initial work to port SNTExecutionControllerTest * Finished porting SNTExecutionControllerTest. * Added SNTExecutionControllerTest to list of unit tests * Ported SNTEndpointSecurityDeviceManager. * Test cleanup, use MockESAPI expectation helpers * Verify SNTEndpointSecurityDeviceManager expectations differently * Test cleanup, omit gTest param list where unused * Log message cleanup * Rename SNTApplicationTest to santad_test.mm * Finished porting santad_test, formerly SNTApplicationTest * Fix SNTEndpointSecurityDeviceManager issues * Pulled in missed fixes. Updated tests. * Renamed lowercase filenames to match rest of codebase * Fix non-static dispatch_once_t, and noisy watching compiler log message * WIP Started process of removing components no longer used * WIP Continued process of removing components no longer used * BUILD file cleanup. Proto warning. Removed unused global * Rename SNTEventProvider to SNTEndpointSecurityEventHandler * Rename SNTEndpointSecurityEventHandler protocol * Remove EnableSysxCache option. Remove --quick flag used during dev. * Ran testing/fix.sh * Addmissing param to fix.sh that was omitting .mm files. * clang-format * Fix linter: find cmd missing .mm ext, git grep exclude patch files. * Use MakeESProcess default params in tests * Move variables to camelCase in objc classes * More case changes * Sanitize strings * Change dispatch queue priorities and standardize daemon queue naming * Exclude patch files in markdown check * Ensure string log messages end with newline * Fix BasicStringTest * Disable clang-format in code producing different results in local/remote versions * Moved to using date ranges in copyright notices as per current guidelines * Update Source/common/SNTConfigurator.h Suggestion adding whitespace in comment to fix clang-format mangling Co-authored-by: Russell Hancox <russellhancox@users.noreply.github.com> * Removed santa_panic macro used in one place * Updated comment about ES cachability * Pin oneTBB to specific commit * Address outstanding WORKSPACE 'canonical reproducible form' messages * Use string append instead of ostringstream due to benchmark results * Remove use of freind classes in EnrichedTypes.h * Added SNTKVOManager, removed observers from SNTConfigurator. * Fixed SNTEndpointSecurityRecorderTest class name * Reduce usage of the auto keyword * Each SNTKVOManager instance now adds its own observer * Replaced more auto keywords with real types. * Remove leftover code coverage debugging from ci.yml * Updated comment * Memoize SNTFileInfo sha256. Reduce some cache sizes. * Fix issue checking for translocated paths * Use more performant NSURL creation method * Fix lint issue * Address PR feedback * Use an array literal for kvo objects * Fix some clang tidy and import issues * Replace third party LRU cache with SantaCache for now * Fix clang tidy issues * Address PR feedback * Fix comment typo Co-authored-by: Pete Markowsky <pmarkowsky@users.noreply.github.com> * Added todo for when we adopt macOS 13 Co-authored-by: Russell Hancox <russellhancox@users.noreply.github.com> Co-authored-by: Pete Markowsky <pmarkowsky@users.noreply.github.com>
255 lines
8.9 KiB
Plaintext
255 lines
8.9 KiB
Plaintext
/// Copyright 2022 Google Inc. All rights reserved.
|
|
///
|
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|
/// you may not use this file except in compliance with the License.
|
|
/// You may obtain a copy of the License at
|
|
///
|
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
|
///
|
|
/// Unless required by applicable law or agreed to in writing, software
|
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
/// See the License for the specific language governing permissions and
|
|
/// limitations under the License.
|
|
|
|
#include <EndpointSecurity/EndpointSecurity.h>
|
|
#import <OCMock/OCMock.h>
|
|
#import <XCTest/XCTest.h>
|
|
#include <gmock/gmock.h>
|
|
#include <gtest/gtest.h>
|
|
#include <cstdio>
|
|
#include <memory>
|
|
#include "Source/santad/SNTCompilerController.h"
|
|
|
|
#include <string_view>
|
|
|
|
#import "Source/common/SNTCachedDecision.h"
|
|
#import "Source/common/SNTFileInfo.h"
|
|
#include "Source/common/TestUtils.h"
|
|
#include "Source/santad/EventProviders/EndpointSecurity/Message.h"
|
|
#include "Source/santad/EventProviders/EndpointSecurity/MockEndpointSecurityAPI.h"
|
|
#include "Source/santad/Logs/EndpointSecurity/Logger.h"
|
|
#import "Source/santad/SNTCompilerController.h"
|
|
#import "Source/santad/SNTDecisionCache.h"
|
|
|
|
using santa::santad::event_providers::endpoint_security::Message;
|
|
using santa::santad::logs::endpoint_security::Logger;
|
|
|
|
static const pid_t PID_MAX = 99999;
|
|
|
|
@interface SNTCompilerController (Testing)
|
|
- (BOOL)isCompiler:(const audit_token_t &)tok;
|
|
- (void)saveFakeDecision:(const es_file_t *)esFile;
|
|
- (void)removeFakeDecision:(const es_file_t *)esFile;
|
|
- (void)createTransitiveRule:(const Message &)esMsg
|
|
target:(const es_file_t *)targetFile
|
|
logger:(std::shared_ptr<Logger>)logger;
|
|
@end
|
|
|
|
@interface SNTCompilerControllerTest : XCTestCase
|
|
@property id mockDecisionCache;
|
|
@property audit_token_t tok1;
|
|
@property audit_token_t tok2;
|
|
@property audit_token_t tokNegativePid;
|
|
@property audit_token_t tokLargePid;
|
|
@end
|
|
|
|
@implementation SNTCompilerControllerTest
|
|
|
|
- (void)setUp {
|
|
self.mockDecisionCache = OCMClassMock([SNTDecisionCache class]);
|
|
OCMStub([self.mockDecisionCache sharedCache]).andReturn(self.mockDecisionCache);
|
|
|
|
self.tok1 = MakeAuditToken(12, 11);
|
|
self.tok2 = MakeAuditToken(34, 22);
|
|
self.tokNegativePid = MakeAuditToken(-1, 33);
|
|
self.tokLargePid = MakeAuditToken(PID_MAX + 1, 44);
|
|
}
|
|
|
|
- (void)tearDown {
|
|
[self.mockDecisionCache stopMocking];
|
|
}
|
|
|
|
- (void)testIsCompiler {
|
|
SNTCompilerController *cc = [[SNTCompilerController alloc] init];
|
|
|
|
// Ensure invalid PIDs are handled
|
|
XCTAssertFalse([cc isCompiler:self.tokNegativePid]);
|
|
XCTAssertFalse([cc isCompiler:self.tokLargePid]);
|
|
|
|
// Items in the compiler control cache are initially false
|
|
XCTAssertFalse([cc isCompiler:self.tok1]);
|
|
|
|
// Start tracking a process as a compiler
|
|
[cc setProcess:self.tok1 isCompiler:true];
|
|
XCTAssertTrue([cc isCompiler:self.tok1]);
|
|
|
|
// Stop tracking a process as a compiler
|
|
[cc setProcess:self.tok1 isCompiler:false];
|
|
XCTAssertFalse([cc isCompiler:self.tok1]);
|
|
}
|
|
|
|
- (void)testSetProcessIsCompiler {
|
|
SNTCompilerController *cc = [[SNTCompilerController alloc] init];
|
|
|
|
// Ensure invalid PIDs are handled
|
|
XCTAssertNoThrow([cc setProcess:self.tokNegativePid isCompiler:true]);
|
|
XCTAssertNoThrow([cc setProcess:self.tokLargePid isCompiler:true]);
|
|
|
|
// Ensure test tokens are initially false
|
|
XCTAssertFalse([cc isCompiler:self.tok1]);
|
|
XCTAssertFalse([cc isCompiler:self.tok2]);
|
|
|
|
// Start tracking one of the toks
|
|
[cc setProcess:self.tok1 isCompiler:true];
|
|
XCTAssertTrue([cc isCompiler:self.tok1]);
|
|
XCTAssertFalse([cc isCompiler:self.tok2]);
|
|
|
|
// Start tracking both toks
|
|
[cc setProcess:self.tok2 isCompiler:true];
|
|
XCTAssertTrue([cc isCompiler:self.tok1]);
|
|
XCTAssertTrue([cc isCompiler:self.tok2]);
|
|
|
|
// Stop tracking one of the toks
|
|
[cc setProcess:self.tok1 isCompiler:false];
|
|
XCTAssertFalse([cc isCompiler:self.tok1]);
|
|
XCTAssertTrue([cc isCompiler:self.tok2]);
|
|
}
|
|
|
|
- (void)testSaveFakeDecision {
|
|
es_file_t file = MakeESFile("foo", {
|
|
.st_dev = 12,
|
|
.st_ino = 34,
|
|
});
|
|
|
|
OCMExpect([self.mockDecisionCache
|
|
cacheDecision:[OCMArg checkWithBlock:^BOOL(SNTCachedDecision *cd) {
|
|
return cd.vnodeId.fsid == file.stat.st_dev && cd.vnodeId.fileid == file.stat.st_ino &&
|
|
cd.decision == SNTEventStateAllowPendingTransitive &&
|
|
[cd.sha256 isEqualToString:@"pending"];
|
|
}]]);
|
|
|
|
SNTCompilerController *cc = [[SNTCompilerController alloc] init];
|
|
[cc saveFakeDecision:&file];
|
|
|
|
XCTAssertTrue(OCMVerifyAll(self.mockDecisionCache), "Unable to verify all expectations");
|
|
}
|
|
|
|
- (void)testRemoveFakeDecision {
|
|
es_file_t file = MakeESFile("foo", {
|
|
.st_dev = 12,
|
|
.st_ino = 34,
|
|
});
|
|
|
|
OCMExpect([self.mockDecisionCache forgetCachedDecisionForFile:file.stat]);
|
|
|
|
SNTCompilerController *cc = [[SNTCompilerController alloc] init];
|
|
[cc removeFakeDecision:&file];
|
|
|
|
XCTAssertTrue(OCMVerifyAll(self.mockDecisionCache), "Unable to verify all expectations");
|
|
}
|
|
|
|
- (void)testHandleEventWithLogger {
|
|
es_file_t file = MakeESFile("foo");
|
|
es_file_t ignoredFile = MakeESFile("/dev/bar");
|
|
es_file_t normalFile = MakeESFile("bar");
|
|
audit_token_t compilerTok = MakeAuditToken(12, 34);
|
|
audit_token_t notCompilerTok = MakeAuditToken(56, 78);
|
|
es_process_t compilerProc = MakeESProcess(&file, compilerTok, {});
|
|
es_process_t notCompilerProc = MakeESProcess(&file, notCompilerTok, {});
|
|
es_message_t esMsg;
|
|
|
|
auto mockESApi = std::make_shared<MockEndpointSecurityAPI>();
|
|
mockESApi->SetExpectationsRetainReleaseMessage(&esMsg);
|
|
|
|
SNTCompilerController *cc = [[SNTCompilerController alloc] init];
|
|
|
|
// Mark a process as a compiler for use with these tests.
|
|
[cc setProcess:compilerTok isCompiler:true];
|
|
|
|
// Ensure unhandled event types return appropriately
|
|
{
|
|
esMsg = MakeESMessage(ES_EVENT_TYPE_NOTIFY_FORK, ¬CompilerProc);
|
|
Message msg(mockESApi, &esMsg);
|
|
XCTAssertFalse([cc handleEvent:msg withLogger:nullptr]);
|
|
}
|
|
|
|
// Ensure non-compiler process events return false
|
|
{
|
|
esMsg = MakeESMessage(ES_EVENT_TYPE_NOTIFY_CLOSE, ¬CompilerProc);
|
|
Message msg(mockESApi, &esMsg);
|
|
XCTAssertFalse([cc handleEvent:msg withLogger:nullptr]);
|
|
}
|
|
{
|
|
esMsg = MakeESMessage(ES_EVENT_TYPE_NOTIFY_RENAME, ¬CompilerProc);
|
|
Message msg(mockESApi, &esMsg);
|
|
XCTAssertFalse([cc handleEvent:msg withLogger:nullptr]);
|
|
}
|
|
|
|
// Ensure compiler process events are only handled with non-ignored paths
|
|
{
|
|
esMsg = MakeESMessage(ES_EVENT_TYPE_NOTIFY_CLOSE, &compilerProc);
|
|
esMsg.event.close.target = &ignoredFile;
|
|
Message msg(mockESApi, &esMsg);
|
|
XCTAssertFalse([cc handleEvent:msg withLogger:nullptr]);
|
|
}
|
|
{
|
|
esMsg = MakeESMessage(ES_EVENT_TYPE_NOTIFY_RENAME, &compilerProc);
|
|
esMsg.event.rename.source = &ignoredFile;
|
|
Message msg(mockESApi, &esMsg);
|
|
XCTAssertFalse([cc handleEvent:msg withLogger:nullptr]);
|
|
}
|
|
|
|
// Ensure EXIT events stop tracking the process as a compiler
|
|
{
|
|
esMsg = MakeESMessage(ES_EVENT_TYPE_NOTIFY_EXIT, &compilerProc);
|
|
Message msg(mockESApi, &esMsg);
|
|
|
|
id mockCompilerController = OCMPartialMock(cc);
|
|
OCMExpect([mockCompilerController setProcess:compilerProc.audit_token isCompiler:false]);
|
|
|
|
XCTAssertTrue([cc handleEvent:msg withLogger:nullptr]);
|
|
|
|
XCTAssertTrue(OCMVerifyAll(mockCompilerController), "Unable to verify all expectations");
|
|
[mockCompilerController stopMocking];
|
|
}
|
|
|
|
// Ensure transitive rules are created when the given event is handled
|
|
{
|
|
esMsg = MakeESMessage(ES_EVENT_TYPE_NOTIFY_CLOSE, &compilerProc);
|
|
esMsg.event.close.target = &normalFile;
|
|
Message msg(mockESApi, &esMsg);
|
|
|
|
id mockCompilerController = OCMPartialMock(cc);
|
|
|
|
OCMExpect([mockCompilerController createTransitiveRule:msg
|
|
target:esMsg.event.close.target
|
|
logger:nullptr])
|
|
.ignoringNonObjectArgs();
|
|
|
|
XCTAssertTrue([cc handleEvent:msg withLogger:nullptr]);
|
|
|
|
XCTAssertTrue(OCMVerifyAll(mockCompilerController), "Unable to verify all expectations");
|
|
[mockCompilerController stopMocking];
|
|
}
|
|
{
|
|
esMsg = MakeESMessage(ES_EVENT_TYPE_NOTIFY_RENAME, &compilerProc);
|
|
esMsg.event.rename.source = &normalFile;
|
|
Message msg(mockESApi, &esMsg);
|
|
|
|
id mockCompilerController = OCMPartialMock(cc);
|
|
|
|
OCMExpect([mockCompilerController createTransitiveRule:msg
|
|
target:esMsg.event.close.target
|
|
logger:nullptr])
|
|
.ignoringNonObjectArgs();
|
|
|
|
XCTAssertTrue([cc handleEvent:msg withLogger:nullptr]);
|
|
|
|
XCTAssertTrue(OCMVerifyAll(mockCompilerController), "Unable to verify all expectations");
|
|
[mockCompilerController stopMocking];
|
|
}
|
|
}
|
|
|
|
@end
|