A third-party Golang package for Code42's Crashplan Forensic File Search (FFS) API
The goal of this Golang package is to provide an easy to use/integrate package for Code42's Crashplan FFS API within the Golang environment. There are two main functions that can be used within the package:
- GetAuthData
- GetFileEvents
These functions allow for someone to query the Crashplan FFS API and get the results returned in a Golang struct which can then be used for other purposes.
The GetAuthData is intended to get an API token for a user that will last for one (1) hour, which can then be used with the GetFileEvents function.
Arguments:
- uri - This is the URL which will provide the API token. (I believe it will always be: https://www.crashplan.com/c42api/v3/auth/jwt?useBody=true)
- username - The username of the account that has permissions to access the FFS API. (This must be an email address according to the API)
- password - The password of the account that is set as the username.
Returns:
- AuthData - Golang struct that contains the API token.
#AuthData struct structure
AuthData
Data AuthToken
AuthToken
V3UserToken string
- error - Any errors.
The GetFileEvents is intended to gather all events for a passed query and return them as a Golang struct slice.
Arguments:
- authData - This is the Golang struct which is gotten from the GetAuthData function.
- ffsURI - This is the URL which actually hosts the FFS API. (See Code42 documentation for URI, default is https://forensicsearch-default.prod.ffs.us2.code42.com/forensic-search/queryservice/api/v1/)
- query - This is the properly formatted FFS Query struct which is what is actually executed against the Code42 Crashplan FFS API. (See documentation for how to properly format these queries.)
- Example JSON query (Returns all events within a 5 second delta)
#Json Format
{
"groups":[
{
"filters":[
{
"operator":"IS",
"term":"fileName",
"value":"*"
},
{
"operator":"ON_OR_AFTER",
"term":"insertionTimestamp",
"value":"2019-08-18T20:31:48.728Z"
},
{
"operator":"ON_OR_BEFORE",
"term":"insertionTimestamp",
"value":"2019-08-18T20:32:03.728Z"
}
],
"filterClause":"AND"
}
],
"groupClause":"AND",
"pgNum":1,
"pgSize":100,
"srtDir":"asc",
"srtKey":"insertionTimestamp"
}
#Query Struct format
Query
Groups []Group
GroupClause string (optional)
PgNum int (optional)
PgSize int (optional)
SrtDir string (optional)
SrtKey string (optional)
}
Group
Filters []Filter
FilterClause string (optional)
}
Filter
Operator string
Term string
Value string
}
Returns:
- []FileEvent - Golang struct slice that contains all events returned from the jsonQuery string
#FileEvent struct structure
FileEvent
EventId string
EventType string
EventTimestamp *time.Time (potentially empty)
InsertionTimestamp *time.Time (potentially empty)
FilePath string (potentially empty)
FileName string
FileType string (potentially empty)
FileCategory string (potentially empty)
IdentifiedExtensionCategory string (potentially empty)
CurrentExtensionCategory string (potentially empty)
FileSize *int (potentially empty)
FileOwner []string (potentially empty)
Md5Checksum string (potentially empty)
Sha256Checksum string (potentially empty)
CreatedTimestamp *time.Time (potentially empty)
ModifyTimestamp *time.Time (potentially empty)
DeviceUsername string (potentially empty)
DeviceUid string (potentially empty)
UserUid string (potentially empty)
OsHostname string (potentially empty)
DomainName string (potentially empty)
PublicIpAddress string (potentially empty)
PrivateIpAddresses []string (potentially empty)
Actor string (potentially empty)
DirectoryId []string (potentially empty)
Source string (potentially empty)
Url string (potentially empty)
Shared *bool (potentially empty)
SharedWith []string (potentially empty)
SharingTypeAdded []string (potentially empty)
CloudDriveId string (potentially empty)
DetectionSourceAlias string (potentially empty)
FileId string (potentially empty)
Exposure []string (potentially empty)
ProcessOwner string (potentially empty)
ProcessName string (potentially empty)
TabWindowTitle string (potentially empty)
TabUrl string (potentially empty)
RemovableMediaVendor string (potentially empty)
RemovableMediaName string (potentially empty)
RemovableMediaSerialNumber string (potentially empty)
RemovableMediaCapacity *int (potentially empty)
RemovableMediaBusType string (potentially empty)
RemovableMediaMediaName string (potentially empty)
RemovableMediaVolumeName string (potentially empty)
RemovableMediaPartitionId string (potentially empty)
SyncDestination string (potentially empty)
SyncDestinationUsername string (potentially empty)
EmailDLPPolicyNames []string (potentially empty)
EmailDLPSubject string (potentially empty)
EmailDLPSender string (potentially empty)
EmailDLPFrom string (potentially empty)
EmailDLPRecipients []string (potentially empty)
OutsideActiveHours *bool (potentially empty)
IdentifiedExtensionMIMEType string (potentially empty)
CurrentExtensionMIMEType string (potentially empty)
SuspiciousFileTypeMismatch *bool (potentially empty)
PrintJobName string (potentially empty)
PrinterName string (potentially empty)
PrintedFilesBackupPath string (potentially empty)
RemoteActivity string (potentially empty)
Trusted *bool (potentially empty)
LoggedInOperatingSystemUser string (potentially empty)
- error - Any errors.
Limitations:
Code42 Crashplan FFS API has limitations like most APIs, these limitations affect the GetFileEvents function:
- 120 Queries per minute, any additional queries will be dropped. (never actually bothered to test if/how this limit is actually enforced)
- 200,000 results returned per query. This limitation is kind of annoying to handle as there is no easy way to handle it. The API does not support paging and the only way to figure out how many results there is for a query is to first query, count, then if over 200,000 results, break up the query into smaller time increments and perform multiple queries to get all the results.
- The GetFileEvents function only supports the /v1/fileevent/export API endpoint currently. This has to do with how the highly limited functionality of the /v1/fileevent endpoint which isn't well documented.
Links for Code42 Documentation
- Figure out a way to build tests for these functions