Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions aftermath/Aftermath.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class Aftermath {

let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)

let dateString = dateFormatter.string(from: date as Date)
Expand All @@ -72,15 +72,15 @@ class Aftermath {
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)

if let date = dateFormatter.date(from: timeStamp) {
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
let dateString = dateFormatter.string(from: date as Date)
return dateString
}

dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"

if let date = dateFormatter.date(from: timeStamp) {
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
let dateString = dateFormatter.string(from: date as Date)
return dateString
} else {
Expand Down
81 changes: 81 additions & 0 deletions artifacts/SantaModule.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import Foundation

public struct SantaStatus {
public let version: String?
public let status: String?
public let exportedConfigPath: String?
public let logFiles: [String]

public init(version: String?, status: String?, exportedConfigPath: String?, logFiles: [String]) {
self.version = version
self.status = status
self.exportedConfigPath = exportedConfigPath
self.logFiles = logFiles
}
}

public enum SantaError: Error {
case executionFailed(String)
}

public final class SantaCollector {
static func runCommand(_ arguments: [String]) -> (output: String?, exitCode: Int32) {
let process = Process()
process.launchPath = "/usr/bin/env"
process.arguments = arguments

let outPipe = Pipe()
process.standardOutput = outPipe
process.standardError = outPipe

do {
try process.run()
} catch {
return ("", -1)
}

process.waitUntilExit()
let data = outPipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: data, encoding: .utf8)
return (output?.trimmingCharacters(in: .whitespacesAndNewlines), process.terminationStatus)
}

public static func version() -> String? {
let res = runCommand(["santactl", "version"]) // PATH lookup via /usr/bin/env; returns output if available
return res.output
}

public static func status() -> String? {
let res = runCommand(["santactl", "status"])
return res.output
}

@discardableResult
public static func exportConfiguration(to path: String) -> Bool {
let res = runCommand(["santactl", "rule", "--export", path])
return res.exitCode == 0
}

public static func listLogFiles(atPath path: String = "/var/db/santa") -> [String] {
let fm = FileManager.default
do {
let items = try fm.contentsOfDirectory(atPath: path)
return items.map { (path as NSString).appendingPathComponent($0) }
} catch {
return []
}
}

public static func collect(exportConfigTo configPath: String? = nil) -> SantaStatus {
let ver = version()
let stat = status()
var exportedPath: String? = nil
if let p = configPath {
if exportConfiguration(to: p) {
exportedPath = p
}
}
let logs = listLogFiles()
return SantaStatus(version: ver, status: stat, exportedConfigPath: exportedPath, logFiles: logs)
}
}
11 changes: 11 additions & 0 deletions tests/aftermath/SantaTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import XCTest
@testable import aftermath

final class SantaTests: XCTestCase {
func testCollectorAPIsDoNotCrash() {
// These calls are safe if `santactl` is missing — they should return nil/empty rather than crash.
_ = SantaCollector.version()
_ = SantaCollector.status()
_ = SantaCollector.listLogFiles()
}
}