-
Notifications
You must be signed in to change notification settings - Fork 297
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
1,160 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
load("@build_bazel_rules_apple//apple:macos.bzl", "macos_command_line_application") | ||
load("//:helper.bzl", "santa_unit_test") | ||
|
||
package(default_visibility = ["//:santa_package_group"]) | ||
|
||
licenses(["notice"]) # Apache 2.0 | ||
|
||
objc_library( | ||
name = "SNTMetricServiceLib", | ||
srcs = [ | ||
"SNTMetricService.h", | ||
"SNTMetricService.m", | ||
"main.m", | ||
], | ||
deps = [ | ||
"//Source/common:SNTConfigurator", | ||
"//Source/common:SNTLogging", | ||
"//Source/common:SNTMetricSet", | ||
"//Source/common:SNTXPCMetricServiceInterface", | ||
"//Source/santametricservice/Formats:SNTMetricRawJsonFormat", | ||
"//Source/santametricservice/Writers:SNTMetricFileWriter", | ||
"@MOLCodesignChecker", | ||
"@MOLXPCConnection", | ||
], | ||
) | ||
|
||
santa_unit_test( | ||
name = "SNTMetricServiceTest", | ||
srcs = ["SNTMetricServiceTest.m"], | ||
deps = [ | ||
":SNTMetricServiceLib", | ||
"@OCMock", | ||
], | ||
) | ||
|
||
test_suite( | ||
name = "unit_tests", | ||
tests = [ | ||
":SNTMetricServiceTest", | ||
"//Source/santametricservice/Formats:SNTMetricRawJsonFormatTest", | ||
"//Source/santametricservice/Writers:SNTMetricFileWriterTest", | ||
], | ||
) | ||
|
||
macos_command_line_application( | ||
name = "santametricservice", | ||
bundle_id = "com.google.santa.metricservice", | ||
infoplists = ["Info.plist"], | ||
minimum_os_version = "10.15", | ||
version = "//:version", | ||
visibility = ["//:santa_package_group"], | ||
deps = [":SNTMetricServiceLib"], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
load("@build_bazel_rules_apple//apple:macos.bzl", "macos_command_line_application") | ||
load("//:helper.bzl", "santa_unit_test") | ||
|
||
package(default_visibility = ["//:santa_package_group"]) | ||
|
||
licenses(["notice"]) # Apache 2.0 | ||
|
||
objc_library( | ||
name = "SNTMetricFormat", | ||
hdrs = ["SNTMetricFormat.h"], | ||
) | ||
|
||
objc_library( | ||
name = "SNTMetricRawJsonFormat", | ||
srcs = [ | ||
"SNTMetricFormat.h", | ||
"SNTMetricRawJsonFormat.h", | ||
"SNTMetricRawJsonFormat.m", | ||
], | ||
deps = [ | ||
":SNTMetricFormat", | ||
"//Source/common:SNTLogging", | ||
], | ||
) | ||
|
||
santa_unit_test( | ||
name = "SNTMetricRawJsonFormatTest", | ||
srcs = [ | ||
"SNTMetricRawJsonFormatTest.m", | ||
], | ||
structured_resources = glob(["testdata/**"]), | ||
deps = [ | ||
":SNTMetricRawJsonFormat", | ||
"//Source/common:SNTMetricSet", | ||
], | ||
) | ||
|
||
test_suite( | ||
name = "format_tests", | ||
tests = [ | ||
":SNTMetricRawJsonFormatTest", | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/// Copyright 2021 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. | ||
|
||
#import <Foundation/Foundation.h> | ||
|
||
@protocol SNTMetricFormat | ||
- (NSArray<NSData *> *)convert:(NSDictionary *)metrics error:(NSError **)err; | ||
@end |
21 changes: 21 additions & 0 deletions
21
Source/santametricservice/Formats/SNTMetricRawJSONFormat.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/// Copyright 2021 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. | ||
|
||
#import <Foundation/Foundation.h> | ||
|
||
#import "Source/santametricservice/Formats/SNTMetricFormat.h" | ||
|
||
@interface SNTMetricRawJSONFormat : NSObject <SNTMetricFormat> | ||
- (NSArray<NSData *> *)convert:(NSDictionary *)metrics error:(NSError **)err; | ||
@end |
94 changes: 94 additions & 0 deletions
94
Source/santametricservice/Formats/SNTMetricRawJSONFormat.m
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/// Copyright 2021 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. | ||
#import "Source/common/SNTLogging.h" | ||
|
||
#import "Source/santametricservice/Formats/SNTMetricRawJSONFormat.h" | ||
|
||
@implementation SNTMetricRawJSONFormat { | ||
NSDateFormatter *dateFormatter; | ||
} | ||
|
||
- (instancetype)init { | ||
self = [super init]; | ||
if (self) { | ||
dateFormatter = [[NSDateFormatter alloc] init]; | ||
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"]; | ||
} | ||
return self; | ||
} | ||
|
||
- (NSArray *)normalizeArray:(NSArray *)arr { | ||
NSMutableArray *normalized = [NSMutableArray arrayWithArray:arr]; | ||
|
||
for (int i = 0; i < [arr count]; i++) { | ||
if ([arr[i] isKindOfClass:[NSArray class]]) { | ||
normalized[i] = [self normalizeArray:(NSArray *)arr[i]]; | ||
} else if ([arr[i] isKindOfClass:[NSDictionary class]]) { | ||
normalized[i] = [self normalize:(NSDictionary *)arr[i]]; | ||
} | ||
} | ||
|
||
return normalized; | ||
} | ||
|
||
/** | ||
* Normalizes the metrics dictionary for exporting to JSON | ||
**/ | ||
- (NSDictionary *)normalize:(NSDictionary *)metrics { | ||
// Convert NSDate's to RFC3339 in strings as NSDate's cannot be serialized | ||
// to JSON. | ||
NSMutableDictionary *normalizedMetrics = [NSMutableDictionary dictionaryWithDictionary:metrics]; | ||
|
||
for (NSString *key in metrics) { | ||
const id object = [metrics objectForKey:key]; | ||
if ([object isKindOfClass:[NSDate class]]) { | ||
normalizedMetrics[key] = [self->dateFormatter stringFromDate:(NSDate *)object]; | ||
} else if ([object isKindOfClass:[NSDictionary class]]) { | ||
normalizedMetrics[key] = [self normalize:metrics[key]]; | ||
} else if ([object isKindOfClass:[NSArray class]]) { | ||
normalizedMetrics[key] = [self normalizeArray:(NSArray *)object]; | ||
} | ||
} | ||
|
||
return (NSDictionary *)normalizedMetrics; | ||
} | ||
|
||
/* | ||
* Convert normalies and converts the metrics dictionary to a single JSON | ||
* object. | ||
* | ||
* @param metrics an NSDictionary exported by the SNTMetricSet | ||
* @param error a pointer to an NSError to allow errors to bubble up. | ||
* | ||
* Returns an NSArray containing one entry of all metrics serialized to JSON or | ||
* nil on error. | ||
*/ | ||
- (NSArray<NSData *> *)convert:(NSDictionary *)metrics error:(NSError **)err { | ||
NSDictionary *normalizedMetrics = [self normalize:metrics]; | ||
|
||
if (![NSJSONSerialization isValidJSONObject:normalizedMetrics]) { | ||
LOGE(@"unable to convert metrics to JSON: invalid metrics"); | ||
return nil; | ||
} | ||
|
||
NSData *json = [NSJSONSerialization dataWithJSONObject:normalizedMetrics | ||
options:NSJSONWritingPrettyPrinted | ||
error:err]; | ||
if (json == nil && *err != nil) { | ||
return nil; | ||
} | ||
|
||
return @[ json ]; | ||
} | ||
@end |
153 changes: 153 additions & 0 deletions
153
Source/santametricservice/Formats/SNTMetricRawJSONFormatTest.m
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
#import <XCTest/XCTest.h> | ||
|
||
#import "Source/common/SNTMetricSet.h" | ||
#import "Source/santametricservice/Formats/SNTMetricRawJSONFormat.h" | ||
|
||
NSDictionary *validMetricsDict = nil; | ||
|
||
@interface SNTMetricRawJSONFormatTest : XCTestCase | ||
@end | ||
|
||
@implementation SNTMetricRawJSONFormatTest | ||
|
||
- (void)initializeValidMetricsDict { | ||
NSDateFormatter *formatter = NSDateFormatter.new; | ||
[formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"]; | ||
NSDate *fixedDate = [formatter dateFromString:@"2021-09-16T21:07:34.826Z"]; | ||
|
||
validMetricsDict = @{ | ||
@"root_labels" : @{@"hostname" : @"testHost", @"username" : @"testUser"}, | ||
@"metrics" : @{ | ||
@"/build/label" : @{ | ||
@"type" : [NSNumber numberWithInt:(int)SNTMetricTypeConstantString], | ||
@"fields" : @{ | ||
@"" : @[ @{ | ||
@"value" : @"", | ||
@"created" : fixedDate, | ||
@"last_updated" : fixedDate, | ||
@"data" : @"20210809.0.1" | ||
} ] | ||
} | ||
}, | ||
@"/santa/events" : @{ | ||
@"type" : [NSNumber numberWithInt:(int)SNTMetricTypeCounter], | ||
@"fields" : @{ | ||
@"rule_type" : @[ | ||
@{ | ||
@"value" : @"binary", | ||
@"created" : fixedDate, | ||
@"last_updated" : fixedDate, | ||
@"data" : @1, | ||
}, | ||
@{ | ||
@"value" : @"certificate", | ||
@"created" : fixedDate, | ||
@"last_updated" : fixedDate, | ||
@"data" : @2, | ||
}, | ||
], | ||
}, | ||
}, | ||
@"/santa/rules" : @{ | ||
@"type" : [NSNumber numberWithInt:(int)SNTMetricTypeGaugeInt64], | ||
@"fields" : @{ | ||
@"rule_type" : @[ | ||
@{ | ||
@"value" : @"binary", | ||
@"created" : fixedDate, | ||
@"last_updated" : fixedDate, | ||
@"data" : @1 | ||
}, | ||
@{ | ||
@"value" : @"certificate", | ||
@"created" : fixedDate, | ||
@"last_updated" : fixedDate, | ||
@"data" : @3 | ||
} | ||
] | ||
}, | ||
}, | ||
@"/santa/using_endpoint_security_framework" : @{ | ||
@"type" : [NSNumber numberWithInt:(int)SNTMetricTypeConstantBool], | ||
@"fields" : @{ | ||
@"" : @[ @{ | ||
@"value" : @"", | ||
@"created" : fixedDate, | ||
@"last_updated" : fixedDate, | ||
@"data" : [NSNumber numberWithBool:YES] | ||
} ] | ||
} | ||
}, | ||
@"/proc/birth_timestamp" : @{ | ||
@"type" : [NSNumber numberWithInt:(int)SNTMetricTypeConstantInt64], | ||
@"fields" : @{ | ||
@"" : @[ @{ | ||
@"value" : @"", | ||
@"created" : fixedDate, | ||
@"last_updated" : fixedDate, | ||
@"data" : [NSNumber numberWithLong:1250999830800] | ||
} ] | ||
}, | ||
}, | ||
@"/proc/memory/virtual_size" : @{ | ||
@"type" : [NSNumber numberWithInt:(int)SNTMetricTypeGaugeInt64], | ||
@"fields" : @{ | ||
@"" : @[ @{ | ||
@"value" : @"", | ||
@"created" : fixedDate, | ||
@"last_updated" : fixedDate, | ||
@"data" : [NSNumber numberWithInt:987654321] | ||
} ] | ||
} | ||
}, | ||
@"/proc/memory/resident_size" : @{ | ||
@"type" : [NSNumber numberWithInt:(int)SNTMetricTypeGaugeInt64], | ||
@"fields" : @{ | ||
@"" : @[ @{ | ||
@"value" : @"", | ||
@"created" : fixedDate, | ||
@"last_updated" : fixedDate, | ||
@"data" : [NSNumber numberWithInt:123456789] | ||
} ] | ||
}, | ||
}, | ||
} | ||
}; | ||
} | ||
|
||
- (void)setUp { | ||
[self initializeValidMetricsDict]; | ||
} | ||
|
||
- (void)testMetricsConversionToJSON { | ||
SNTMetricRawJSONFormat *formatter = [[SNTMetricRawJSONFormat alloc] init]; | ||
NSError *err = nil; | ||
NSArray<NSData *> *output = [formatter convert:validMetricsDict error:&err]; | ||
|
||
XCTAssertEqual(1, [output count]); | ||
XCTAssertNotNil(output[0]); | ||
XCTAssertNil(err); | ||
|
||
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:output[0] | ||
options:NSJSONReadingAllowFragments | ||
error:&err]; | ||
XCTAssertNotNil(jsonDict); | ||
|
||
NSString *path = [[NSBundle bundleForClass:[self class]] resourcePath]; | ||
path = [path stringByAppendingPathComponent:@"testdata/json/test.json"]; | ||
|
||
NSFileManager *filemgr = [NSFileManager defaultManager]; | ||
NSData *goldenFileData = [filemgr contentsAtPath:path]; | ||
|
||
XCTAssertNotNil(goldenFileData, @"unable to open / read golden file"); | ||
|
||
NSDictionary *expectedJSONDict = | ||
[NSJSONSerialization JSONObjectWithData:goldenFileData | ||
options:NSJSONReadingAllowFragments | ||
error:&err]; | ||
|
||
XCTAssertNotNil(expectedJSONDict); | ||
XCTAssertEqualObjects(expectedJSONDict, jsonDict, @"generated JSON does not match golden file."); | ||
} | ||
|
||
@end |
Oops, something went wrong.