From 184661f94cecf1981489db2665ece7d309e8921f Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Fri, 5 Apr 2024 12:31:35 -0700 Subject: [PATCH] add support for client_certificate_v2 posture rule --- .changelog/1685.txt | 3 ++ device_posture_rule.go | 79 +++++++++++++++++++++---------------- device_posture_rule_test.go | 63 +++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 35 deletions(-) create mode 100644 .changelog/1685.txt diff --git a/.changelog/1685.txt b/.changelog/1685.txt new file mode 100644 index 0000000000..1b559c3c90 --- /dev/null +++ b/.changelog/1685.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +device_posture_rule: support extended_key_usage, check_private_key, and locations for client_certificate_v2 posture rule +``` \ No newline at end of file diff --git a/device_posture_rule.go b/device_posture_rule.go index 4768b77048..ec8b37bff9 100644 --- a/device_posture_rule.go +++ b/device_posture_rule.go @@ -165,41 +165,50 @@ type DevicePostureRuleMatch struct { // DevicePostureRuleInput represents the value to be checked against. type DevicePostureRuleInput struct { - ID string `json:"id,omitempty"` - Path string `json:"path,omitempty"` - Exists bool `json:"exists,omitempty"` - Thumbprint string `json:"thumbprint,omitempty"` - Sha256 string `json:"sha256,omitempty"` - Running bool `json:"running,omitempty"` - RequireAll bool `json:"requireAll,omitempty"` - CheckDisks []string `json:"checkDisks,omitempty"` - Enabled bool `json:"enabled,omitempty"` - Version string `json:"version,omitempty"` - VersionOperator string `json:"versionOperator,omitempty"` - Overall string `json:"overall,omitempty"` - SensorConfig string `json:"sensor_config,omitempty"` - Os string `json:"os,omitempty"` - OsDistroName string `json:"os_distro_name,omitempty"` - OsDistroRevision string `json:"os_distro_revision,omitempty"` - OSVersionExtra string `json:"os_version_extra,omitempty"` - Operator string `json:"operator,omitempty"` - Domain string `json:"domain,omitempty"` - ComplianceStatus string `json:"compliance_status,omitempty"` - ConnectionID string `json:"connection_id,omitempty"` - IssueCount string `json:"issue_count,omitempty"` - CountOperator string `json:"countOperator,omitempty"` - TotalScore int `json:"total_score,omitempty"` - ScoreOperator string `json:"scoreOperator,omitempty"` - CertificateID string `json:"certificate_id,omitempty"` - CommonName string `json:"cn,omitempty"` - ActiveThreats int `json:"active_threats,omitempty"` - NetworkStatus string `json:"network_status,omitempty"` - Infected bool `json:"infected,omitempty"` - IsActive bool `json:"is_active,omitempty"` - EidLastSeen string `json:"eid_last_seen,omitempty"` - RiskLevel string `json:"risk_level,omitempty"` - State string `json:"state,omitempty"` - LastSeen string `json:"last_seen,omitempty"` + ID string `json:"id,omitempty"` + Path string `json:"path,omitempty"` + Exists bool `json:"exists,omitempty"` + Thumbprint string `json:"thumbprint,omitempty"` + Sha256 string `json:"sha256,omitempty"` + Running bool `json:"running,omitempty"` + RequireAll bool `json:"requireAll,omitempty"` + CheckDisks []string `json:"checkDisks,omitempty"` + Enabled bool `json:"enabled,omitempty"` + Version string `json:"version,omitempty"` + VersionOperator string `json:"versionOperator,omitempty"` + Overall string `json:"overall,omitempty"` + SensorConfig string `json:"sensor_config,omitempty"` + Os string `json:"os,omitempty"` + OsDistroName string `json:"os_distro_name,omitempty"` + OsDistroRevision string `json:"os_distro_revision,omitempty"` + OSVersionExtra string `json:"os_version_extra,omitempty"` + Operator string `json:"operator,omitempty"` + Domain string `json:"domain,omitempty"` + ComplianceStatus string `json:"compliance_status,omitempty"` + ConnectionID string `json:"connection_id,omitempty"` + IssueCount string `json:"issue_count,omitempty"` + CountOperator string `json:"countOperator,omitempty"` + TotalScore int `json:"total_score,omitempty"` + ScoreOperator string `json:"scoreOperator,omitempty"` + CertificateID string `json:"certificate_id,omitempty"` + CommonName string `json:"cn,omitempty"` + ActiveThreats int `json:"active_threats,omitempty"` + NetworkStatus string `json:"network_status,omitempty"` + Infected bool `json:"infected,omitempty"` + IsActive bool `json:"is_active,omitempty"` + EidLastSeen string `json:"eid_last_seen,omitempty"` + RiskLevel string `json:"risk_level,omitempty"` + State string `json:"state,omitempty"` + LastSeen string `json:"last_seen,omitempty"` + ExtendedKeyUsage []string `json:"extended_key_usage,omitempty"` + CheckPrivateKey bool `json:"check_private_key,omitempty"` + Locations CertificateLocations `json:"locations,omitempty"` +} + +// Locations struct for client certificate rule v2 +type CertificateLocations struct { + Paths []string `json:"paths,omitempty"` + TrustStores []string `json:"trust_stores,omitempty"` } // DevicePostureRuleListResponse represents the response from the list diff --git a/device_posture_rule_test.go b/device_posture_rule_test.go index b9b72b2b82..62e8c50400 100644 --- a/device_posture_rule_test.go +++ b/device_posture_rule_test.go @@ -645,6 +645,69 @@ func TestDevicePostureClientCertificateRule(t *testing.T) { } } +func TestDevicePostureClientCertificateRuleV2(t *testing.T) { + setup() + defer teardown() + + handler := func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodGet, r.Method, "Expected method 'GET', got %s", r.Method) + w.Header().Set("content-type", "application/json") + fmt.Fprintf(w, `{ + "success": true, + "errors": [], + "messages": [], + "result": { + "id": "480f4f69-1a28-4fdd-9240-1ed29f0ac1db", + "schedule": "1h", + "expiration": "1h", + "type": "client_certificate_v2", + "name": "My rule name", + "description": "My description", + "match": [ + { + "platform": "windows" + } + ], + "input": { + "certificate_id": "d2c04b78-3ba2-4294-8efa-4e85aef0777f", + "cn": "example.com", + "extended_key_usage": ["clientAuth", "emailProtection"], + "locations": {"trust_stores": ["system"]}, + "check_private_key": true + } + } + } + `) + } + + want := DevicePostureRule{ + ID: "480f4f69-1a28-4fdd-9240-1ed29f0ac1db", + Name: "My rule name", + Description: "My description", + Type: "client_certificate_v2", + Schedule: "1h", + Expiration: "1h", + Match: []DevicePostureRuleMatch{{Platform: "windows"}}, + Input: DevicePostureRuleInput{ + CertificateID: "d2c04b78-3ba2-4294-8efa-4e85aef0777f", + CommonName: "example.com", + CheckPrivateKey: true, + ExtendedKeyUsage: []string{"clientAuth", "emailProtection"}, + Locations: CertificateLocations{ + TrustStores: []string{"system"}, + }, + }, + } + + mux.HandleFunc("/accounts/"+testAccountID+"/devices/posture/480f4f69-1a28-4fdd-9240-1ed29f0ac1db", handler) + + actual, err := client.DevicePostureRule(context.Background(), testAccountID, "480f4f69-1a28-4fdd-9240-1ed29f0ac1db") + + if assert.NoError(t, err) { + assert.Equal(t, want, actual) + } +} + func TestCreateDevicePostureRule(t *testing.T) { setup() defer teardown()