diff --git a/.github/wordlist.txt b/.github/wordlist.txt index c094daf42..7e95bcf1a 100644 --- a/.github/wordlist.txt +++ b/.github/wordlist.txt @@ -1275,3 +1275,38 @@ ReadContainersByDateRangeCount ReadContainerCountByRegistry FindContainersCountAffectedByZeroDayVulnerabilities ReadVulnerableContainerImageCount +QueryActivityByCaseID +CAwsAccount +GetD +Enums +shubham +WorkflowUpdateHumanInputV +WorkflowGetHumanInputV +WorkflowDefinitionsCreate +WorkflowDefinitionsUpdate +WorkflowDefinitionsImport +WorkflowDefinitionsExport +WorkflowExecutionsCombined +WorkflowDefinitionsCombined +DeletePolicyGroup +UpdatePolicyGroups +CreatePolicyGroups +ReadPolicyGroups +UpdatePolicyExclusions +ReadPolicyExclusions +DeletePolicy +ReadPolicies +CGCPUserScriptsAttachment +CGCPServiceAccountsExt +CGCPAccount +ConnectD +DeleteD +GetDiscoverCloudAzureUserScriptsAttachment +GetCSPMGCPServiceAccountsExt +ConnectCSPMGCPAccount +UpdateCSPMGCPAccount +DeleteCSPMGCPAccount +CreateCSPMAzureManagementGroup +GetCSPMAzureManagementGroup +ReadContainerAlertsCountBySeverity +PostAggregatesAlertsV diff --git a/CHANGELOG.md b/CHANGELOG.md index 815cb9947..ce04b1d94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,129 @@ +# Version 1.4.1 +## Added features and functionality ++ Added: `include_hidden` argument added to the _PostAggregatesAlertsV2_, _PostEntitiesAlertsV2_, _PatchEntitiesAlertsV3_ and _GetQueriesAlertsV2_ operations. + - `_endpoint/_alerts.py` + ++ Added: _ReadContainerAlertsCountBySeverity_ operation added to the __Container Alerts__ service collection. + - `_endpoint/_container_alerts.py` + - `container_alerts.py` + > Unit testing expanded to complete code coverage. + - `tests/test_container_alerts.py` + ++ Added: `cspm_lite` argument added to the _GetCSPMAwsAccount_ and _GetCSPMAzureAccount_ operations within the __CSPM Registration__ service collection. + - `_endpoint/_cspm_registration.py` + - `cspm_registration.py` + ++ Added: `azure_management_group` argument added to the _GetCSPMAzureUserScriptsAttachment_ operation within the __CSPM Registration__ service collection. + - `_endpoint/_cspm_registration.py` + - `cspm_registration.py` + ++ Added: 9 new operations added to the __CSPM Registration__ service collection. + * _GetCSPMAzureManagementGroup_ + * _CreateCSPMAzureManagementGroup_ + * _GetCSPMCGPAccount_ + * _CreateCSPMGCPAccount_ + * _DeleteCSPMGCPAccount_ + * _UpdateCSPMGCPAccount_ + * _ConnectCSPMGCPAccount_ + * _GetCSPMGCPServiceAccountsExt_ + * _GetCSPMGCPUserScriptsAttachment_ + - `_endpoint/_cspm_registration.py` + - `_payload/_cspm_registration.py` + - `cspm_registration.py` + > Unit testing expanded to complete code coverage. + - `tests/test_cspm_registration.py` + ++ Added: `azure_management_group` argument added to the _GetDiscoverCloudAzureUserScriptsAttachment_ operation within the __D4C Registration__ service collection. + - `_endpoint/_d4c_registration.py` + - `d4c_registration.py` + ++ Added: 4 new operations added to the __D4C Registration__ service collection. + * _DeleteD4CGCPAccount_ + * _ConnectD4CGCPAccount_ + * _GetD4CGCPServiceAccountsExt_ + * _GetD4CGCPUserScriptsAttachment_ + - `_endpoint/_d4c_registration.py` + - `_payload/_d4c_registration.py` + - `d4c_registration.py` + > Unit testing expanded to complete code coverage. + - `tests/test_d4c_registration.py` + ++ Added: `execution_cid` argument added to the _WorkflowExecute_ operation within the __Workflows__ service collection. + - `_endpoint/_workflows.py` + - `workflows.py` + ++ Added: New service collection __Image Assessment Policies__ containing 11 new operations. + * _ReadPolicies_ + * _CreatePolicies_ + * _UpdatePolicies_ + * _DeletePolicy_ + * _ReadPolicyExclusions_ + * _UpdatePolicyExclusions_ + * _ReadPolicyGroups_ + * _CreatePolicyGroups_ + * _UpdatePolicyGroups_ + * _DeletePolicyGroup_ + * _UpdatePolicyPrecedence_ + - `_endpoint/__init__.py` + - `_endpoint/_image_assessment_policies.py` + > 3 new payload handlers are added. + - `_payload/__init__.py` + - `_payload/_container.py` + - `__init__.py` + - `image_assessment_policies.py` + > Unit testing expanded to complete code coverage. + - `tests/test_image_assessment_policies.py` + ++ Added: 8 new operations added to the __Workflows__ service collection. + * _WorkflowDefinitionsCombined_ + * _WorkflowExecutionsCombined_ + * _WorkflowDefinitionsExport_ + * _WorkflowDefinitionsImport_ + * _WorkflowDefinitionsUpdate_ + * _WorkflowDefinitionsCreate_ + * _WorkflowGetHumanInputV1_ + * _WorkflowUpdateHumanInputV1_ + - `_endpoint/_workflows.py` + - `workflows.py` + > 2 new payload handlers are added. + - `_payload/__init__.py` + - `_payload/_workflows.py` + > Unit testing expanded to complete code coverage. + - `tests/test_workflows.py` + +## Issue resolved ++ Fixed: `member_cid` argument is not being passed to the authentication event when leveraging Environment Authentication. Closes #1105. + - `_auth_object/_falcon_interface.py` + ++ Fixed: `rule_ids` is not included in body payloads when the list is empty for the _update_rule_groups_ operation within the __Firewall Management__ Service Class. Closes #1107. + - `_payload/_firewall.py` + ++ Fixed: Added missing actions to _allowed_actions validator within `PerformActionV2` method of the __Hosts__ service collection. Closes #1108. + - `hosts.py` + - Thanks go out to @i-shubham01 for identifying and resolving this issue! 🙇 + +## Other ++ Updated: Enums added to _GetCSPMAwsAccount_ and _GetCSPMAwsConsoleSetupURLs_ operations within the __CSPM Registration__ endpoint module. + - `_endpoint/_cspm_registration.py` + ++ Updated: Several parameter descriptions within the __Custom IOA__ endpoint module updated. + - `_endpoint/_custom_ioa.py` + - `_endpoint/deprecated/_custom_ioa.py` + ++ Updated: Enum updated within the _GetD4CAwsAccount_ operation of the __D4C Registration__ endpoint module. + - `_endpoint/_d4c_registration.py` + ++ Updated: Parameter description for the _Submit_ operation within the __Falcon Intelligence Sandbox__ endpoint module updated. + - `_endpoint/_falconx_sandbox.py` + ++ Updated: Multiple parameter descriptions within the __Kubernetes Protection__ endpoint module updated. + - `_endpoint/_kubernetes_protection_.py` + ++ Updated: Enum updated within the _QueryActivityByCaseID_ operation of the __Message Center__ endpoint module. + - `_endpoint/_message_center.py` + +--- + # Version 1.4.0 ## Other + Dropped: Python 3.6 support. diff --git a/src/falconpy/__init__.py b/src/falconpy/__init__.py index c4dee67c2..8c286b775 100644 --- a/src/falconpy/__init__.py +++ b/src/falconpy/__init__.py @@ -118,6 +118,7 @@ from .host_group import HostGroup from .hosts import Hosts from .identity_protection import IdentityProtection +from .image_assessment_policies import ImageAssessmentPolicies from .incidents import Incidents from .installation_tokens import InstallationTokens from .intel import Intel @@ -193,7 +194,8 @@ "RealTimeResponseAudit", "Workflows", "DeprecatedClass", "DeprecatedOperation", "SDKDeprecationWarning", "ConfigurationAssessmentEvaluationLogic", "ConfigurationAssessment", "ContainerAlerts", "ContainerDetections", "ContainerImages", "ContainerPackages", - "ContainerVulnerabilities", "DriftIndicators", "UnidentifiedContainers" + "ContainerVulnerabilities", "DriftIndicators", "UnidentifiedContainers", + "ImageAssessmentPolicies" ] """ This is free and unencumbered software released into the public domain. diff --git a/src/falconpy/_auth_object/_falcon_interface.py b/src/falconpy/_auth_object/_falcon_interface.py index f71cf2e3a..731413acd 100644 --- a/src/falconpy/_auth_object/_falcon_interface.py +++ b/src/falconpy/_auth_object/_falcon_interface.py @@ -163,6 +163,9 @@ def __init__(self, "client_id": api_id, "client_secret": api_sec } + # Provide member_cid for MSSP environment authentication scenarios. Issue #1105. + if member_cid: + self._creds["member_cid"] = member_cid # Log the creation of this object if debugging is enabled. # Starting with v1.3.0 minimal Python native logging is available. In order to reduce diff --git a/src/falconpy/_endpoint/__init__.py b/src/falconpy/_endpoint/__init__.py index 9488020cd..b7c338f93 100644 --- a/src/falconpy/_endpoint/__init__.py +++ b/src/falconpy/_endpoint/__init__.py @@ -68,6 +68,7 @@ from ._host_group import _host_group_endpoints from ._hosts import _hosts_endpoints from ._identity_protection import _identity_protection_endpoints +from ._image_assessment_policies import _image_assessment_policies_endpoints from ._incidents import _incidents_endpoints from ._installation_tokens import _installation_tokens_endpoints from ._intel import _intel_endpoints @@ -135,6 +136,7 @@ api_endpoints.extend(_host_group_endpoints) api_endpoints.extend(_hosts_endpoints) api_endpoints.extend(_identity_protection_endpoints) +api_endpoints.extend(_image_assessment_policies_endpoints) api_endpoints.extend(_incidents_endpoints) api_endpoints.extend(_installation_tokens_endpoints) api_endpoints.extend(_intel_endpoints) diff --git a/src/falconpy/_endpoint/_alerts.py b/src/falconpy/_endpoint/_alerts.py index 26f34656d..fc2c388f5 100644 --- a/src/falconpy/_endpoint/_alerts.py +++ b/src/falconpy/_endpoint/_alerts.py @@ -59,6 +59,13 @@ "retrieves aggregate values for Alerts across all CIDs", "alerts", [ + { + "type": "boolean", + "default": True, + "description": "allows previously hidden alerts to be retrieved", + "name": "include_hidden", + "in": "query" + }, { "description": "request body takes a list of aggregate-alert query requests", "name": "body", @@ -114,6 +121,13 @@ "retrieves all Alerts given their composite ids", "alerts", [ + { + "type": "boolean", + "default": True, + "description": "allows previously hidden alerts to be retrieved", + "name": "include_hidden", + "in": "query" + }, { "name": "body", "in": "body", @@ -125,7 +139,7 @@ "PatchEntitiesAlertsV2", "PATCH", "/alerts/entities/alerts/v2", - "Perform actions on detections identified by detection ID(s) in request.\nEach action has a name and a " + "Perform actions on Alerts identified by composite ID(s) in request.\nEach action has a name and a " "description which describes what the action does.\nIf a request adds and removes tag in a single request, the " "order of processing would be to remove tags before adding new ones in.\n\n", "alerts", @@ -142,11 +156,18 @@ "PatchEntitiesAlertsV3", "PATCH", "/alerts/entities/alerts/v3", - "Perform actions on detections identified by detection ID(s) in request.\nEach action has a name and a " + "Perform actions on Alerts identified by composite ID(s) in request.\nEach action has a name and a " "description which describes what the action does.\nIf a request adds and removes tag in a single request, the " "order of processing would be to remove tags before adding new ones in.\n\n", "alerts", [ + { + "type": "boolean", + "default": True, + "description": "allows previously hidden alerts to be retrieved", + "name": "include_hidden", + "in": "query" + }, { "description": "request body takes a list of action parameter request that is applied against all \"ids\" provided", "name": "body", @@ -219,6 +240,13 @@ "retrieves all Alerts ids that match a given query", "alerts", [ + { + "type": "boolean", + "default": True, + "description": "allows previously hidden alerts to be retrieved", + "name": "include_hidden", + "in": "query" + }, { "type": "integer", "description": "The first detection to return, where `0` is the latest detection. Use with the " diff --git a/src/falconpy/_endpoint/_container_alerts.py b/src/falconpy/_endpoint/_container_alerts.py index 1a83b0f0c..35c9bbb09 100644 --- a/src/falconpy/_endpoint/_container_alerts.py +++ b/src/falconpy/_endpoint/_container_alerts.py @@ -37,6 +37,22 @@ """ _container_alerts_endpoints = [ + [ + "ReadContainerAlertsCountBySeverity", + "GET", + "/container-security/aggregates/container-alerts/count-by-severity/v1", + "Get Container Alerts counts by severity", + "container_alerts", + [ + { + "type": "string", + "description": "Search Container Alerts using a query in Falcon Query Language (FQL). Supported " + "filters: cid,container_id,last_seen", + "name": "filter", + "in": "query" + } + ] + ], [ "ReadContainerAlertsCount", "GET", @@ -47,7 +63,7 @@ { "type": "string", "description": "Search Container Alerts using a query in Falcon Query Language (FQL). Supported " - "filters: cid,last_seen", + "filters: cid,container_id,last_seen", "name": "filter", "in": "query" } diff --git a/src/falconpy/_endpoint/_cspm_registration.py b/src/falconpy/_endpoint/_cspm_registration.py index 9a51ac2c8..afb35ba74 100644 --- a/src/falconpy/_endpoint/_cspm_registration.py +++ b/src/falconpy/_endpoint/_cspm_registration.py @@ -46,9 +46,10 @@ "cspm_registration", [ { - "maxLength": 4, - "minLength": 3, - "pattern": "^(full|dry)$", + "enum": [ + "dry", + "full" + ], "type": "string", "description": "Type of scan, dry or full, to perform on selected accounts", "name": "scan-type", @@ -85,7 +86,10 @@ "in": "query" }, { - "pattern": "^(provisioned|operational)$", + "enum": [ + "provisioned", + "operational" + ], "type": "string", "description": "Account status to filter results by.", "name": "status", @@ -101,10 +105,19 @@ "in": "query" }, { - "pattern": "^(true|false)$", "enum": [ - "false", - "true" + "true", + "false" + ], + "type": "string", + "description": "Only return CSPM Lite accounts", + "name": "cspm_lite", + "in": "query" + }, + { + "enum": [ + "true", + "false" ], "type": "string", "description": "Only return migrated d4c accounts", @@ -204,10 +217,9 @@ "in": "query" }, { - "pattern": "^(true|false)$", "enum": [ - "false", - "true" + "true", + "false" ], "type": "string", "name": "use_existing_cloudtrail", @@ -286,6 +298,17 @@ "name": "status", "in": "query" }, + { + "pattern": "^(true|false)$", + "enum": [ + "false", + "true" + ], + "type": "string", + "description": "Only return CSPM Lite accounts", + "name": "cspm_lite", + "in": "query" + }, { "maxLength": 3, "minLength": 1, @@ -318,6 +341,20 @@ } ] ], + [ + "UpdateCSPMAzureAccount", + "PATCH", + "/cloud-connect-cspm-azure/entities/account/v1", + "Patches a existing account in our system for a customer.", + "cspm_registration", + [ + { + "name": "body", + "in": "body", + "required": True + } + ] + ], [ "DeleteCSPMAzureAccount", "DELETE", @@ -448,6 +485,54 @@ } ] ], + [ + "GetCSPMAzureManagementGroup", + "GET", + "/cloud-connect-cspm-azure/entities/management-group/v1", + "Return information about Azure management group registration", + "cspm_registration", + [ + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi", + "description": "Tenant ids to filter azure accounts", + "name": "tenant_ids", + "in": "query" + }, + { + "maxLength": 3, + "minLength": 1, + "type": "integer", + "default": 100, + "description": "The maximum records to return. Defaults to 100.", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "The offset to start retrieving records from", + "name": "offset", + "in": "query" + } + ] + ], + [ + "CreateCSPMAzureManagementGroup", + "POST", + "/cloud-connect-cspm-azure/entities/management-group/v1", + "Creates a new management group in our system for a customer.", + "cspm_registration", + [ + { + "name": "body", + "in": "body", + "required": True + } + ] + ], [ "GetCSPMAzureUserScriptsAttachment", "GET", @@ -490,6 +575,193 @@ "description": "Template to be rendered", "name": "template", "in": "query" + }, + { + "type": "boolean", + "description": "Use Azure Management Group", + "name": "azure_management_group", + "in": "query" + } + ] + ], + [ + "GetCSPMCGPAccount", + "GET", + "/cloud-connect-cspm-gcp/entities/account/v1", + "Returns information about the current status of an GCP account.", + "cspm_registration", + [ + { + "enum": [ + "Folder", + "Organization", + "Project" + ], + "type": "string", + "description": "GCP Hierarchy Parent Type, organization/folder/project", + "name": "parent_type", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi", + "description": "Hierarchical Resource IDs of accounts", + "name": "ids", + "in": "query" + }, + { + "enum": [ + "dry", + "full" + ], + "type": "string", + "description": "Type of scan, dry or full, to perform on selected accounts", + "name": "scan-type", + "in": "query" + }, + { + "enum": [ + "operational", + "provisioned" + ], + "type": "string", + "description": "Account status to filter results by.", + "name": "status", + "in": "query" + }, + { + "maxLength": 3, + "minLength": 1, + "type": "integer", + "default": 100, + "description": "The maximum records to return. Defaults to 100.", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "The offset to start retrieving records from", + "name": "offset", + "in": "query" + }, + { + "type": "string", + "description": "Order fields in ascending or descending order. Ex: parent_type|asc.", + "name": "sort", + "in": "query" + } + ] + ], + [ + "CreateCSPMGCPAccount", + "POST", + "/cloud-connect-cspm-gcp/entities/account/v1", + "Creates a new account in our system for a customer and generates a new service account for them to add " + "access to in their GCP environment to grant us access.", + "cspm_registration", + [ + { + "name": "body", + "in": "body", + "required": True + } + ] + ], + [ + "UpdateCSPMGCPAccount", + "PATCH", + "/cloud-connect-cspm-gcp/entities/account/v1", + "Patches a existing account in our system for a customer.", + "cspm_registration", + [ + { + "name": "body", + "in": "body", + "required": True + } + ] + ], + [ + "DeleteCSPMGCPAccount", + "DELETE", + "/cloud-connect-cspm-gcp/entities/account/v1", + "Deletes a GCP account from the system.", + "cspm_registration", + [ + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi", + "description": "Hierarchical Resource IDs of accounts", + "name": "ids", + "in": "query" + } + ] + ], + [ + "ConnectCSPMGCPAccount", + "POST", + "/cloud-connect-cspm-gcp/entities/account/v2", + "Creates a new GCP account with newly-uploaded service account or connects with existing service account " + "with only the following fields: parent_id, parent_type and service_account_id", + "cspm_registration", + [ + { + "name": "body", + "in": "body", + "required": True + } + ] + ], + [ + "GetCSPMGCPServiceAccountsExt", + "GET", + "/cloud-connect-cspm-gcp/entities/service-accounts/v1", + "Returns the service account id and client email for external clients.", + "cspm_registration", + [ + { + "pattern": "^\\d+$", + "type": "string", + "description": "Service Account ID", + "name": "id", + "in": "query" + } + ] + ], + [ + "GetCSPMGCPUserScriptsAttachment", + "GET", + "/cloud-connect-cspm-gcp/entities/user-scripts-download/v1", + "Return a script for customer to run in their cloud environment to grant us access to their GCP " + "environment as a downloadable attachment", + "cspm_registration", + [ + { + "enum": [ + "Folder", + "Organization", + "Project" + ], + "type": "string", + "description": "GCP Hierarchy Parent Type, organization/folder/project", + "name": "parent_type", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi", + "description": "Hierarchical Resource IDs of accounts", + "name": "ids", + "in": "query" } ] ], @@ -672,7 +944,8 @@ "GetConfigurationDetections", "GET", "/detects/entities/iom/v1", - "Get list of active misconfigurations", + "Get list of active misconfigurations. This endpoint is deprecated, please use GetConfigurationDetectionIDsV2 and " + "GetConfigurationDetectionEntities instead", "cspm_registration", [ { diff --git a/src/falconpy/_endpoint/_custom_ioa.py b/src/falconpy/_endpoint/_custom_ioa.py index 55ab0073f..ac36fd61f 100644 --- a/src/falconpy/_endpoint/_custom_ioa.py +++ b/src/falconpy/_endpoint/_custom_ioa.py @@ -341,7 +341,7 @@ "name" ], "type": "string", - "description": "Possible order by fields: {name, created_by, created_on, modified_by, modified_on, enabled}", + "description": "Possible order by fields: {enabled, name, created_by, created_on, modified_by, modified_on}", "name": "sort", "in": "query" }, @@ -391,7 +391,7 @@ "name" ], "type": "string", - "description": "Possible order by fields: {name, created_by, created_on, modified_by, modified_on, enabled}", + "description": "Possible order by fields: {enabled, name, created_by, created_on, modified_by, modified_on}", "name": "sort", "in": "query" }, @@ -466,10 +466,10 @@ "rules.ruletype_name" ], "type": "string", - "description": "Possible order by fields: {rules.created_on, rules.current_version.action_label, " - "rules.current_version.modified_by, rules.current_version.modified_on, rules.ruletype_name, rules.enabled, " - "rules.current_version.description, rules.current_version.pattern_severity, rules.created_by, " - "rules.current_version.name}", + "description": "Possible order by fields: {rules.current_version.description, " + "rules.current_version.action_label, rules.current_version.modified_on, rules.created_on, " + "rules.current_version.name, rules.created_by, rules.current_version.pattern_severity, " + "rules.current_version.modified_by, rules.ruletype_name, rules.enabled}", "name": "sort", "in": "query" }, diff --git a/src/falconpy/_endpoint/_d4c_registration.py b/src/falconpy/_endpoint/_d4c_registration.py index 53326a1ea..49b7f1bf3 100644 --- a/src/falconpy/_endpoint/_d4c_registration.py +++ b/src/falconpy/_endpoint/_d4c_registration.py @@ -96,10 +96,9 @@ "in": "query" }, { - "pattern": "^(true|false)$", "enum": [ - "false", - "true" + "true", + "false" ], "type": "string", "description": "Only return migrated d4c accounts", @@ -380,6 +379,12 @@ "description": "Template to be rendered", "name": "template", "in": "query" + }, + { + "type": "boolean", + "description": "Use Azure Management Group", + "name": "azure_management_group", + "in": "query" } ] ], @@ -486,6 +491,97 @@ "d4c_registration", [] ], + [ + "DeleteD4CGCPAccount", + "DELETE", + "/cloud-connect-gcp/entities/account/v1", + "Deletes a GCP account from the system.", + "d4c_registration", + [ + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi", + "description": "Hierarchical Resource IDs of accounts", + "name": "ids", + "in": "query" + } + ] + ], + [ + "ConnectD4CGCPAccount", + "POST", + "/cloud-connect-gcp/entities/account/v2", + "Creates a new GCP account with newly-uploaded service account or connects with existing service account " + "with only the following fields: parent_id, parent_type and service_account_id", + "d4c_registration", + [ + { + "name": "body", + "in": "body", + "required": True + } + ] + ], + [ + "GetD4CGCPServiceAccountsExt", + "GET", + "/cloud-connect-gcp/entities/service-accounts/v1", + "Returns the service account id and client email for external clients.", + "d4c_registration", + [ + { + "pattern": "^\\d+$", + "type": "string", + "description": "Service Account ID", + "name": "id", + "in": "query" + } + ] + ], + [ + "GetD4CGCPUserScriptsAttachment", + "GET", + "/cloud-connect-gcp/entities/user-scripts-download/v1", + "Return a script for customer to run in their cloud environment to grant us access to their GCP " + "environment as a downloadable attachment", + "d4c_registration", + [ + { + "enum": [ + "Folder", + "Organization", + "Project" + ], + "type": "string", + "description": "GCP Hierarchy Parent Type, organization/folder/project", + "name": "parent_type", + "in": "query" + }, + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi", + "description": "Hierarchical Resource IDs of accounts", + "name": "ids", + "in": "query" + }, + { + "enum": [ + "operational", + "provisioned" + ], + "type": "string", + "description": "Account status to filter results by.", + "name": "status", + "in": "query" + } + ] + ], [ "GetD4CGCPUserScripts", "GET", diff --git a/src/falconpy/_endpoint/_falconx_sandbox.py b/src/falconpy/_endpoint/_falconx_sandbox.py index 7649f3054..148603ace 100644 --- a/src/falconpy/_endpoint/_falconx_sandbox.py +++ b/src/falconpy/_endpoint/_falconx_sandbox.py @@ -246,13 +246,14 @@ "description": "Submit either a URL or a sample SHA256 for sandbox analysis. The sample file must have " " been previously uploaded through `/samples/entities/samples/v2`. You must specify a JSON object that includes " " the `falconx.SubmissionParametersV1` key/value pairs shown below.\n\n**`environment_id`**: Specifies the " - "sandbox environment used for analysis. Values:\n\n- `300`: Linux Ubuntu 16.04, 64-bit\n- `200`: Android " - "(static analysis)\n- `160`: Windows 10, 64-bit\n- `110`: Windows 7, 64-bit\n- `100`: Windows 7, " - "32-bit\n\n**`sha256`** ID of the sample, which is a SHA256 hash value. Find a sample ID from the response when " - " uploading a malware sample or search with `/falconx/queries/submissions/v1`.The `url` parameter must be unset " - " if `sha256` is used.\n\n**`url`** A web page or file URL. It can be HTTP(S) or FTP. The `sha256` parameter " - "must be unset if `url` is used.\n\n**`action_script`** (optional): Runtime script for sandbox analysis. " - "Values:\n\n- `default`\n- `default_maxantievasion`\n- `default_randomfiles`\n- `default_randomtheme`\n- " + "sandbox environment used for analysis. Values:\n\n- `400`: MacOS Catalina 10.15\n- `300`: Linux Ubuntu 16.04, " + "64-bit\n- `200`: Android (static analysis)\n- `160`: Windows 10, 64-bit\n- `140`: Windows 11, 64-bit\n- `110`: " + " Windows 7, 64-bit\n- `100`: Windows 7, 32-bit\n\n**`sha256`** ID of the sample, which is a SHA256 hash value. " + " Find a sample ID from the response when uploading a malware sample or search with " + "`/falconx/queries/submissions/v1`.The `url` parameter must be unset if `sha256` is used.\n\n**`url`** A web " + "page or file URL. It can be HTTP(S) or FTP. The `sha256` parameter must be unset if `url` is " + "used.\n\n**`action_script`** (optional): Runtime script for sandbox analysis. Values:\n\n- `default`\n- " + "`default_maxantievasion`\n- `default_randomfiles`\n- `default_randomtheme`\n- " "`default_openie`\n\n**`command_line`** (optional): Command line script passed to the submitted file at " "runtime. Max length: 2048 characters\n\n**`document_password`** (optional): Auto-filled for Adobe or Office " "files that prompt for a password. Max length: 32 characters\n\n**`enable_tor`** (optional): Deprecated, please " diff --git a/src/falconpy/_endpoint/_image_assessment_policies.py b/src/falconpy/_endpoint/_image_assessment_policies.py new file mode 100644 index 000000000..f79e8ec86 --- /dev/null +++ b/src/falconpy/_endpoint/_image_assessment_policies.py @@ -0,0 +1,194 @@ +"""Internal API endpoint constant library. + + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" + +_image_assessment_policies_endpoints = [ + [ + "ReadPolicies", + "GET", + "/container-security/entities/image-assessment-policies/v1", + "Get all Image Assessment policies", + "image_assessment_policies", + [] + ], + [ + "CreatePolicies", + "POST", + "/container-security/entities/image-assessment-policies/v1", + "Create Image Assessment policies", + "image_assessment_policies", + [ + { + "name": "body", + "in": "body", + "required": True + } + ] + ], + [ + "UpdatePolicies", + "PATCH", + "/container-security/entities/image-assessment-policies/v1", + "Update Image Assessment Policy entities", + "image_assessment_policies", + [ + { + "type": "string", + "description": "Image Assessment Policy entity UUID", + "name": "id", + "in": "query", + "required": True + }, + { + "name": "body", + "in": "body", + "required": True + } + ] + ], + [ + "DeletePolicy", + "DELETE", + "/container-security/entities/image-assessment-policies/v1", + "Delete Image Assessment Policy by policy UUID", + "image_assessment_policies", + [ + { + "type": "string", + "description": "Image Assessment Policy entity UUID", + "name": "id", + "in": "query", + "required": True + } + ] + ], + [ + "ReadPolicyExclusions", + "GET", + "/container-security/entities/image-assessment-policy-exclusions/v1", + "Retrieve Image Assessment Policy Exclusion entities", + "image_assessment_policies", + [] + ], + [ + "UpdatePolicyExclusions", + "POST", + "/container-security/entities/image-assessment-policy-exclusions/v1", + "Update Image Assessment Policy Exclusion entities", + "image_assessment_policies", + [ + { + "name": "body", + "in": "body", + "required": True + } + ] + ], + [ + "ReadPolicyGroups", + "GET", + "/container-security/entities/image-assessment-policy-groups/v1", + "Retrieve Image Assessment Policy Group entities", + "image_assessment_policies", + [] + ], + [ + "CreatePolicyGroups", + "POST", + "/container-security/entities/image-assessment-policy-groups/v1", + "Create Image Assessment Policy Group entities", + "image_assessment_policies", + [ + { + "name": "body", + "in": "body", + "required": True + } + ] + ], + [ + "UpdatePolicyGroups", + "PATCH", + "/container-security/entities/image-assessment-policy-groups/v1", + "Update Image Assessment Policy Group entities", + "image_assessment_policies", + [ + { + "type": "string", + "description": "Policy Image Group entity UUID", + "name": "id", + "in": "query", + "required": True + }, + { + "name": "body", + "in": "body", + "required": True + } + ] + ], + [ + "DeletePolicyGroup", + "DELETE", + "/container-security/entities/image-assessment-policy-groups/v1", + "Delete Image Assessment Policy Group entities", + "image_assessment_policies", + [ + { + "type": "string", + "description": "Policy Image Group entity UUID", + "name": "id", + "in": "query", + "required": True + } + ] + ], + [ + "UpdatePolicyPrecedence", + "POST", + "/container-security/entities/image-assessment-policy-precedence/v1", + "Update Image Assessment Policy precedence", + "image_assessment_policies", + [ + { + "name": "body", + "in": "body", + "required": True + } + ] + ] +] diff --git a/src/falconpy/_endpoint/_kubernetes_protection.py b/src/falconpy/_endpoint/_kubernetes_protection.py index 0ec5e2134..1f2348990 100644 --- a/src/falconpy/_endpoint/_kubernetes_protection.py +++ b/src/falconpy/_endpoint/_kubernetes_protection.py @@ -56,7 +56,7 @@ { "type": "string", "description": "Retrieve count of Kubernetes clusters that match a query in Falcon Query Language " - "(FQL). Supported filters: access,agent_status,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,cluster " + "(FQL). Supported filters: access,agent_status,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,cluster" "_name,cluster_status,container_count,kubernetes_version,last_seen, management_status, node_count, pod_count, " "tags", "name": "filter", @@ -74,7 +74,7 @@ { "type": "string", "description": "Retrieve count of Kubernetes clusters that match a query in Falcon Query Language " - "(FQL). Supported filters: access,agent_status,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,cluster " + "(FQL). Supported filters: access,agent_status,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,cluster" "_name,cluster_status,container_count,kubernetes_version,last_seen, management_status, node_count, pod_count, " "tags", "name": "filter", @@ -92,7 +92,7 @@ { "type": "string", "description": "Retrieve count of Kubernetes clusters that match a query in Falcon Query Language " - "(FQL). Supported filters: access,agent_status,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,cluster " + "(FQL). Supported filters: access,agent_status,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,cluster" "_name,cluster_status,container_count,kubernetes_version,last_seen, management_status, node_count, pod_count, " "tags", "name": "filter", @@ -109,12 +109,12 @@ [ { "type": "string", - "description": "Get container counts using a query in Falcon Query Language (FQL). Supported filters: " - " agent_id,agent_type,allow_privilege_escalation,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,clust " + "description": "Get container counts using a query in Falcon Query Language (FQL). Supported filters:" + " agent_id,agent_type,allow_privilege_escalation,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,clust" "er_name,container_id,container_name,cve_id,detection_name,first_seen,image_detection_count,image_digest,image_" "has_been_assessed,image_id,image_registry,image_repository,image_tag,image_vulnerability_count,insecure_mount_" - "source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,labels,last_seen,namespace,nod " - "e_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_write_access,run_as_root_group,run_a " + "source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,labels,last_seen,namespace,nod" + "e_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_write_access,run_as_root_group,run_a" "s_root_user,running_status", "name": "filter", "in": "query" @@ -161,11 +161,11 @@ { "type": "string", "description": "Retrieve count of Kubernetes containers that match a query in Falcon Query Language " - "(FQL). Supported filters: agent_id,agent_type,allow_privilege_escalation,cid,cloud_account_id,cloud_name,clou " + "(FQL). Supported filters: agent_id,agent_type,allow_privilege_escalation,cid,cloud_account_id,cloud_name,clou" "d_region,cluster_id,cluster_name,container_id,container_name,cve_id,detection_name,first_seen,image_detection_" - "count,image_digest,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_vulnerabil " - "ity_count,insecure_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,label " - "s,last_seen,namespace,node_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_write_acces " + "count,image_digest,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_vulnerabil" + "ity_count,insecure_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,label" + "s,last_seen,namespace,node_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_write_acces" "s,run_as_root_group,run_as_root_user,running_status", "name": "filter", "in": "query" @@ -182,11 +182,11 @@ { "type": "string", "description": "Retrieve count of Kubernetes containers that match a query in Falcon Query Language " - "(FQL). Supported filters: agent_id,agent_type,allow_privilege_escalation,cid,cloud_account_id,cloud_name,clou " + "(FQL). Supported filters: agent_id,agent_type,allow_privilege_escalation,cid,cloud_account_id,cloud_name,clou" "d_region,cluster_id,cluster_name,container_id,container_name,cve_id,detection_name,first_seen,image_detection_" - "count,image_digest,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_vulnerabil " - "ity_count,insecure_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,label " - "s,last_seen,namespace,node_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_write_acces " + "count,image_digest,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_vulnerabil" + "ity_count,insecure_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,label" + "s,last_seen,namespace,node_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_write_acces" "s,run_as_root_group,run_as_root_user,running_status", "name": "filter", "in": "query" @@ -221,11 +221,11 @@ { "type": "string", "description": "Retrieve count of Kubernetes containers that match a query in Falcon Query Language " - "(FQL). Supported filters: agent_id,agent_type,allow_privilege_escalation,cid,cloud_account_id,cloud_name,clou " + "(FQL). Supported filters: agent_id,agent_type,allow_privilege_escalation,cid,cloud_account_id,cloud_name,clou" "d_region,cluster_id,cluster_name,container_id,container_name,cve_id,detection_name,first_seen,image_detection_" - "count,image_digest,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_vulnerabil " - "ity_count,insecure_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,label " - "s,last_seen,namespace,node_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_write_acces " + "count,image_digest,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_vulnerabil" + "ity_count,insecure_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,label" + "s,last_seen,namespace,node_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_write_acces" "s,run_as_root_group,run_as_root_user,running_status", "name": "filter", "in": "query" @@ -242,10 +242,10 @@ { "type": "string", "description": "Retrieve count of Kubernetes containers that match a query in Falcon Query Language " - "(FQL). Supported filters: agent_id,allow_privilege_escalation,cid,cloud_account_id,cloud_name,cloud_region,cl " - "uster_id,cluster_name,container_id,container_name,cve_id,detection_name,first_seen,image_detection_count,image " - "_digest,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_vulnerability_count,i " - "nsecure_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,labels,last_seen " + "(FQL). Supported filters: agent_id,allow_privilege_escalation,cid,cloud_account_id,cloud_name,cloud_region,cl" + "uster_id,cluster_name,container_id,container_name,cve_id,detection_name,first_seen,image_detection_count,image" + "_digest,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_vulnerability_count,i" + "nsecure_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,labels,last_seen" ",namespace,node_name,node_uid,pod_id,pod_name,port,privileged,root_write_access,run_as_root_group,run_as_root_" "user,running_status", "name": "filter", @@ -263,11 +263,11 @@ { "type": "string", "description": "Retrieve count of Kubernetes containers that match a query in Falcon Query Language " - "(FQL). Supported filters: agent_id,agent_type,allow_privilege_escalation,cid,cloud_account_id,cloud_name,clou " + "(FQL). Supported filters: agent_id,agent_type,allow_privilege_escalation,cid,cloud_account_id,cloud_name,clou" "d_region,cluster_id,cluster_name,container_id,container_name,cve_id,detection_name,first_seen,image_detection_" - "count,image_digest,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_vulnerabil " - "ity_count,insecure_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,label " - "s,last_seen,namespace,node_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_write_acces " + "count,image_digest,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_vulnerabil" + "ity_count,insecure_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,label" + "s,last_seen,namespace,node_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_write_acces" "s,run_as_root_group,run_as_root_user,running_status", "name": "filter", "in": "query" @@ -299,11 +299,11 @@ { "type": "string", "description": "Retrieve count of Kubernetes containers that match a query in Falcon Query Language " - "(FQL). Supported filters: agent_id,agent_type,allow_privilege_escalation,cid,cloud_account_id,cloud_name,clou " + "(FQL). Supported filters: agent_id,agent_type,allow_privilege_escalation,cid,cloud_account_id,cloud_name,clou" "d_region,cluster_id,cluster_name,container_id,container_name,cve_id,detection_name,first_seen,image_detection_" - "count,image_digest,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_vulnerabil " - "ity_count,insecure_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,label " - "s,last_seen,namespace,node_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_write_acces " + "count,image_digest,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_vulnerabil" + "ity_count,insecure_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,label" + "s,last_seen,namespace,node_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_write_acces" "s,run_as_root_group,run_as_root_user,running_status", "name": "filter", "in": "query" @@ -321,10 +321,10 @@ "type": "string", "description": "Get vulnerabilities count by severity for container using a query in Falcon Query " "Language (FQL). Supported filters: agent_id,agent_type,allow_privilege_escalation,cid,cloud_account_id,cloud_" - "name,cloud_region,cluster_id,cluster_name,container_id,container_name,cve_id,detection_name,first_seen,image_d " - "etection_count,image_digest,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_v " - "ulnerability_count,insecure_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,i " - "pv6,labels,last_seen,namespace,node_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_wr " + "name,cloud_region,cluster_id,cluster_name,container_id,container_name,cve_id,detection_name,first_seen,image_d" + "etection_count,image_digest,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_v" + "ulnerability_count,insecure_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,i" + "pv6,labels,last_seen,namespace,node_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_wr" "ite_access,run_as_root_group,run_as_root_user,running_status", "name": "filter", "in": "query" @@ -349,7 +349,7 @@ { "type": "string", "description": "Retrieve count of Kubernetes deployments that match a query in Falcon Query Language " - "(FQL). Supported filters: annotations_list,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,cluster_na " + "(FQL). Supported filters: annotations_list,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,cluster_na" "me,deployment_id,deployment_name,first_seen,last_seen,namespace,pod_count", "name": "filter", "in": "query" @@ -497,10 +497,10 @@ "type": "string", "description": "Search Kubernetes containers using a query in Falcon Query Language (FQL). Supported " "filters: agent_id,agent_type,allow_privilege_escalation,cid,cloud_account_id,cloud_name,cloud_region,cluster_" - "id,cluster_name,container_id,container_name,cve_id,detection_name,first_seen,image_detection_count,image_diges " - "t,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_vulnerability_count,insecur " - "e_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,labels,last_seen,names " - "pace,node_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_write_access,run_as_root_gro " + "id,cluster_name,container_id,container_name,cve_id,detection_name,first_seen,image_detection_count,image_diges" + "t,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_vulnerability_count,insecur" + "e_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,labels,last_seen,names" + "pace,node_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_write_access,run_as_root_gro" "up,run_as_root_user,running_status", "name": "filter", "in": "query" @@ -517,11 +517,11 @@ { "type": "string", "description": "Retrieve count of Kubernetes containers that match a query in Falcon Query Language " - "(FQL). Supported filters: agent_id,agent_type,allow_privilege_escalation,cid,cloud_account_id,cloud_name,clou " + "(FQL). Supported filters: agent_id,agent_type,allow_privilege_escalation,cid,cloud_account_id,cloud_name,clou" "d_region,cluster_id,cluster_name,container_id,container_name,cve_id,detection_name,first_seen,image_detection_" - "count,image_digest,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_vulnerabil " - "ity_count,insecure_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,label " - "s,last_seen,namespace,node_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_write_acces " + "count,image_digest,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_vulnerabil" + "ity_count,insecure_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,label" + "s,last_seen,namespace,node_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_write_acces" "s,run_as_root_group,run_as_root_user,running_status", "name": "filter", "in": "query" @@ -571,7 +571,8 @@ "type": "string", "description": "Search Kubernetes nodes using a query in Falcon Query Language (FQL). Supported " "filters: aid,annotations_list,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,cluster_name,container_" - "count,container_runtime_version,first_seen,image_digest,ipv4,last_seen,node_name,pod_count", + "count,container_runtime_version,first_seen,image_digest,ipv4,last_seen,linux_sensor_coverage,node_name,pod_cou" + "nt", "name": "filter", "in": "query" } @@ -588,7 +589,8 @@ "type": "string", "description": "Search Kubernetes nodes using a query in Falcon Query Language (FQL). Supported " "filters: aid,annotations_list,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,cluster_name,container_" - "count,container_runtime_version,first_seen,image_digest,ipv4,last_seen,node_name,pod_count", + "count,container_runtime_version,first_seen,image_digest,ipv4,last_seen,linux_sensor_coverage,node_name,pod_cou" + "nt", "name": "filter", "in": "query" } @@ -605,7 +607,8 @@ "type": "string", "description": "Search Kubernetes nodes using a query in Falcon Query Language (FQL). Supported " "filters: aid,annotations_list,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,cluster_name,container_" - "count,container_runtime_version,first_seen,image_digest,ipv4,last_seen,node_name,pod_count", + "count,container_runtime_version,first_seen,image_digest,ipv4,last_seen,linux_sensor_coverage,node_name,pod_cou" + "nt", "name": "filter", "in": "query" } @@ -621,8 +624,9 @@ { "type": "string", "description": "Retrieve count of Kubernetes nodes that match a query in Falcon Query Language (FQL). " - "Supported filters: aid,annotations_list,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,cluster_name, " - "container_count,container_runtime_version,first_seen,image_digest,ipv4,last_seen,node_name,pod_count", + "Supported filters: aid,annotations_list,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,cluster_name," + "container_count,container_runtime_version,first_seen,image_digest,ipv4,last_seen,linux_sensor_coverage,node_na" + "me,pod_count", "name": "filter", "in": "query" } @@ -646,10 +650,10 @@ { "type": "string", "description": "Retrieve count of Kubernetes pods that match a query in Falcon Query Language (FQL). " - "Supported filters: agent_id,agent_type,allow_privilege_escalation,annotations_list,cid,cloud_account_id,cloud " - "_name,cloud_region,cluster_id,cluster_name,container_count,ipv4,ipv6,labels,last_seen,namespace,node_name,node " - "_uid,owner_id,owner_type,pod_id,pod_name,port,privileged,root_write_access, run_as_root_group, " - "run_as_root_user", + "Supported filters: agent_id,agent_type,allow_privilege_escalation,annotations_list,cid,cloud_account_id,cloud" + "_name,cloud_region,cluster_id,cluster_name,container_count,ipv4,ipv6,labels,last_seen,namespace,node_name,node" + "_uid,owner_id,owner_type,pod_external_id,pod_id,pod_name,port,privileged,root_write_access,run_as_root_group,r" + "un_as_root_user", "name": "filter", "in": "query" } @@ -665,7 +669,7 @@ { "type": "string", "description": "Search Kubernetes clusters using a query in Falcon Query Language (FQL). Supported " - "filters: access,agent_status,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,cluster_name,cluster_sta " + "filters: access,agent_status,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,cluster_name,cluster_sta" "tus,container_count,kubernetes_version,last_seen, management_status, node_count, pod_count, tags", "name": "filter", "in": "query" @@ -700,7 +704,7 @@ { "type": "string", "description": "Retrieve list of images on running containers using a query in Falcon Query Language " - "(FQL). Supported filters: cid,hosts,image_digest,image_has_been_assessed,image_id,image_name,image_registry,i " + "(FQL). Supported filters: cid,hosts,image_digest,image_has_been_assessed,image_id,image_name,image_registry,i" "mage_repository,image_tag,last_seen,running_status", "name": "filter", "in": "query" @@ -736,10 +740,10 @@ "type": "string", "description": "Search Kubernetes containers using a query in Falcon Query Language (FQL). Supported " "filters: agent_id,agent_type,allow_privilege_escalation,cid,cloud_account_id,cloud_name,cloud_region,cluster_" - "id,cluster_name,container_id,container_name,cve_id,detection_name,first_seen,image_detection_count,image_diges " - "t,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_vulnerability_count,insecur " - "e_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,labels,last_seen,names " - "pace,node_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_write_access,run_as_root_gro " + "id,cluster_name,container_id,container_name,cve_id,detection_name,first_seen,image_detection_count,image_diges" + "t,image_has_been_assessed,image_id,image_registry,image_repository,image_tag,image_vulnerability_count,insecur" + "e_mount_source,insecure_mount_type,insecure_propagation_mode,interactive_mode,ipv4,ipv6,labels,last_seen,names" + "pace,node_name,node_uid,package_name_version,pod_id,pod_name,port,privileged,root_write_access,run_as_root_gro" "up,run_as_root_user,running_status", "name": "filter", "in": "query" @@ -774,7 +778,7 @@ { "type": "string", "description": "Search Kubernetes deployments using a query in Falcon Query Language (FQL). Supported " - "filters: annotations_list,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,cluster_name,deployment_id, " + "filters: annotations_list,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,cluster_name,deployment_id," "deployment_name,first_seen,last_seen,namespace,pod_count", "name": "filter", "in": "query" @@ -809,7 +813,7 @@ { "type": "string", "description": "Search Kubernetes IOMs using a query in Falcon Query Language (FQL). Supported " - "filters: cid,cis_id,cluster_id,cluster_name,containers_impacted_count,containers_impacted_ids,detection_type, " + "filters: cid,cis_id,cluster_id,cluster_name,containers_impacted_count,containers_impacted_ids,detection_type," "name,namespace,resource_id,resource_name,resource_type,severity", "name": "filter", "in": "query" @@ -845,7 +849,8 @@ "type": "string", "description": "Search Kubernetes nodes using a query in Falcon Query Language (FQL). Supported " "filters: aid,annotations_list,cid,cloud_account_id,cloud_name,cloud_region,cluster_id,cluster_name,container_" - "count,container_runtime_version,first_seen,image_digest,ipv4,last_seen,node_name,pod_count", + "count,container_runtime_version,first_seen,image_digest,ipv4,last_seen,linux_sensor_coverage,node_name,pod_cou" + "nt", "name": "filter", "in": "query" }, @@ -879,9 +884,10 @@ { "type": "string", "description": "Search Kubernetes pods using a query in Falcon Query Language (FQL). Supported " - "filters: agent_id,agent_type,allow_privilege_escalation,annotations_list,cid,cloud_account_id,cloud_name,clou " - "d_region,cluster_id,cluster_name,container_count,ipv4,ipv6,labels,last_seen,namespace,node_name,node_uid,owner " - "_id,owner_type,pod_id,pod_name,port,privileged,root_write_access, run_as_root_group, run_as_root_user", + "filters: agent_id,agent_type,allow_privilege_escalation,annotations_list,cid,cloud_account_id,cloud_name,clou" + "d_region,cluster_id,cluster_name,container_count,ipv4,ipv6,labels,last_seen,namespace,node_name,node_uid,owner" + "_id,owner_type,pod_external_id,pod_id,pod_name,port,privileged,root_write_access,run_as_root_group,run_as_root" + "_user", "name": "filter", "in": "query" }, @@ -935,7 +941,7 @@ { "type": "string", "description": "Search Kubernetes IOMs using a query in Falcon Query Language (FQL). Supported " - "filters: cid,cis_id,cluster_id,cluster_name,containers_impacted_count,containers_impacted_ids,detection_type, " + "filters: cid,cis_id,cluster_id,cluster_name,containers_impacted_count,containers_impacted_ids,detection_type," "name,namespace,resource_id,resource_name,resource_type,severity", "name": "filter", "in": "query" diff --git a/src/falconpy/_endpoint/_message_center.py b/src/falconpy/_endpoint/_message_center.py index 8c23a62b0..736cea7b3 100644 --- a/src/falconpy/_endpoint/_message_center.py +++ b/src/falconpy/_endpoint/_message_center.py @@ -196,8 +196,8 @@ }, { "enum": [ - "activity.created_time.asc", - "activity.created_time.desc" + "activity.type.asc", + "activity.type.desc" ], "type": "string", "description": "The property to sort on, followed by a dot (.), followed by the sort direction, either " diff --git a/src/falconpy/_endpoint/_workflows.py b/src/falconpy/_endpoint/_workflows.py index 33f7b005b..19a493460 100644 --- a/src/falconpy/_endpoint/_workflows.py +++ b/src/falconpy/_endpoint/_workflows.py @@ -37,6 +37,168 @@ """ _workflows_endpoints = [ + [ + "WorkflowDefinitionsCombined", + "GET", + "/workflows/combined/definitions/v1", + "Search workflow definitions based on the provided filter", + "workflows", + [ + { + "type": "string", + "description": "FQL query specifying filter parameters.", + "name": "filter", + "in": "query", + "allowEmptyValue": True + }, + { + "type": "string", + "description": "Starting pagination offset of records to return.", + "name": "offset", + "in": "query" + }, + { + "type": "integer", + "description": "Maximum number of records to return.", + "name": "limit", + "in": "query" + }, + { + "pattern": "^\\w+(\\.asc|\\.desc)?(,\\w+(\\.asc|\\.desc)?)*$", + "type": "string", + "description": "Sort items by providing a comma separated list of property and direction (eg " + "name.desc,time.asc). If direction is omitted, defaults to descending.", + "name": "sort", + "in": "query" + } + ] + ], + [ + "WorkflowExecutionsCombined", + "GET", + "/workflows/combined/executions/v1", + "Search workflow executions based on the provided filter", + "workflows", + [ + { + "type": "string", + "description": "FQL query specifying filter parameters.", + "name": "filter", + "in": "query", + "allowEmptyValue": True + }, + { + "type": "string", + "description": "Starting pagination offset of records to return.", + "name": "offset", + "in": "query" + }, + { + "type": "integer", + "description": "Maximum number of records to return.", + "name": "limit", + "in": "query" + }, + { + "pattern": "^\\w+(\\.asc|\\.desc)?(,\\w+(\\.asc|\\.desc)?)*$", + "type": "string", + "description": "Sort items by providing a comma separated list of property and direction (eg " + "name.desc,time.asc). If direction is omitted, defaults to descending.", + "name": "sort", + "in": "query" + } + ] + ], + [ + "WorkflowDefinitionsExport", + "GET", + "/workflows/entities/definitions/export/v1", + "Exports a workflow definition for the given definition ID", + "workflows", + [ + { + "maxLength": 40, + "minLength": 32, + "type": "string", + "description": "ID of workflow definitions to return details for", + "name": "id", + "in": "query", + "required": True + } + ] + ], + [ + "WorkflowDefinitionsImport", + "POST", + "/workflows/entities/definitions/import/v1", + "Imports a workflow definition based on the provided model", + "workflows", + [ + { + "type": "file", + "x-mimetype": "application/yaml", + "description": "A workflow definition in YAML format to import", + "name": "data_file", + "in": "formData", + "required": True + }, + { + "type": "string", + "description": "Workflow name to override", + "name": "name", + "in": "query" + }, + { + "type": "boolean", + "default": False, + "description": "When enabled, prevents saving workflow after validating", + "name": "validate_only", + "in": "query" + } + ] + ], + [ + "WorkflowDefinitionsUpdate", + "PUT", + "/workflows/entities/definitions/v1", + "Updates a workflow definition based on the provided model", + "workflows", + [ + { + "type": "boolean", + "default": False, + "description": "When enabled, prevents saving workflow after validating", + "name": "validate_only", + "in": "query" + }, + { + "name": "body", + "in": "body", + "required": True + } + ] + ], + [ + "WorkflowDefinitionsCreate", + "POST", + "/workflows/entities/definitions/v1", + "Creates a workflow definition based on the provided model", + "workflows", + [ + { + "type": "boolean", + "default": False, + "description": "When enabled, prevents saving workflow after validating", + "name": "validate_only", + "in": "query" + }, + { + "name": "body", + "in": "body", + "required": True + } + ] + ], [ "WorkflowExecute", "POST", @@ -44,6 +206,17 @@ "Executes an on-demand Workflow, the body is JSON used to trigger the execution, the response the execution ID(s)", "workflows", [ + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "CID(s) to execute on. This can be a child if this is a flight control enabled " + "definition. If unset the definition CID is used.", + "name": "execution_cid", + "in": "query" + }, { "type": "array", "items": { @@ -132,6 +305,50 @@ } ] ], + [ + "WorkflowGetHumanInputV1", + "GET", + "/workflows/entities/human-inputs/v1", + "Gets one or more specific human inputs by their IDs.", + "workflows", + [ + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "csv", + "description": "IDs of human inputs to read", + "name": "ids", + "in": "query", + "required": True + } + ] + ], + [ + "WorkflowUpdateHumanInputV1", + "PATCH", + "/workflows/entities/human-inputs/v1", + "Provides an input in response to a human input action. Depending on action configuration, one or more of " + "Approve, Decline, and/or Escalate are permitted.", + "workflows", + [ + { + "maxLength": 32, + "minLength": 32, + "type": "string", + "description": "ID of human input to provide an input to", + "name": "id", + "in": "query", + "required": True + }, + { + "name": "body", + "in": "body", + "required": True + } + ] + ], [ "WorkflowSystemDefinitionsDeProvision", "POST", diff --git a/src/falconpy/_endpoint/deprecated/_custom_ioa.py b/src/falconpy/_endpoint/deprecated/_custom_ioa.py index 346c92e75..0ffc268f7 100644 --- a/src/falconpy/_endpoint/deprecated/_custom_ioa.py +++ b/src/falconpy/_endpoint/deprecated/_custom_ioa.py @@ -327,7 +327,7 @@ "name" ], "type": "string", - "description": "Possible order by fields: {name, created_by, created_on, modified_by, modified_on, enabled}", + "description": "Possible order by fields: {enabled, name, created_by, created_on, modified_by, modified_on}", "name": "sort", "in": "query" }, @@ -377,7 +377,7 @@ "name" ], "type": "string", - "description": "Possible order by fields: {name, created_by, created_on, modified_by, modified_on, enabled}", + "description": "Possible order by fields: {enabled, name, created_by, created_on, modified_by, modified_on}", "name": "sort", "in": "query" }, @@ -452,10 +452,10 @@ "rules.ruletype_name" ], "type": "string", - "description": "Possible order by fields: {rules.created_on, rules.current_version.action_label, " - "rules.current_version.modified_by, rules.current_version.modified_on, rules.ruletype_name, rules.enabled, " - "rules.current_version.description, rules.current_version.pattern_severity, rules.created_by, " - "rules.current_version.name}", + "description": "Possible order by fields: {rules.current_version.description, " + "rules.current_version.action_label, rules.current_version.modified_on, rules.created_on, " + "rules.current_version.name, rules.created_by, rules.current_version.pattern_severity, " + "rules.current_version.modified_by, rules.ruletype_name, rules.enabled}", "name": "sort", "in": "query" }, diff --git a/src/falconpy/_payload/__init__.py b/src/falconpy/_payload/__init__.py index 531f0e3ff..04e31a64f 100644 --- a/src/falconpy/_payload/__init__.py +++ b/src/falconpy/_payload/__init__.py @@ -37,7 +37,13 @@ recon_export_job_payload ) from ._malquery import malquery_exact_search_payload, malquery_hunt_payload, malquery_fuzzy_payload -from ._container import image_payload, registry_payload +from ._container import ( + image_payload, + registry_payload, + image_policy_payload, + image_exclusions_payload, + image_group_payload + ) from ._detects import update_detects_payload from ._incidents import incident_action_parameters from ._ioa import ioa_exclusion_payload, ioa_custom_payload @@ -78,7 +84,12 @@ from ._sample_uploads import extraction_payload from ._ods import scheduled_scan_payload from ._cloud_snapshots import snapshot_inventory_payload, snapshot_registration_payload -from ._workflows import workflow_deprovision_payload, workflow_template_payload +from ._workflows import ( + workflow_deprovision_payload, + workflow_template_payload, + workflow_definition_payload, + workflow_human_input + ) from ._foundry import foundry_dynamic_search_payload, foundry_execute_search_payload __all__ = [ @@ -102,5 +113,7 @@ "gcp_registration_payload", "filevantage_rule_group_payload", "filevantage_rule_payload", "filevantage_policy_payload", "filevantage_scheduled_exclusion_payload", "snapshot_inventory_payload", "snapshot_registration_payload", "workflow_deprovision_payload", - "workflow_template_payload", "foundry_execute_search_payload", "foundry_dynamic_search_payload" + "workflow_template_payload", "foundry_execute_search_payload", "foundry_dynamic_search_payload", + "image_policy_payload", "image_exclusions_payload", "image_group_payload", + "workflow_definition_payload", "workflow_human_input" ] diff --git a/src/falconpy/_payload/_container.py b/src/falconpy/_payload/_container.py index 210dfd3f1..af7501744 100644 --- a/src/falconpy/_payload/_container.py +++ b/src/falconpy/_payload/_container.py @@ -150,3 +150,104 @@ def registry_payload(passed_keywords: dict) -> dict: returned_payload["credential"]["details"][key] = passed_keywords.get(key) return returned_payload + + +def image_policy_payload(passed_keywords: dict) -> dict: + """Craft a properly formatted image assessment policy payload. + + { + "description": "string", + "is_enabled": boolean, + "name": "string", + "policy_data": { + "rules": [ + { + "action": "string", + "policy_rules_data": { + "conditions": [ + {} + ] + } + } + ] + } + } + """ + returned_payload = {} + keys = ["description", "name", "is_enabled"] + for key in keys: + if passed_keywords.get(key, None) is not None: + returned_payload[key] = passed_keywords.get(key, None) + + if passed_keywords.get("policy_data", None) is not None: + returned_payload["policy_data"] = passed_keywords.get("policy_data", None) + if passed_keywords.get("rules", None) is not None: + if not returned_payload["policy_data"]: + rules = passed_keywords.get("rules", None) + if isinstance(rules, dict): + rules = [rules] + returned_payload["policy_data"] = { + "rules": rules + } + + return returned_payload + + +def image_exclusions_payload(passed_keywords: dict) -> dict: + """Craft a properly formatted image policy exclusion payload. + + { + "conditions": [ + { + "description": "string", + "prop": "string", + "ttl": 0, + "value": [ + "string" + ] + } + ] + } + """ + returned_payload = {} + if passed_keywords.get("conditions", None) is not None: + returned_payload["conditions"] = passed_keywords.get("conditions", None) + keys = ["description", "prop", "ttl", "value"] + if not returned_payload.get("conditions", None) and passed_keywords: + condition = {} + for key in keys: + if passed_keywords.get(key, None) is not None: + condition[key] = passed_keywords.get(key, None) + returned_payload["conditions"] = [condition] + + return returned_payload + + +def image_group_payload(passed_keywords: dict) -> dict: + """Craft a properly formatted image policy group payload. + + { + "description": "string", + "name": "string", + "policy_group_data": { + "conditions": [ + {} + ] + }, + "policy_id": "string" + } + """ + returned_payload = {} + keys = ["description", "name", "policy_group_data", "policy_id"] + for key in keys: + if passed_keywords.get(key, None) is not None: + returned_payload[key] = passed_keywords.get(key, None) + if not returned_payload.get("policy_group_data", None) and passed_keywords.get("conditions"): + conditions = passed_keywords.get("conditions", None) + if isinstance(conditions, dict): + conditions = [conditions] + returned_payload["policy_group_data"] = { + "conditions": conditions + } + + return returned_payload diff --git a/src/falconpy/_payload/_cspm_registration.py b/src/falconpy/_payload/_cspm_registration.py index 07b132f1c..c834f2908 100644 --- a/src/falconpy/_payload/_cspm_registration.py +++ b/src/falconpy/_payload/_cspm_registration.py @@ -50,6 +50,8 @@ def cspm_registration_payload(passed_keywords: dict) -> Dict[str, List[Dict[str, "client_id": "string", "cloudtrail_region": "string", "default_subscription": true, + "default_subscription_id": "string", + "environment": "string", "iam_role_arn": "string", "is_master": true, "organization_id": "string", @@ -69,7 +71,7 @@ def cspm_registration_payload(passed_keywords: dict) -> Dict[str, List[Dict[str, item = {} keys = ["account_id", "account_type", "cloudtrail_region", "iam_role_arn", "organization_id", "tenant_id", "subscription_id", "remediation_region", - "remediation_tou_accepted", "client_id" + "remediation_tou_accepted", "client_id", "environment", "default_subscription_id" ] bool_keys = ["behavior_assessment_enabled", "is_master", "sensor_management_enabled", "use_existing_cloudtrail", "default_subscription" diff --git a/src/falconpy/_payload/_d4c_registration.py b/src/falconpy/_payload/_d4c_registration.py index 301bd32d5..b0085b87b 100644 --- a/src/falconpy/_payload/_d4c_registration.py +++ b/src/falconpy/_payload/_d4c_registration.py @@ -112,15 +112,23 @@ def gcp_registration_payload(passed_keywords: dict) -> dict: { "resources": [ { + "client_email": "string", + "client_id": "string", "parent_id": "string", - "parent_type": "string" + "parent_type": "string", + "private_key": "string", + "private_key_id": "string", + "project_id": "string", + "service_account_id": 0 } ] } """ returned_payload: Dict[str, List[Dict[str, str]]] = {} returned_payload["resources"] = [] - keys = ["parent_id", "parent_type"] + keys = ["client_email", "client_id", "parent_id", "parent_type", + "private_key", "private_key_id", "project_id", "service_account_id" + ] item = {} for key in keys: if passed_keywords.get(key, None): diff --git a/src/falconpy/_payload/_firewall.py b/src/falconpy/_payload/_firewall.py index dc6a7e283..db69d8683 100644 --- a/src/falconpy/_payload/_firewall.py +++ b/src/falconpy/_payload/_firewall.py @@ -259,7 +259,7 @@ def firewall_rule_group_update_payload(passed_keywords: dict) -> dict: returned_payload["diff_type"] = passed_keywords.get("diff_type", "application/json-patch+json") # Grab the rule_ids keyword and check for list formatting id_list = passed_keywords.get("rule_ids", None) - if id_list: + if id_list is not None: # Allow empty lists so all rules can be removed. Issue #1107. if isinstance(id_list, str): id_list = id_list.split(",") returned_payload["rule_ids"] = id_list diff --git a/src/falconpy/_payload/_workflows.py b/src/falconpy/_payload/_workflows.py index 203f2f56f..4d3628921 100644 --- a/src/falconpy/_payload/_workflows.py +++ b/src/falconpy/_payload/_workflows.py @@ -131,3 +131,49 @@ def workflow_template_payload(passed_keywords: dict): returned_payload["parameters"] = param_branch return returned_payload + + +def workflow_definition_payload(passed_keywords: dict) -> dict: + """Craft a properly formatted workflow definition payload. + + { + "Definition": {}, + "change_log": "string", + "enabled": true, + "flight_control": { + "all_cids": true, + "excluded_cids": [ + "string" + ], + "include_parent_cid": true, + "selected_cids": [ + "string" + ] + }, + "id": "string" + } + """ + returned_payload = {} + keys = ["definition", "change_log", "enabled", "flight_control", "id"] + for key in keys: + if passed_keywords.get(key, None) is not None: + returned_payload[key] = passed_keywords.get(key, None) + + return returned_payload + + +def workflow_human_input(passed_keywords: dict) -> dict: + """Craft a properly formatted human input payload. + + { + "input": "string", + "note": "string" + } + """ + returned_payload = {} + keys = ["input", "note"] + for key in keys: + if passed_keywords.get(key, None): + returned_payload[key] = passed_keywords.get(key, None) + + return returned_payload diff --git a/src/falconpy/_version.py b/src/falconpy/_version.py index ad4b4f5ea..cb02b7086 100644 --- a/src/falconpy/_version.py +++ b/src/falconpy/_version.py @@ -35,7 +35,7 @@ For more information, please refer to """ -_VERSION = '1.4.0' +_VERSION = '1.4.1' _MAINTAINER = 'Joshua Hiller' _AUTHOR = 'CrowdStrike' _AUTHOR_EMAIL = 'falconpy@crowdstrike.com' diff --git a/src/falconpy/container_alerts.py b/src/falconpy/container_alerts.py index ff63ed655..e75bc575b 100644 --- a/src/falconpy/container_alerts.py +++ b/src/falconpy/container_alerts.py @@ -54,13 +54,40 @@ class ContainerAlerts(ServiceClass): - a valid token provided by the authentication service class (oauth2.py) """ + @force_default(defaults=["parameters"], default_types=["dict"]) + def read_counts_by_severity(self: object, *args, parameters: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Get container alert counts by severity. + + Keyword arguments: + filter -- Search Container Alerts using a query in Falcon Query Language (FQL). String. + Supported filters: cid, container_id, last_seen + parameters -- Full parameters payload dictionary. Not required if using other keywords. + + Arguments: When not specified, the first argument to this method is assumed to be 'filter'. + All others are ignored. + + Returns: dict object containing API response. + + HTTP Method: GET + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/container-alerts/ReadContainerAlertsCountBySeverity + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="ReadContainerAlertsCountBySeverity", + keywords=kwargs, + params=handle_single_argument(args, parameters, "filter") + ) + @force_default(defaults=["parameters"], default_types=["dict"]) def read_counts(self: object, *args, parameters: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: """Search Container Alerts by the provided search criteria. Keyword arguments: filter -- Search Container Alerts using a query in Falcon Query Language (FQL). String. - Supported filters: cid, last_seen + Supported filters: cid, container_id, last_seen parameters -- Full parameters payload dictionary. Not required if using other keywords. Arguments: When not specified, the first argument to this method is assumed to be 'filter'. @@ -113,5 +140,6 @@ def search_and_read(self: object, parameters: dict = None, **kwargs) -> Dict[str # This method name aligns to the operation ID in the API but # does not conform to snake_case / PEP8 and is defined here for # backwards compatibility / ease of use purposes + ReadContainerAlertsCountBySeverity = read_counts_by_severity ReadContainerAlertsCount = read_counts SearchAndReadContainerAlerts = search_and_read diff --git a/src/falconpy/cspm_registration.py b/src/falconpy/cspm_registration.py index 06ea1a1b0..5b5c4e7aa 100644 --- a/src/falconpy/cspm_registration.py +++ b/src/falconpy/cspm_registration.py @@ -38,7 +38,12 @@ # pylint: disable=R0904, C0302 # Matching API operation counts and allowing the long file for now from typing import Dict, Union from ._util import force_default, process_service_request, handle_single_argument -from ._payload import cspm_registration_payload, cspm_policy_payload, cspm_scan_payload +from ._payload import ( + cspm_registration_payload, + cspm_policy_payload, + cspm_scan_payload, + gcp_registration_payload + ) from ._service_class import ServiceClass from ._endpoint._cspm_registration import _cspm_registration_endpoints as Endpoints @@ -62,6 +67,7 @@ def get_aws_account(self: object, parameters: dict = None, **kwargs) -> Dict[str Keyword arguments: scan_type -- Type of scan, `dry` or `full`, to perform on selected accounts + cspm_lite -- Only return CSPM lite accounts. Boolean. ids -- AWS account IDs. String or list of strings. iam_role_arns -- AWS IAM role ARNs. String or list of strings. organization_ids -- AWS organization IDs. String or list of strings. @@ -287,6 +293,7 @@ def get_azure_account(self: object, parameters: dict = None, **kwargs) -> Dict[s Keyword arguments: scan_type -- Type of scan, `dry` or `full`, to perform on selected accounts + cspm_lite -- Only return CSPM lite accounts. Boolean. ids -- Azure account IDs. String or list of strings. limit -- The maximum number of records to return in this response. [Integer, 1-1000] Use with the offset parameter to manage pagination of results. Defaults to 100. @@ -363,6 +370,46 @@ def create_azure_account(self: object, body: dict = None, **kwargs) -> Dict[str, body=body ) + @force_default(defaults=["body"], default_types=["dict"]) + def update_azure_account(self: object, body: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Update Azure account. + + Keyword arguments: + body -- full body payload, not required when using other keywords. + { + "resources": [ + { + "environment": "string", + "subscription_id": "string" + } + ] + } + account_type -- Azure account type. String. + client_id -- Azure Client ID. String. + default_subscription -- Indicate if this is the default subscription. Boolean. + subscription_id -- Azure Subscription ID. String. + tenant_id -- Azure Tenant ID. String. + years_valid -- Number of years this account is valid. Integer. + + This method only supports keywords for providing arguments. + + Returns: dict object containing API response. + + HTTP Method: POST + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/UpdateCSPMAzureAccount + """ + if not body: + body = cspm_registration_payload(passed_keywords=kwargs) + + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="UpdateCSPMAzureAccount", + body=body + ) + @force_default(defaults=["parameters"], default_types=["dict"]) def delete_azure_account(self: object, *args, parameters: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: """Delete an existing Azure Subscription by specifying their IDs. @@ -484,7 +531,7 @@ def azure_download_certificate(self: object, Keyword arguments: tenant_id -- Azure Tenant ID to generate script for. Defaults to the most recently registered tenant. - parameters -- full parameters payload, not required if tenant-id keyword is used. + parameters -- full parameters payload, not required if tenant_id keyword is used. refresh -- Force a refresh of the certificate. Boolean. Defaults to False. years_valid -- Years the certificate should be valid (only used when refresh=true). @@ -506,6 +553,78 @@ def azure_download_certificate(self: object, params=handle_single_argument(args, parameters, "tenant_id") ) + @force_default(defaults=["parameters"], default_types=["dict"]) + def get_azure_management_group(self: object, + *args, + parameters: dict = None, + **kwargs + ) -> Dict[str, Union[int, dict]]: + """ + Return information about Azure management group registration. + + Keyword arguments: + limit -- The maximum number of records to return. Defaults to 100. Integer. + offset -- The offset to start retrieving records from. Integer. + parameters -- full parameters payload, not required if tenant_id keyword is used. + tenant_ids -- Azure Tenant ID to filter by. String or list of strings. + + Arguments: When not specified, the first argument to this method is assumed to be + 'tenant_ids'. All others are ignored. + + Returns: dict object containing API response. + + HTTP Method: GET + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/GetCSPMAzureManagementGroup + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="GetCSPMAzureManagementGroup", + keywords=kwargs, + params=handle_single_argument(args, parameters, "tenant_ids") + ) + + @force_default(defaults=["body"], default_types=["dict"]) + def create_azure_management_group(self: object, body: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Register new Azure account. + + Creates a new account in our system for a customer and generates a script + to run in their cloud environment to grant CrowdStrike Horizon access. + + Keyword arguments: + body -- full body payload, not required when using other keywords. + { + "resources": [ + { + "default_subscription_id": "string" + "tenant_id": "string", + } + ] + } + default_subscription_id -- ID of the default azure subscription. String. + tenant_id -- Azure Tenant ID. String. + + This method only supports keywords for providing arguments. + + Returns: dict object containing API response. + + HTTP Method: POST + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/CreateCSPMAzureManagementGroup + """ + if not body: + body = cspm_registration_payload(passed_keywords=kwargs) + + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="CreateCSPMAzureManagementGroup", + body=body + ) + @force_default(defaults=["parameters"], default_types=["dict"]) def get_azure_user_scripts_attachment(self: object, *args, @@ -520,14 +639,15 @@ def get_azure_user_scripts_attachment(self: object, Keyword arguments: account_type -- Account type. ('commercial' or 'gov') String. + azure_management_group -- Use Azure Management Group. Boolean. tenant_id -- Azure Tenant ID to generate script for. Defaults to the most recently registered tenant. - parameters -- full parameters payload, not required if tenant-id keyword is used. + parameters -- full parameters payload, not required if tenant_id keyword is used. subscription_ids -- Subscription IDs to generate script for. Defaults to all. String or list of strings. template -- Template to be rendered. String. Arguments: When not specified, the first argument to this method is assumed to be - 'tenant-id'. All others are ignored. + 'tenant_id'. All others are ignored. Returns: dict object containing API response. @@ -544,7 +664,258 @@ def get_azure_user_scripts_attachment(self: object, endpoints=Endpoints, operation_id="GetCSPMAzureUserScriptsAttachment", keywords=kwargs, - params=handle_single_argument(args, parameters, "tenant-id") + params=handle_single_argument(args, parameters, "tenant_id") + ) + + @force_default(defaults=["parameters"], default_types=["dict"]) + def get_gcp_account(self: object, parameters: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Return information about the current status of an GCP account. + + Keyword arguments: + ids -- Hierarchical Resource IDs of accounts. String or list of strings. + limit -- The maximum records to return. Defaults to 100. Integer. + offset -- The offset to start retrieving records from. Integer. + parameters -- full parameters payload, not required if ids is provided as a keyword. + parent_type -- GCP Hierarchy Parent Type, organization/folder/project. String. + scan_type -- Type of scan, `dry` or `full`, to perform on selected accounts. + sort -- Order fields in ascending or descending order. Ex: parent_type|asc. + status -- Account status to filter results by, 'operational' or 'provisioned'. String. + + This method does not accept arguments or keywords. + + Returns: dict object containing API response. + + HTTP Method: GET + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/GetCSPMCGPAccount + """ + if kwargs.get("scan_type", None): + kwargs["scan-type"] = kwargs.get("scan_type", None) + + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="GetCSPMCGPAccount", + keywords=kwargs, + params=parameters + ) + + @force_default(defaults=["body"], default_types=["dict"]) + def create_gcp_account(self: object, body: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Register new GCP account. + + Creates a new account in our system for a customer and generates a new service + account for them to add access to in their GCP environment to grant us access. + + Keyword arguments: + body -- full body payload, not required if using other keywords. + { + "resources": [ + { + "parent_id": "string", + "parent_type": "string" + } + ] + } + parent_id -- GCP parent ID. String. + parent_type -- GCP parent type. String. + + This method only supports keywords for providing arguments. + + Returns: dict object containing API response. + + HTTP Method: POST + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/CreateCSPMGCPAccount + """ + if not body: + body = gcp_registration_payload(passed_keywords=kwargs) + + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="CreateCSPMGCPAccount", + body=body + ) + + @force_default(defaults=["parameters"], default_types=["dict"]) + def delete_gcp_account(self: object, *args, parameters: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Delete a GCP account from the system. + + Keyword arguments: + ids -- Hierarchical Resource IDs of accounts. String or list of strings. + parameters -- full parameters payload, not required if ids is provided as a keyword. + + Arguments: When not specified, the first argument to this method is assumed to be 'ids'. + All others are ignored. + + Returns: dict object containing API response. + + HTTP Method: DELETE + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/DeleteCSPMGCPAccount + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="DeleteCSPMGCPAccount", + keywords=kwargs, + params=handle_single_argument(args, parameters, "ids") + ) + + @force_default(defaults=["body"], default_types=["dict"]) + def update_gcp_account(self: object, body: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Update a GCP account. + + Keyword arguments: + body -- full body payload, not required if using other keywords. + { + "resources": [ + { + "environment": "string", + "parent_id": "string" + } + ] + } + environment -- GCP environment. String. + parent_id -- GCP parent ID. String. + + This method only supports keywords for providing arguments. + + Returns: dict object containing API response. + + HTTP Method: PATCH + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/UpdateCSPMGCPAccount + """ + if not body: + body = gcp_registration_payload(passed_keywords=kwargs) + + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="UpdateCSPMGCPAccount", + body=body + ) + + @force_default(defaults=["body"], default_types=["dict"]) + def connect_gcp_account(self: object, body: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Register new GCP account. + + Creates a new account in our system for a customer and generates a new service + account for them to add access to in their GCP environment to grant us access. + + Keyword arguments: + body -- full body payload, not required if using other keywords. + { + "resources": [ + { + "client_email": "string", + "client_id": "string", + "parent_id": "string", + "parent_type": "string", + "private_key": "string", + "private_key_id": "string", + "project_id": "string", + "service_account_id": 0 + } + ] + } + client_email -- GCP account email. String. + client_id -- GCP account client ID. String. + parent_id -- GCP parent ID. String. + parent_type -- GCP parent type. String. + private_key -- GCP private key. String. + private_key_id -- GCP private key ID. String. + project_id -- GCP project ID. String. + service_account_id -- GCP service account ID. Integer. + + This method only supports keywords for providing arguments. + + Returns: dict object containing API response. + + HTTP Method: POST + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/ConnectCSPMGCPAccount + """ + if not body: + body = gcp_registration_payload(passed_keywords=kwargs) + + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="ConnectCSPMGCPAccount", + body=body + ) + + @force_default(defaults=["parameters"], default_types=["dict"]) + def get_gcp_service_account(self: object, + *args, + parameters: dict = None, + **kwargs + ) -> Dict[str, Union[int, dict]]: + """Return the service account id and client email for external clients. + + Keyword arguments: + id -- Service Account ID. String. + parameters -- full parameters payload, not required if id is provided as a keyword. + + Arguments: When not specified, the first argument to this method is assumed to be 'id'. + All others are ignored. + + Returns: dict object containing API response. + + HTTP Method: GET + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/GetCSPMGCPServiceAccountsExt + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="GetCSPMGCPServiceAccountsExt", + keywords=kwargs, + params=handle_single_argument(args, parameters, "id") + ) + + @force_default(defaults=["parameters"], default_types=["dict"]) + def get_gcp_user_scripts_attachment(self: object, + *args, + parameters: dict = None, + **kwargs + ) -> Dict[str, Union[int, dict]]: + """Retrieve GCP user script attachment. + + Return a script for customer to run in their cloud environment to + grants access to the GCP environment as a downloadable attachment. + + Keyword arguments: + ids -- Hierarchical Resource IDs of accounts. String or list of strings. + parameters -- full parameters payload, not required if ids is provided as a keyword. + parent_type -- GCP Hierarchy Parent Type. String. + Allowed values: organization, folder, project + + Arguments: When not specified, the first argument to this method is assumed to be 'ids'. + All others are ignored. + + Returns: dict object containing API response. + + HTTP Method: GET + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/cspm-registration/GetCSPMGCPUserScriptsAttachment + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="GetCSPMGCPUserScriptsAttachment", + keywords=kwargs, + params=handle_single_argument(args, parameters, "ids") ) @force_default(defaults=["parameters"], default_types=["dict"]) @@ -1070,11 +1441,22 @@ def update_scan_schedule(self: object, body: dict = None, **kwargs) -> Dict[str, GetCSPMAwsAccountScriptsAttachment = get_aws_account_scripts_attachment GetCSPMAzureAccount = get_azure_account CreateCSPMAzureAccount = create_azure_account + UpdateCSPMAzureAccount = update_azure_account DeleteCSPMAzureAccount = delete_azure_account UpdateCSPMAzureAccountClientID = update_azure_account_client_id UpdateCSPMAzureTenantDefaultSubscriptionID = update_azure_tenant_default_subscription_id GetCSPMAzureUserScriptsAttachment = get_azure_user_scripts_attachment AzureDownloadCertificate = azure_download_certificate + GetCSPMAzureManagementGroup = get_azure_management_group + CreateCSPMAzureManagementGroup = create_azure_management_group + GetCSPMCGPAccount = get_gcp_account + GetCSPMGCPAccount = get_gcp_account # Typo fix + CreateCSPMGCPAccount = create_gcp_account + DeleteCSPMGCPAccount = delete_gcp_account + UpdateCSPMGCPAccount = update_gcp_account + ConnectCSPMGCPAccount = connect_gcp_account + GetCSPMGCPServiceAccountsExt = get_gcp_service_account + GetCSPMGCPUserScriptsAttachment = get_gcp_user_scripts_attachment GetBehaviorDetections = get_behavior_detections GetConfigurationDetections = get_configuration_detections GetConfigurationDetectionEntities = get_configuration_detection_entities diff --git a/src/falconpy/d4c_registration.py b/src/falconpy/d4c_registration.py index b641d9ffc..92968135b 100644 --- a/src/falconpy/d4c_registration.py +++ b/src/falconpy/d4c_registration.py @@ -353,6 +353,7 @@ def get_azure_user_scripts_attachment(self: object, parameters: dict = None, **k Keyword arguments: parameters -- full parameters payload, not required if using other keywords. + azure_management_group - Use Azure Management Group. Boolean. subscription_ids -- Azure subscription IDs. String or list of strings. template -- Template to be rendered. String. tenant_id -- Azure tenant ID. String. @@ -469,6 +470,149 @@ def create_gcp_account(self: object, body: dict = None, **kwargs) -> Dict[str, U body=body ) + @force_default(defaults=["parameters"], default_types=["dict"]) + def delete_gcp_account(self: object, *args, parameters: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Delete a GCP account from the system. + + Keyword arguments: + ids -- Hierarchical Resource IDs of accounts. String or list of strings. + parameters -- full parameters payload, not required if ids is provided as a keyword. + + Arguments: When not specified, the first argument to this method is assumed to be 'ids'. + All others are ignored. + + Returns: dict object containing API response. + + HTTP Method: DELETE + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/d4c-registration/DeleteD4CGCPAccount + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="DeleteD4CGCPAccount", + keywords=kwargs, + params=handle_single_argument(args, parameters, "ids") + ) + + @force_default(defaults=["body"], default_types=["dict"]) + def connect_gcp_account(self: object, body: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Register new GCP account. + + Creates a new account in our system for a customer and generates a new service + account for them to add access to in their GCP environment to grant us access. + + Keyword arguments: + body -- full body payload, not required if using other keywords. + { + "resources": [ + { + "client_email": "string", + "client_id": "string", + "parent_id": "string", + "parent_type": "string", + "private_key": "string", + "private_key_id": "string", + "project_id": "string", + "service_account_id": 0 + } + ] + } + client_email -- GCP account email. String. + client_id -- GCP account client ID. String. + parent_id -- GCP parent ID. String. + parent_type -- GCP parent type. String. + private_key -- GCP private key. String. + private_key_id -- GCP private key ID. String. + project_id -- GCP project ID. String. + service_account_id -- GCP service account ID. Integer. + + This method only supports keywords for providing arguments. + + Returns: dict object containing API response. + + HTTP Method: POST + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/d4c-registration/ConnectD4CGCPAccount + """ + if not body: + body = gcp_registration_payload(passed_keywords=kwargs) + + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="ConnectD4CGCPAccount", + body=body + ) + + @force_default(defaults=["parameters"], default_types=["dict"]) + def get_gcp_service_account(self: object, + *args, + parameters: dict = None, + **kwargs + ) -> Dict[str, Union[int, dict]]: + """Return the service account id and client email for external clients. + + Keyword arguments: + id -- Service Account ID. String. + parameters -- full parameters payload, not required if id is provided as a keyword. + + Arguments: When not specified, the first argument to this method is assumed to be 'id'. + All others are ignored. + + Returns: dict object containing API response. + + HTTP Method: GET + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/d4c-registration/GetD4CGCPServiceAccountsExt + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="GetD4CGCPServiceAccountsExt", + keywords=kwargs, + params=handle_single_argument(args, parameters, "id") + ) + + @force_default(defaults=["parameters"], default_types=["dict"]) + def get_gcp_user_scripts_attachment_v2(self: object, + *args, + parameters: dict = None, + **kwargs + ) -> Dict[str, Union[int, dict]]: + """Retrieve GCP user script attachment. + + Return a script for customer to run in their cloud environment to + grant us access to their GCP environment as a downloadable attachment. + + Keyword arguments: + ids -- Hierarchical Resource IDs of accounts. String or list of strings. + parameters -- full parameters payload, not required if ids is provided as a keyword. + parent_type -- GCP Hierarchy Parent Type. String. + Allowed values: organization, folder, project + status -- Account status to filter results by. String. + + Arguments: When not specified, the first argument to this method is assumed to be 'ids'. + All others are ignored. + + Returns: dict object containing API response. + + HTTP Method: GET + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/d4c-registration/GetD4CGCPUserScriptsAttachment + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="GetD4CGCPUserScriptsAttachment", + keywords=kwargs, + params=handle_single_argument(args, parameters, "ids") + ) + @force_default(defaults=["parameters"], default_types=["dict"]) def azure_download_certificate(self: object, *args, parameters: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: """Download Azure Certificate. @@ -623,6 +767,10 @@ def get_aws_horizon_scripts(self: object, parameters: dict = None, **kwargs) -> GetD4CCGPAccount = get_gcp_account CreateCSPMGCPAccount = create_gcp_account CreateD4CGCPAccount = create_gcp_account + DeleteD4CGCPAccount = delete_gcp_account + ConnectD4CGCPAccount = connect_gcp_account + GetD4CGCPUserScriptsAttachment = get_gcp_user_scripts_attachment_v2 + GetD4CGCPServiceAccountsExt = get_gcp_service_account GetCSPMGCPUserScriptsAttachment = get_gcp_user_scripts_attachment GetCSPMGCPUserScripts = get_gcp_user_scripts GetD4CGCPUserScripts = get_gcp_user_scripts diff --git a/src/falconpy/hosts.py b/src/falconpy/hosts.py index 03c2a769e..7daca498e 100644 --- a/src/falconpy/hosts.py +++ b/src/falconpy/hosts.py @@ -95,7 +95,8 @@ def perform_action(self: object, body: dict = None, parameters: dict = None, **k if not body: body = generic_payload_list(submitted_keywords=kwargs, payload_value="ids") - _allowed_actions = ['contain', 'lift_containment', 'hide_host', 'unhide_host'] + _allowed_actions = ['contain', 'lift_containment', 'hide_host', 'unhide_host', + 'detection_suppress', 'detection_unsuppress'] operation_id = "PerformActionV2" parameter_payload = args_to_params(parameters, kwargs, Endpoints, operation_id) action_name = parameter_payload.get("action_name", "Not Specified") diff --git a/src/falconpy/image_assessment_policies.py b/src/falconpy/image_assessment_policies.py new file mode 100644 index 000000000..a49c34c5f --- /dev/null +++ b/src/falconpy/image_assessment_policies.py @@ -0,0 +1,440 @@ +"""CrowdStrike Falcon Image Assessment Policies API interface class. + + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from typing import Dict, Union +from ._util import force_default, process_service_request, handle_single_argument +from ._payload import image_policy_payload, image_exclusions_payload, image_group_payload +from ._service_class import ServiceClass +from ._endpoint._image_assessment_policies import _image_assessment_policies_endpoints as Endpoints + + +class ImageAssessmentPolicies(ServiceClass): + """The only requirement to instantiate an instance of this class is one of the following. + + - a valid client_id and client_secret provided as keywords. + - a credential dictionary with client_id and client_secret containing valid API credentials + { + "client_id": "CLIENT_ID_HERE", + "client_secret": "CLIENT_SECRET_HERE" + } + - a previously-authenticated instance of the authentication service class (oauth2.py) + - a valid token provided by the authentication service class (oauth2.py) + """ + + def read_policies(self: object) -> Dict[str, Union[int, dict]]: + """Get all Image Assessment policies. + + This method does not accept keyword arguments. + + This method does not accept arguments. + + Returns: dict object containing API response. + + HTTP Method: GET + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/image-assessment-policies/ReadPolicies + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="ReadPolicies" + ) + + @force_default(defaults=["body"], default_types=["dict"]) + def create_policies(self: object, body: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Create Image Assessment policies. + + Keyword arguments: + body -- Full body payload, not required when using other arguments. + { + "description": "string", + "name": "string" + } + description -- Policy description. String. + name -- Policy name. String. + + This method only supports keywords for providing arguments. + + Returns: dict object containing API response. + + HTTP Method: POST + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/image-assessment-policies/CreatePolicies + """ + if not body: + body = image_policy_payload(passed_keywords=kwargs) + + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="CreatePolicies", + body=body + ) + + @force_default(defaults=["parameters", "body"], default_types=["dict", "dict"]) + def update_policies(self: object, + body: dict = None, + parameters: dict = None, + **kwargs + ) -> Dict[str, Union[int, dict]]: + """Update Image Assessment Policy entities. + + Keyword arguments: + id -- Image Assessment Policy entity UUID + body -- Full body payload in JSON format. Not required when using other keywords. + { + "description": "string", + "is_enabled": boolean, + "name": "string", + "policy_data": { + "rules": [ + { + "action": "string", + "policy_rules_data": { + "conditions": [ + {} + ] + } + } + ] + } + } + description -- Policy description. String. + is_enabled -- Flag indicating if the policy is enabled. Boolean. + name -- Policy name. String. + policy_data -- Policy detail in JSON format. Dictionary. + rules -- List of rules for the policy. List of dictionaries or a single dictionary. + Overridden if policy_data is supplied. + + This method only supports keywords for providing arguments. + + Returns: dict object containing API response. + + HTTP Method: PATCH + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/image-assessment-policies/UpdatePolicies + """ + if not body: + body = image_policy_payload(passed_keywords=kwargs) + + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="UpdatePolicies", + keywords=kwargs, + params=parameters, + body=body + ) + + @force_default(defaults=["parameters"], default_types=["dict"]) + def delete_policy(self: object, *args, parameters: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Delete Image Assessment Policy by policy UUID. + + Keyword arguments: + id -- Image Assessment Policy entity UUID. String. + parameters -- Full parameters payload dictionary. Not required if using other keywords. + + Arguments: When not specified, the first argument to this method is assumed to be 'id'. + All others are ignored. + + Returns: dict object containing API response. + + HTTP Method: DELETE + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/image-assessment-policies/DeletePolicy + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="DeletePolicy", + keywords=kwargs, + params=handle_single_argument(args, parameters, "id") + ) + + def read_policy_exclusions(self: object) -> Dict[str, Union[int, dict]]: + """Retrieve Image Assessment Policy Exclusion entities. + + This method does not accept keyword arguments. + + This method does not accept arguments. + + Returns: dict object containing API response. + + HTTP Method: GET + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/image-assessment-policies/ReadPolicyExclusions + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="ReadPolicyExclusions" + ) + + @force_default(defaults=["body"], default_types=["dict"]) + def update_policy_exclusions(self: object, body: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Update Image Assessment Policy Exclusion entities. + + Keyword arguments: + body -- Full body payload in JSON format, not required if using other keywords. + { + "conditions": [ + { + "description": "string", + "prop": "string", + "ttl": 0, + "value": [ + "string" + ] + } + ] + } + conditions -- List of conditions to apply to the exclusion policy. List of dictionaries. + description -- Condition description. Ignored if conditions list is provided. String. + prop -- Condition property. Ignored if conditions list is provided. String. + ttl -- Condition time to live. Ignored if conditions list is provided. Integer. + value -- Condition values. Ignored if conditions list is provided. List of strings. + + This method only supports keywords for providing arguments. + + Returns: dict object containing API response. + + HTTP Method: POST + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/image-assessment-policies/UpdatePolicyExclusions + """ + if not body: + body = image_exclusions_payload(passed_keywords=kwargs) + + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="UpdatePolicyExclusions", + body=body + ) + + def read_policy_groups(self: object) -> Dict[str, Union[int, dict]]: + """Retrieve Image Assessment Policy Group entities. + + This method does not accept keyword arguments. + + This method does not accept arguments. + + Returns: dict object containing API response. + + HTTP Method: GET + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/image-assessment-policies/ReadPolicyGroups + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="ReadPolicyGroups" + ) + + @force_default(defaults=["body"], default_types=["dict"]) + def create_policy_groups(self: object, body: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Create Image Assessment Policy Group entities. + + Keyword arguments: + body -- Full body payload in JSON format, not required whe using other keywords. + { + "description": "string", + "name": "string", + "policy_group_data": { + "conditions": [ + {} + ] + }, + "policy_id": "string" + } + conditions -- List of policy conditions to apply. Dictionary or list of dictionaries. + Overridden if policy_group_data is supplied. + description -- Policy group description. String. + name -- Policy group name. String. + policy_group_data -- Policy group conditions. Dictionary. + policy_id -- Policy ID to update. String. + + This method only supports keywords for providing arguments. + + Returns: dict object containing API response. + + HTTP Method: POST + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/image-assessment-policies/CreatePolicyGroups + """ + if not body: + body = image_group_payload(passed_keywords=kwargs) + + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="CreatePolicyGroups", + body=body + ) + + @force_default(defaults=["parameters", "body"], default_types=["dict", "dict"]) + def update_policy_groups(self: object, + body: dict = None, + parameters: dict = None, + **kwargs + ) -> Dict[str, Union[int, dict]]: + """Update Image Assessment Policy Group entities. + + Keyword arguments: + body -- Full body payload in JSON format, not required when using other keywords. + { + "description": "string", + "name": "string", + "policy_group_data": { + "conditions": [ + {} + ] + } + } + conditions -- List of policy conditions to apply. Dictionary or list of dictionaries. + Overridden if policy_group_data is supplied. + description -- Policy group description. String. + id -- Policy Image Group entity UUID. String. + name -- Policy group name. String. + parameters -- Full parameters payload dictionary. Not required if using other keywords. + policy_group_data -- List of policy conditions. Dictionary. + + This method only supports keywords for providing arguments. + + Returns: dict object containing API response. + + HTTP Method: PATCH + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/image-assessment-policies/UpdatePolicyGroups + """ + if not body: + body = image_group_payload(passed_keywords=kwargs) + + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="UpdatePolicyGroups", + keywords=kwargs, + params=parameters, + body=body + ) + + @force_default(defaults=["parameters"], default_types=["dict"]) + def delete_policy_group(self: object, *args, parameters: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Delete Image Assessment Policy Group entities. + + Keyword arguments: + id -- Policy Image Group entity UUID + parameters -- Full parameters payload dictionary. Not required if using other keywords. + + Arguments: When not specified, the first argument to this method is assumed to be 'id'. + All others are ignored. + + Returns: dict object containing API response. + + HTTP Method: DELETE + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/image-assessment-policies/DeletePolicyGroup + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="DeletePolicyGroup", + keywords=kwargs, + params=handle_single_argument(args, parameters, "id") + ) + + @force_default(defaults=["body"], default_types=["dict"]) + def update_policy_precedence(self: object, body: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Update Image Assessment Policy precedence. + + Keyword arguments: + body -- Full body payload in JSON format, not required when using other keywords. + { + "precedence": [ + "string" + ] + } + precedence -- List of policy IDs in precedence order. String or List of strings. + + This method only supports keywords for providing arguments. + + Returns: dict object containing API response. + + HTTP Method: POST + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/image-assessment-policies/UpdatePolicyPrecedence + """ + if not body: + prec = kwargs.get("precedence", None) + if isinstance(prec, str): + prec = prec.split(",") + if prec: + body["precedence"] = prec + + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="UpdatePolicyPrecedence", + body=body + ) + + # These method names align to the operation IDs in the API but + # do not conform to snake_case / PEP8 and are defined here + # for backwards compatibility / ease of use purposes + ReadPolicies = read_policies + CreatePolicies = create_policies + UpdatePolicies = update_policies + DeletePolicy = delete_policy + ReadPolicyExclusions = read_policy_exclusions + UpdatePolicyExclusions = update_policy_exclusions + ReadPolicyGroups = read_policy_groups + CreatePolicyGroups = create_policy_groups + UpdatePolicyGroups = update_policy_groups + DeletePolicyGroup = delete_policy_group + UpdatePolicyPrecedence = update_policy_precedence diff --git a/src/falconpy/workflows.py b/src/falconpy/workflows.py index bc3014a08..7ad182a44 100644 --- a/src/falconpy/workflows.py +++ b/src/falconpy/workflows.py @@ -36,12 +36,19 @@ For more information, please refer to """ from typing import Dict, Union -from ._util import force_default, process_service_request, handle_single_argument +from ._util import ( + force_default, + process_service_request, + handle_single_argument, + generate_error_result + ) from ._payload import ( simple_action_parameter, generic_payload_list, workflow_deprovision_payload, - workflow_template_payload + workflow_template_payload, + workflow_definition_payload, + workflow_human_input ) from ._service_class import ServiceClass from ._endpoint._workflows import _workflows_endpoints as Endpoints @@ -60,6 +67,201 @@ class Workflows(ServiceClass): - a valid token provided by the authentication service class (oauth2.py) """ + @force_default(defaults=["parameters"], default_types=["dict"]) + def search_definitions(self: object, parameters: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Search workflow definitions based on the provided filter. + + Keyword arguments: + filter -- FQL query specifying filter parameters. String. + offset -- Starting pagination offset of records to return. String. + limit -- Maximum number of records to return. Integer. + sort -- FQL formatted sort (ex: name.desc,time.asc). String. + If direction is omitted, defaults to descending. + parameters -- Full parameters payload dictionary. Not required if using other keywords. + + This method only supports keywords for providing arguments. + + Returns: dict object containing API response. + + HTTP Method: GET + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/workflows/WorkflowDefinitionsCombined + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="WorkflowDefinitionsCombined", + keywords=kwargs, + params=parameters + ) + + @force_default(defaults=["parameters"], default_types=["dict"]) + def search_executions(self: object, parameters: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Search workflow executions based on the provided filter. + + Keyword arguments: + filter -- FQL query specifying filter parameters. String. + offset -- Starting pagination offset of records to return. String. + limit -- Maximum number of records to return. Integer. + sort -- FQL formatted sort (ex: name.desc,time.asc). String. + If direction is omitted, defaults to descending. + parameters -- Full parameters payload dictionary. Not required if using other keywords. + + This method only supports keywords for providing arguments. + + Returns: dict object containing API response. + + HTTP Method: GET + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/workflows/WorkflowExecutionsCombined + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="WorkflowExecutionsCombined", + keywords=kwargs, + params=parameters + ) + + @force_default(defaults=["parameters"], default_types=["dict"]) + def export_definition(self: object, *args, parameters: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Export a workflow definition for the given definition ID. + + Keyword arguments: + id -- ID of workflow definitions to return details for. String. + parameters -- Full parameters payload dictionary. Not required if using other keywords. + + Arguments: When not specified, the first argument to this method is assumed to be 'id'. + All others are ignored. + + Returns: dict object containing API response. + + HTTP Method: GET + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/workflows/WorkflowDefinitionsExport + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="WorkflowDefinitionsExport", + keywords=kwargs, + params=handle_single_argument(args, parameters, "id") + ) + + @force_default(defaults=["parameters"], default_types=["dict"]) + def import_definition(self: object, parameters: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Import a workflow definition based on the provided model. + + Keyword arguments: + data_file -- A workflow definition in YAML format to import. Binary data. + name -- Workflow name to override. String. + validate_only -- When enabled, prevents saving workflow after validating. Boolean. + parameters -- Full parameters payload dictionary. Not required if using other keywords. + + This method only supports keywords for providing arguments. + + Returns: dict object containing API response. + + HTTP Method: POST + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/workflows/WorkflowDefinitionsImport + """ + data_file = kwargs.get("data_file", None) + if data_file: + returned = process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="WorkflowDefinitionsImport", + keywords=kwargs, + params=parameters, + data=data_file + ) + else: + returned = generate_error_result("You must provide a workflow file in YAML format to import.") + + return returned + + @force_default(defaults=["body", "parameters"], default_types=["dict", "dict"]) + def update_definition(self: object, + body: dict = None, + parameters: dict = None, + **kwargs + ) -> Dict[str, Union[int, dict]]: + """Update a workflow definition based on the provided model. + + Keyword arguments: + validate_only -- When enabled, prevents saving workflow after validating. Boolean. + body -- Full body payload in JSON format, not required when using other keywords. + definition -- Full workflow definition. Dictionary. + change_log -- Optional description to outline changes made during the update. String. + enabled -- Specifies if the new definition should be enabled upon creation. + flight_control -- Flight control parameters. Dictionary. + id -- Used to identify documents across versions. String. + parameters -- Full parameters payload dictionary. Not required if using other keywords. + + This method only supports keywords for providing arguments. + + Returns: dict object containing API response. + + HTTP Method: PUT + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/workflows/WorkflowDefinitionsUpdate + """ + if not body: + body = workflow_definition_payload(passed_keywords=kwargs) + + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="WorkflowDefinitionsUpdate", + keywords=kwargs, + params=parameters, + body=body + ) + + @force_default(defaults=["body", "parameters"], default_types=["dict", "dict"]) + def create_definition(self: object, + body: dict = None, + parameters: dict = None, + **kwargs + ) -> Dict[str, Union[int, dict]]: + """Create a workflow definition based on the provided model. + + Keyword arguments: + validate_only -- When enabled, prevents saving workflow after validating. Boolean. + body -- Full body payload in JSON format, not required when using other keywords. + definition -- Full workflow definition. Dictionary. + change_log -- Optional description to outline changes made during the update. String. + enabled -- Specifies if the new definition should be enabled upon creation. + flight_control -- Flight control parameters. Dictionary. + parameters -- Full parameters payload dictionary. Not required if using other keywords. + + This method only supports keywords for providing arguments. + + Returns: dict object containing API response. + + HTTP Method: POST + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/workflows/WorkflowDefinitionsCreate + """ + if not body: + body = workflow_definition_payload(passed_keywords=kwargs) + + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="WorkflowDefinitionsCreate", + keywords=kwargs, + params=parameters, + body=body + ) + @force_default(defaults=["body", "parameters"], default_types=["dict", "dict"]) def execute(self: object, body: dict = None, parameters: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: """Execute an on-demand workflow. Response will contain the execution ID. @@ -71,6 +273,8 @@ def execute(self: object, body: dict = None, parameters: dict = None, **kwargs) } definition_id -- Definition ID to execute. Either a name or ID can be specified. String or List of Strings. + execution_cid -- CID(s) to execute on. This can be a child for Flight Control scenarios. + If unset, the definition CID is used. String or List of strings. name -- Workflow name to execute. Either a name or ID can be specified. String. parameters -- Full parameters payload in dictionary (JSON) format. Not required if you are using other keywords. Dictionary. @@ -173,6 +377,75 @@ def execution_results(self: object, *args, parameters: dict = None, **kwargs) -> params=handle_single_argument(args, parameters, "ids") ) + @force_default(defaults=["parameters"], default_types=["dict"]) + def get_human_input(self: object, *args, parameters: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: + """Get one or more specific human inputs by their IDs. + + Keyword arguments: + ids -- IDs of human inputs to read. String or List of strings. + parameters -- Full parameters payload dictionary. Not required if using other keywords. + + Arguments: When not specified, the first argument to this method is assumed to be 'ids'. + All others are ignored. + + Returns: dict object containing API response. + + HTTP Method: GET + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/workflows/WorkflowGetHumanInputV1 + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="WorkflowGetHumanInputV1", + keywords=kwargs, + params=handle_single_argument(args, parameters, "ids") + ) + + @force_default(defaults=["body", "parameters"], default_types=["dict", "dict"]) + def update_human_input(self: object, + body: dict = None, + parameters: dict = None, + **kwargs + ) -> Dict[str, Union[int, dict]]: + """Update a human input. + + Provides an input in response to a human input action. + Depending on action configuration, one or more of Approve, Decline, and/or Escalate are permitted. + + Keyword arguments: + body -- Full body payload in JSON format, not required when using other keywords. + { + "input": "string", + "note": "string" + } + id -- ID of human input to provide an input to. String. + input -- Input to insert. String. + note -- Optional note to append. String. + parameters -- Full parameters payload dictionary. Not required if using other keywords. + + This method only supports keywords for providing arguments. + + Returns: dict object containing API response. + + HTTP Method: POST + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/workflows/WorkflowUpdateHumanInputV1 + """ + if not body: + body = workflow_human_input(passed_keywords=kwargs) + + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="WorkflowUpdateHumanInputV1", + keywords=kwargs, + params=parameters, + body=body + ) + @force_default(defaults=["body"], default_types=["dict"]) def deprovision(self: object, body: dict = None, **kwargs) -> Dict[str, Union[int, dict]]: """Deprovision a system definition that was previously provisioned on a target CID. @@ -373,9 +646,17 @@ def provision(self: object, body: dict = None, **kwargs) -> Dict[str, Union[int, # These method names align to the operation IDs in the API but # do not conform to snake_case / PEP8 and are defined here for # backwards compatibility / ease of use purposes + WorkflowDefinitionsCombined = search_definitions + WorkflowExecutionsCombined = search_executions + WorkflowDefinitionsExport = export_definition + WorkflowDefinitionsImport = import_definition + WorkflowDefinitionsUpdate = update_definition + WorkflowDefinitionsCreate = create_definition WorkflowExecute = execute WorkflowExecutionsAction = execution_action WorkflowExecutionResults = execution_results + WorkflowGetHumanInputV1 = get_human_input + WorkflowUpdateHumanInputV1 = update_human_input WorkflowSystemDefinitionsDeProvision = deprovision WorkflowSystemDefinitionsPromote = promote WorkflowSystemDefinitionsProvision = provision diff --git a/tests/test_authentications.py b/tests/test_authentications.py index d218f10cd..1af019487 100644 --- a/tests/test_authentications.py +++ b/tests/test_authentications.py @@ -302,6 +302,19 @@ def test_EnvironmentAuthentication(self): else: pytest.skip("Required environment credentials not present") + def test_EnvironmentAuthFail(self): + _returned = False + save_id = os.getenv("FALCON_CLIENT_ID") + save_key = os.getenv("FALCON_CLIENT_SECRET") + if save_id or save_key: + thing = Hosts(debug=_DEBUG, member_cid="12345678") + result = thing.login() + if thing.token_status != 201: + _returned = True + assert _returned + else: + pytest.skip("Required environment credentials not present") + @pytest.mark.skipif(auth.authorization.base_url == "https://api.laggar.gcw.crowdstrike.com", reason="Test unsupported in GovCloud" ) diff --git a/tests/test_container_alerts.py b/tests/test_container_alerts.py index c4bb87995..6631ff0b1 100644 --- a/tests/test_container_alerts.py +++ b/tests/test_container_alerts.py @@ -23,6 +23,7 @@ class TestContainerAlerts: def test_all_code_paths(self): error_checks = True tests = { + "read_counts_by_severity": falcon.read_counts_by_severity(filter="cid:'12345678901234567890123456789012"), "read_counts": falcon.read_counts(filter="cid:'12345678901234567890123456789012"), "search_and_read": falcon.search_and_read(limit=1) } diff --git a/tests/test_cspm_registration.py b/tests/test_cspm_registration.py index 6b82e6570..190307a65 100644 --- a/tests/test_cspm_registration.py +++ b/tests/test_cspm_registration.py @@ -85,7 +85,17 @@ def cspm_generate_errors(self): "get_configuration_detections": falcon.get_configuration_detections(limit=1), "GetConfigurationDetectionEntities": falcon.get_configuration_detection_entities(), "GetConfigurationDetectionIdsV2": falcon.get_configuration_detection_ids_v2(), - "GetCSPMPoliciesDetails": falcon.get_policy_details() + "GetCSPMPoliciesDetails": falcon.get_policy_details(), + "GetGCPAccount": falcon.get_gcp_account(ids="12345678", scan_type="dry"), + "CreateGCPAccount": falcon.create_gcp_account(parent_id="whatever", parent_type="shiny"), + "DeleteD4CGCPAccount": falcon.delete_gcp_account("1234567"), + "ConnectD4CGCPAccount": falcon.connect_gcp_account(client_id="123456", parent_id="123456"), + "GetD4CGCPServiceAccoutnExt": falcon.get_gcp_service_account(id="12345678"), + "GetD4CGCPUserScriptsAttachmentV2": falcon.get_gcp_user_scripts_attachment(ids="12345678"), + "UpdateGCP": falcon.update_gcp_account(environment="temperate", parent_id="1234567"), + "GetMgmt": falcon.get_azure_management_group(tenant_id="1234567"), + "CreateMgmt": falcon.create_azure_management_group(default_subscription_id="bob", tenant_id="1234567"), + "UpdateAzure": falcon.update_azure_account(environment="chilly", subscription_id="banana") } for key in tests: if tests[key]["status_code"] != 500: diff --git a/tests/test_d4c_registration.py b/tests/test_d4c_registration.py index 7548001ec..151fc8356 100644 --- a/tests/test_d4c_registration.py +++ b/tests/test_d4c_registration.py @@ -105,7 +105,11 @@ def d4c_generate_errors(self): "GetD4CAwsConsoleSetupURLs": falcon.get_aws_console_setup("us-east-2"), "GetD4CAwsAccountScriptsAttachment": falcon.get_aws_account_scripts("123456789"), "GetHorizonD4CScripts": falcon.get_aws_horizon_scripts(organization_id="123456789"), - "GetDiscoverCloudAzureTenantIDs": falcon.get_azure_tenant_ids() + "GetDiscoverCloudAzureTenantIDs": falcon.get_azure_tenant_ids(), + "DeleteD4CGCPAccount": falcon.delete_gcp_account("1234567"), + "ConnectD4CGCPAccount": falcon.connect_gcp_account(client_id="123456", parent_id="123456"), + "GetD4CGCPServiceAccoutnExt": falcon.get_gcp_service_account(id="12345678"), + "GetD4CGCPUserScriptsAttachmentV2": falcon.get_gcp_user_scripts_attachment_v2(ids="12345678") } for key in tests: if tests[key]["status_code"] != 500: diff --git a/tests/test_image_assessment_policies.py b/tests/test_image_assessment_policies.py new file mode 100644 index 000000000..3ebbde7a4 --- /dev/null +++ b/tests/test_image_assessment_policies.py @@ -0,0 +1,49 @@ +# test_image_assessment_policies.py +# This class tests the image assessment policies service class + +# import json +import os +import sys + +# Authentication via the test_authorization.py +from tests import test_authorization as Authorization + +# Import our sibling src folder into the path +sys.path.append(os.path.abspath('src')) +# Classes to test - manually imported from sibling folder +from falconpy import ImageAssessmentPolicies + +auth = Authorization.TestAuthorization() +config = auth.getConfigObject() +falcon = ImageAssessmentPolicies(auth_object=config) +AllowedResponses = [200, 201, 207, 400, 502] # Allowing 502 from CreatePolicyGroups for now + + +class TestImageAssessmentPolicies: + def test_all_code_paths(self): + error_checks = True + tests = { + "ReadPolicies": falcon.read_policies(), + "CreatePolicies": falcon.create_policies(description="whatever"), + "UpdatePolicies": falcon.update_policies(name="whatever", is_enabled=False, rules=[], policy_data={}), + "UpdatePolicies": falcon.update_policies(name="whatever", is_enabled=False, rules={}, policy_data={}), + "ReadPolicyExclusions": falcon.read_policy_exclusions(), + "UpdatePolicyExclusions": falcon.update_policy_exclusions(description="whatever", conditions=[]), + "ReadPolicyGroups": falcon.read_policy_groups(), + "CreatePolicyGroups": falcon.create_policy_groups(name="whatever", policy_id="1234567"), + "UpdatePolicyGroups": falcon.update_policy_groups(id="12345678", description="something", policy_group_data={}), + "UpdatePolicyGroups": falcon.update_policy_groups(id="12345678", description="something", conditions={"whatever": "something"}), + "DeletePolicyGroup": falcon.delete_policy_group(id="1234567"), + "UpdatePolicyPrecedence": falcon.update_policy_precedence(precedence="123457,8765542"), + } + if tests["CreatePolicies"]["status_code"] == 200: + tests["DeletePolicy"] = falcon.delete_policy(tests["CreatePolicies"]["body"]["resources"][0]["policy_id"]) + else: + tests["DeletePolicy"] = falcon.delete_policy("12345678") + for key in tests: + + if tests[key]["status_code"] not in AllowedResponses: + error_checks = False + # print(key) + # print(tests[key]) + assert error_checks diff --git a/tests/test_real_time_response.py b/tests/test_real_time_response.py index 6d2eb805b..fc2684a81 100644 --- a/tests/test_real_time_response.py +++ b/tests/test_real_time_response.py @@ -49,10 +49,12 @@ def rtr_session_tester(self): # pytest.skip("Race condition met, skipping.") if aid_to_check: - result = falcon.RTR_InitSession(body={"device_id": aid_to_check}) + result = falcon.batch_init_sessions(host_ids=aid_to_check) if "resources" in result["body"]: if result["body"]["resources"]: - session_id = result["body"]["resources"][0]["session_id"] + session_id = result["body"]["resources"][aid_to_check]["session_id"] + batch_id = result["body"].get("combined") + falcon.batch_get_command(batch_id=batch_id, file_path="/tmp/testfile.txt") if falcon.RTR_DeleteSession(session_id=session_id)["status_code"] in AllowedResponses: returned = True else: diff --git a/tests/test_service_class.py b/tests/test_service_class.py index 7e884bcb9..dafc44a0c 100644 --- a/tests/test_service_class.py +++ b/tests/test_service_class.py @@ -376,18 +376,21 @@ def test_list_response_component_get_property(self): @rate_limited @not_supported def test_list_response_component_get_property_fail(self): - with pytest.warns(SSLDisabledWarning): - _no_ssl = Hosts(creds=config.creds, pythonic=True, debug=_DEBUG, ssl_verify=False) - if _no_ssl.token_status == 403: - pytest.skip("SSL required for GovCloud testing.") - try: - if _no_ssl.token_valid and not _no_ssl.token_stale: # Duplicative, just testing the properties - _thing: Result = _no_ssl.query_devices(limit=3) - except APIError: - pytest.skip("SSL required for GovCloud testing.") - position = 5 _success = False + if config.base_url != "https://api.laggar.gcw.crowdstrike.com": + with pytest.warns(SSLDisabledWarning): + _no_ssl = Hosts(creds=config.creds, pythonic=True, debug=_DEBUG, ssl_verify=False) + if _no_ssl.token_status == 403: + pytest.skip("SSL required for GovCloud testing.") + try: + if _no_ssl.token_valid and not _no_ssl.token_stale: # Duplicative, just testing the properties + _thing: Result = _no_ssl.query_devices(limit=3) + except APIError: + pytest.skip("SSL required for GovCloud testing.") + else: + pytest.skip("This test is unsupported in this region.") + try: _success = bool(_thing.resources.get_property(position)) except IndexError: diff --git a/tests/test_workflows.py b/tests/test_workflows.py index a82534013..b12adaf1d 100644 --- a/tests/test_workflows.py +++ b/tests/test_workflows.py @@ -15,7 +15,7 @@ auth = Authorization.TestAuthorization() config = auth.getConfigObject() falcon = Workflows(auth_object=config) -AllowedResponses = [200, 201, 400, 403, 404, 429] # Temp allow 403 +AllowedResponses = [200, 201, 400, 403, 404, 415, 500] # Allowing 415 due to workflow import class TestWorkflows: @@ -28,12 +28,21 @@ def run_all_tests(self): "WorkflowSystemDefinitionsDeProvision" : falcon.deprovision(definition_id="12345", deprovision_all=True), "WorkflowSystemDefinitionsPromote" : falcon.promote(customer_definition_id="12345", activities={}), "WorkflowSystemDefinitionsProvision" : falcon.provision(name="FalconPyTesting", configuration=[{}]), - + "WorkflowDefinitionsCombined": falcon.search_definitions(), + "WorkflowExecutionsCombined": falcon.search_executions(), + "WorkflowDefinitionsExport": falcon.export_definition(), + "WorkflowDefinitionsImport": falcon.import_definition(validate_only=True, data_file="this_will_415"), + "WorkflowDefinitionsImport": falcon.import_definition(validate_only=True, file_data="this_will_500"), + "WorkflowDefinitionsUpdate": falcon.update_definition(change_log="testing"), + "WorkflowDefinitionsCreate": falcon.create_definition(change_log="testing"), + "WorkflowGetHumanInputV1": falcon.get_human_input(ids="1234567"), + "WorkflowUpdateHumanInputV1": falcon.update_human_input(input="whatever", note="whatever"), } for key in tests: if tests[key]["status_code"] not in AllowedResponses: error_checks = False - # print(tests[key]) + # print(key) + # print(tests[key]) return error_checks