Cisco ASA
Use the Cisco Adaptive Security Appliance Software integration to manage interfaces, rules, and network objects.
Network Security · Cisco ASA
Details
| ID | Cisco ASA |
|---|---|
| Provider | Cisco Systems |
| Category | Network Security |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM EDR Cortex Cloud Cloud Runtime Security |
README
Use the Cisco Adaptive Security Appliance Software integration to manage interfaces, rules, and network objects.
This integration was integrated and tested with version 9.16(3)23 of Cisco ASA
Configure Cisco ASA in Cortex
| Parameter | Required |
|---|---|
| Server URL (e.g., https://192.168.0.1) | True |
| Credentials | True |
| Password | True |
| Use system proxy settings | False |
| Trust any certificate (not secure) | False |
| Is ASAv | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
cisco-asa-list-network-object-group
Retrieve information about network object groups. Network object groups can contain multiple network objects as well as inline networks or hosts. Network object groups can include a mix of both IPv4 and IPv6 addresses/network.
Base Command
cisco-asa-list-network-object-group
Input
| Argument Name | Description | Required |
|---|---|---|
| object_id | The object ID of the network group to retrieve. This can’t be used with pagination arguments. | Optional |
| page | Page number of paginated results. Minimum of 1; default 1. | Optional |
| page_size | The number of items per page. Maximum of 100; default 50. | Optional |
| limit | The maximum number of records to retrieve. Maximum of 100; default 50. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoASA.NetworkObjectGroup.object_id | String | The object ID of the network object group. |
| CiscoASA.NetworkObjectGroup.name | String | The name of the network object group. |
| CiscoASA.NetworkObjectGroup.description | String | The description of the network object group. |
| CiscoASA.NetworkObjectGroup.members.kind | String | The type of the network item. The viable types are IPv4Address, IPv4Network, IPv6Address, IPv6Network and objectRef#NetworkObj. |
| CiscoASA.NetworkObjectGroup.members.object_id | String | The object ID of the network object. |
| CiscoASA.NetworkObjectGroup.members.value | String | The value of IPv4Address, IPv4Network, IPv6Address or IPv6Network. |
Command example
!cisco-asa-list-network-object-group limit=1
Context Example
{
"CiscoASA": {
"NetworkObjectGroup": {
"description": "This is a test",
"members": [
{
"kind": "objectRef#NetworkObj",
"object_id": "Test_Lior"
},
{
"kind": "objectRef#NetworkObj",
"object_id": "Test_Lior1"
},
{
"kind": "objectRef#NetworkObj",
"object_id": "Test_Lior2"
}
],
"name": "TEST_GROUP1",
"object_id": "TEST_GROUP1"
}
}
}
Human Readable Output
Network Object Groups
Object Id Name Description Members TEST_GROUP1 TEST_GROUP1 This is a test {‘kind’: ‘objectRef#NetworkObj’, ‘object_id’: ‘Test_Lior’},
{‘kind’: ‘objectRef#NetworkObj’, ‘object_id’: ‘Test_Lior1’},
{‘kind’: ‘objectRef#NetworkObj’, ‘object_id’: ‘Test_Lior2’}
cisco-asa-list-local-user-group
Retrieve information about local user groups, which are collections of user accounts, either from the local database or imported from Active Directory, that manage access to network resources not defined globally.
Base Command
cisco-asa-list-local-user-group
Input
| Argument Name | Description | Required |
|---|---|---|
| object_id | The object ID of the local user group to retrieve. This can’t be used with pagination arguments. | Optional |
| page | Page number of paginated results. Minimum of 1; default 1. | Optional |
| page_size | The number of items per page. Maximum of 100; default 50. | Optional |
| limit | The maximum number of records to retrieve. Maximum of 100; default 50. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoASA.LocalUserGroup.object_id | String | The object ID of the local user group. |
| CiscoASA.LocalUserGroup.name | String | The name of the local user group. |
| CiscoASA.LocalUserGroup.description | String | The description of the local user group. |
| CiscoASA.LocalUserGroup.members.kind | String | The type of the user. |
| CiscoASA.LocalUserGroup.members.object_id | String | The ID of the user. |
Command example
!cisco-asa-list-local-user-group limit=1
Context Example
{
"CiscoASA": {
"LocalUserGroup": {
"members": [
{
"kind": "objectRef#UserObj",
"object_id": "api"
},
{
"kind": "objectRef#UserObj",
"object_id": "restapi"
}
],
"name": "LIOR_GROUP",
"object_id": "LIOR_GROUP"
}
}
}
Human Readable Output
Local User Groups
Object Id Name Members LIOR_GROUP LIOR_GROUP {‘kind’: ‘objectRef#UserObj’, ‘object_id’: ‘api’},
{‘kind’: ‘objectRef#UserObj’, ‘object_id’: ‘restapi’}
cisco-asa-list-local-user
Retrieve information about individual local user accounts within a network system. These local users can be part of local user groups and groups imported from Active Directory.
Base Command
cisco-asa-list-local-user
Input
| Argument Name | Description | Required |
|---|---|---|
| object_id | The object ID of the local user to retrieve. This can’t be used with pagination arguments. | Optional |
| page | Page number of paginated results. Minimum of 1; default 1. | Optional |
| page_size | The number of items per page. Maximum of 100; default 50. | Optional |
| limit | The maximum number of records to retrieve. Maximum of 100; default 50. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoASA.LocalUser.object_id | String | The object ID of the local user. |
| CiscoASA.LocalUser.name | String | The name of the local user. |
| CiscoASA.LocalUser.mschap_authenticated | Boolean | Whether Extensible Authentication Protocol-Microsoft Challenge Handshake Authentication Protocol is authenticated. |
| CiscoASA.LocalUser.privilege_level | Number | The user’s privilege level. |
| CiscoASA.LocalUser.asdm_cli_access_type | String | ASDM and CLI access type. Can be one of “Full”, “None”, “Cli”. |
Command example
!cisco-asa-list-local-user limit=1
Context Example
{
"CiscoASA": {
"LocalUser": {
"asdm_cli_access_type": "Full",
"mschap_authenticated": false,
"name": "admin",
"object_id": "admin",
"privilege_level": 15
}
}
}
Human Readable Output
Local Users
Object Id Name Privilege Level Asdm Cli Access Type admin admin 15 Full
cisco-asa-list-time-range
Retrieve information about time range objects. A time range object defines a specific time consisting of a start time, an end time, and optional recurring entries. You use these objects on ACL rules to provide time-based access to certain features or assets. For example, you could create an access rule that allows access to a particular server during working hours only.
Base Command
cisco-asa-list-time-range
Input
| Argument Name | Description | Required |
|---|---|---|
| object_id | The object ID of the time range to retrieve. This can’t be used with pagination arguments. | Optional |
| page | Page number of paginated results. Minimum of 1; default 1. | Optional |
| page_size | The number of items per page. Maximum of 100; default 50. | Optional |
| limit | The maximum number of records to retrieve. Maximum of 100; default 50. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoASA.TimeRange.object_id | String | The object ID of the time range. |
| CiscoASA.TimeRange.name | String | The name of the time range. |
| CiscoASA.TimeRange.start | String | Time at which this time range starts. |
| CiscoASA.TimeRange.end | String | Time at which this time range ends. |
| CiscoASA.TimeRange.periodic.frequency | String | The days of the week at which this time range will run periodically. |
| CiscoASA.TimeRange.periodic.start_hour | Number | The hour at which this time range will start periodically. |
| CiscoASA.TimeRange.periodic.start_minute | Number | The minute at which this time range will start periodically. |
| CiscoASA.TimeRange.periodic.end_hour | Number | The hour at which this time range will end periodically. |
| CiscoASA.TimeRange.periodic.end_minute | Number | The minute at which this time range will end periodically. |
Command example
!cisco-asa-list-time-range page=1 page_size=1
Context Example
{
"CiscoASA": {
"TimeRange": {
"end": "03:47 May 14 2014",
"name": "trUserTest",
"object_id": "trUserTest",
"periodic": [
{
"end_hour": 23,
"end_minute": 59,
"frequency": "Wednesday to Thursday",
"start_hour": 4,
"start_minute": 3
}
],
"start": "now"
}
}
}
Human Readable Output
Time Ranges
Object Id Name Start End Periodic trUserTest trUserTest now 03:47 May 14 2014 {‘frequency’: ‘Wednesday to Thursday’, ‘start_hour’: 4, ‘start_minute’: 3, ‘end_hour’: 23, ‘end_minute’: 59}
cisco-asa-list-security-object-group
Retrieve information about security groups, which are collections of security groups or identifiers that manage access and permissions to network resources. These groups can be used in features like Cisco TrustSec and are often part of extended access control lists, enabling centralized and localized security policy management.
Base Command
cisco-asa-list-security-object-group
Input
| Argument Name | Description | Required |
|---|---|---|
| object_id | The object ID of the security object group to retrieve. This can’t be used with pagination arguments. | Optional |
| page | Page number of paginated results. Minimum of 1; default 1. | Optional |
| page_size | The number of items per page. Maximum of 100; default 50. | Optional |
| limit | The maximum number of records to retrieve. Maximum of 100; default 50. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoASA.SecurityObjectGroup.object_id | String | The object ID of the security object group. |
| CiscoASA.SecurityObjectGroup.name | String | The name of the security object group. |
| CiscoASA.SecurityObjectGroup.description | String | The description of the security object group. |
| CiscoASA.SecurityObjectGroup.members.kind | String | The type of the security object group; SecurityName, SecurityTag, objectRef#SecurityObjGroup. |
| CiscoASA.SecurityObjectGroup.members.value | String | The value of the SecurityName or SecurityTag. |
| CiscoASA.SecurityObjectGroup.members.object_id | String | The object ID of objectRef#SecurityObjGroup. |
Command example
!cisco-asa-list-security-object-group page=1 page_size=1
Context Example
{
"CiscoASA": {
"SecurityObjectGroup": {
"description": "test12",
"members": [
{
"kind": "SecurityName",
"value": "zeno1"
},
{
"kind": "SecurityTag",
"value": "71"
}
],
"name": "oneSecurityGroup",
"object_id": "oneSecurityGroup"
}
}
}
Human Readable Output
Security Object Groups
Object Id Name Description Members oneSecurityGroup oneSecurityGroup test12 {‘kind’: ‘SecurityName’, ‘value’: ‘zeno1’},
{‘kind’: ‘SecurityTag’, ‘value’: ‘71’}
cisco-asa-list-user-object
Retrieve information about user definitions within the system. This helps in managing and configuring user access and permissions in a network security context.
Base Command
cisco-asa-list-user-object
Input
| Argument Name | Description | Required |
|---|---|---|
| object_id | The object ID of the user object to retrieve. This can’t be used with pagination arguments. | Optional |
| page | Page number of paginated results. Minimum of 1; default 1. | Optional |
| page_size | The number of items per page. Maximum of 100; default 50. | Optional |
| limit | The maximum number of records to retrieve. Maximum of 100; default 50. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoASA.UserObject.object_id | String | The object ID of the user object. |
| CiscoASA.UserObject.user_name | String | The user’s user name. |
| CiscoASA.UserObject.local_user_object_id | String | The object ID of the local user. |
| CiscoASA.UserObject.value | String | The value of the local user. |
Command example
!cisco-asa-list-user-object page=1 page_size=1
Context Example
{
"CiscoASA": {
"UserObject": {
"local_user_object_id": "api",
"object_id": "api",
"user_name": "api"
}
}
}
Human Readable Output
User Objects
Object Id User Name api api
cisco-asa-write-memory
Saves the running configuration to the default location for the startup configuration.
Base Command
cisco-asa-write-memory
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoASA.WriteMemory.response | String | Shows a successful ‘write memory’ command execution on a Cisco ASA device, building the configuration and generating a cryptochecksum for integrity. The process is completed with an “[OK]” message. |
Command example
#### Context Example
```json
{
"CiscoASA": {
"WriteMemory": {
"response": [
"Building configuration...\nCryptochecksum: fa399474 22b66df0 6e2a7619 b37adea3 \n\n20838 bytes copied in 0.50 secs\n[OK]\n"
]
}
}
}
Human Readable Output
Results
response Building configuration…
Cryptochecksum: fa399474 22b66df0 6e2a7619 b37adea3
20838 bytes copied in 0.50 secs
[OK]
cisco-asa-list-rules
Gets a list all rules for the supplied interface.
Base Command
cisco-asa-list-rules
Input
| Argument Name | Description | Required |
|---|---|---|
| interface_name | The name of the interface from which to get rules. | Optional |
| interface_type | The interface type. Possible values are: In, Out, Global. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoASA.Rules.Source | String | The rule’s source. |
| CiscoASA.Rules.Dest | String | The rule’s destination. |
| CiscoASA.Rules.InterfaceType | String | The interface type. Can be “In”, “Out”, or “Global”. |
| CiscoASA.Rules.IsActive | Boolean | Whether the rule is active. |
| CiscoASA.Rules.Interface | String | The name of the interface. |
| CiscoASA.Rules.Position | Number | The position of the rule. |
| CiscoASA.Rules.ID | String | The rule ID. |
| CiscoASA.Rules.Remarks | Unknown | A list of all rule remarks. |
| CiscoASA.Rules.Permit | Boolean | Whether the rule permits traffic from source to destination. |
| CiscoASA.Rules.DestService | String | The destination service. |
| CiscoASA.Rules.SourceService | String | The source service. |
| CiscoASA.Rules.SourceKind | String | One of AnyIPAddress, IPv4Address, IPv4FQDN, IPv4Network, IPv4Range, IPv6Address, IPv6FQDN, IPv6Network, IPv6Range, SecurityName, SecurityTag, interfaceIP, objectRef#NetworkObj, objectRef#NetworkObjGroup. |
| CiscoASA.Rules.DestKind | String | One of AnyIPAddress, IPv4Address, IPv4FQDN, IPv4Network, IPv4Range, IPv6Address, IPv6FQDN, IPv6Network, IPv6Range, SecurityName, SecurityTag, interfaceIP, objectRef#NetworkObj, objectRef#NetworkObjGroup. |
| CiscoASA.Rules.SourceSecurity.kind | String | The type of the security group; SecurityName, SecurityTag, objectRef#SecurityObjGroup. |
| CiscoASA.Rules.SourceSecurity.value | String | The value of the SecurityName or SecurityTag. |
| CiscoASA.Rules.SourceSecurity.objectId | String | The object ID of objectRef#SecurityObjGroup. |
| CiscoASA.Rules.DestinationSecurity.kind | String | The type of the security group; SecurityName, SecurityTag, objectRef#SecurityObjGroup. |
| CiscoASA.Rules.DestinationSecurity.value | String | The value of the SecurityName or SecurityTag |
| CiscoASA.Rules.DestinationSecurity.objectId | String | The object ID of objectRef#SecurityObjGroup. |
| CiscoASA.Rules.User.kind | String | One of AnyUser, NoneUser, objectRef#LocalUserObjGroup, objectRef#UserGroupObj, objectRef#UserObj |
| CiscoASA.Rules.User.value | String | The user value. |
| CiscoASA.Rules.User.objectId | String | The object ID of the user. |
| CiscoASA.Rules.TimeRange.kind | String | The object reference type or the actual TimeRange value. |
| CiscoASA.Rules.TimeRange.value | String | The value of the time range. |
| CiscoASA.Rules.TimeRange.objectId | String | The object ID of the time range. |
Command example
!cisco-asa-list-rules interface_type=Global
Context Example
{
"CiscoASA": {
"Rules": [
{
"Dest": "TEST_GROUP2",
"DestKind": "objectRef#NetworkObjGroup",
"DestService": "ip",
"DestinationSecurity": {
"kind": "SecurityTag",
"value": "71"
},
"ID": "3583139358",
"Interface": null,
"InterfaceType": "Global",
"IsActive": true,
"Permit": false,
"Position": 1,
"Remarks": [],
"Source": "TEST_GROUP1",
"SourceKind": "objectRef#NetworkObjGroup",
"SourceSecurity": {
"kind": "objectRef#SecurityObjGroup",
"objectId": "oneSecurityGroup"
},
"SourceService": "ip",
"TimeRange": {
"kind": "objectRef#TimeRange",
"objectId": "trUserTest"
},
"User": {
"kind": "objectRef#UserObj",
"objectId": "api"
}
},
{
"Dest": "TEST_GROUP2",
"DestKind": "objectRef#NetworkObjGroup",
"DestService": "ip",
"ID": "3194110035",
"Interface": null,
"InterfaceType": "Global",
"IsActive": true,
"Permit": false,
"Position": 2,
"Remarks": [],
"Source": "TEST_GROUP1",
"SourceKind": "objectRef#NetworkObjGroup",
"SourceService": "ip",
"TimeRange": {
"kind": "objectRef#TimeRange",
"objectId": "trUserTest"
},
"User": {
"kind": "objectRef#UserObj",
"objectId": "api"
}
}
]
}
}
Human Readable Output
Rules
ID Source Dest Permit Interface InterfaceType IsActive Position SourceService DestService 3583139358 TEST_GROUP1 TEST_GROUP2 false Global true 1 ip ip 3194110035 TEST_GROUP1 TEST_GROUP2 false Global true 2 ip ip
cisco-asa-backup
Creates a backup of the current settings (i.e., the backup.cfg file).
Base Command
cisco-asa-backup
Input
| Argument Name | Description | Required |
|---|---|---|
| backup_name | The name of the backup. | Required |
| passphrase | The passphrase for the backup. | Optional |
Context Output
There is no context output for this command.
Command example
!cisco-asa-backup backup_name=Lior
Human Readable Output
Created backup successfully in:
Location: disk0:/Lior
Passphrase: None
cisco-asa-get-rule-by-id
Gets a specific rule by rule ID.
Base Command
cisco-asa-get-rule-by-id
Input
| Argument Name | Description | Required |
|---|---|---|
| rule_id | The rule ID. | Required |
| interface_name | The name of the interface. | Optional |
| interface_type | The interface type. Possible values are: In, Out, Global. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoASA.Rules.Interface | String | The name of the interface. |
| CiscoASA.Rules.Source | String | The rule’s source. |
| CiscoASA.Rules.Dest | String | The rule’s destination. |
| CiscoASA.Rules.InterfaceType | String | The interface type. Can be “In”, “Out”, or “Global”. |
| CiscoASA.Rules.IsActive | Boolean | Whether the rule is active. |
| CiscoASA.Rules.Position | Number | The position of the rule. |
| CiscoASA.Rules.ID | String | The rule ID. |
| CiscoASA.Rules.Remarks | Unknown | A list of all rule remarks. |
| CiscoASA.Rules.Permit | Boolean | Whether the rule permits traffic from source to destination. |
| CiscoASA.Rules.DestService | String | The destination service. |
| CiscoASA.Rules.SourceService | String | The source service. |
| CiscoASA.Rules.SourceKind | String | One of AnyIPAddress, IPv4Address, IPv4FQDN, IPv4Network, IPv4Range, IPv6Address, IPv6FQDN, IPv6Network, IPv6Range, SecurityName, SecurityTag, interfaceIP, objectRef#NetworkObj, objectRef#NetworkObjGroup. |
| CiscoASA.Rules.DestKind | String | One of AnyIPAddress, IPv4Address, IPv4FQDN, IPv4Network, IPv4Range, IPv6Address, IPv6FQDN, IPv6Network, IPv6Range, SecurityName, SecurityTag, interfaceIP, objectRef#NetworkObj, objectRef#NetworkObjGroup. |
| CiscoASA.Rules.SourceSecurity.kind | String | The type of the security group; SecurityName, SecurityTag, objectRef#SecurityObjGroup. |
| CiscoASA.Rules.SourceSecurity.value | String | The value of the SecurityName or SecurityTag. |
| CiscoASA.Rules.SourceSecurity.objectId | String | The object ID of objectRef#SecurityObjGroup. |
| CiscoASA.Rules.DestinationSecurity.kind | String | The type of the security group; SecurityName, SecurityTag, objectRef#SecurityObjGroup. |
| CiscoASA.Rules.DestinationSecurity.value | String | The value of the SecurityName or SecurityTag |
| CiscoASA.Rules.DestinationSecurity.objectId | String | The object ID of objectRef#SecurityObjGroup. |
| CiscoASA.Rules.User.kind | String | One of AnyUser, NoneUser, objectRef#LocalUserObjGroup, objectRef#UserGroupObj, objectRef#UserObj |
| CiscoASA.Rules.User.value | String | The user value. |
| CiscoASA.Rules.User.objectId | String | The object ID of the user. |
| CiscoASA.Rules.TimeRange.kind | String | The object reference type or the actual TimeRange value. |
| CiscoASA.Rules.TimeRange.value | String | The value of the time range. |
| CiscoASA.Rules.TimeRange.objectId | String | The object ID of the time range. |
Command example
!cisco-asa-get-rule-by-id interface_type=Global rule_id=3371063501
Context Example
{
"CiscoASA": {
"Rules": {
"Dest": "5.5.5.5",
"DestKind": "IPv4Address",
"DestService": "tcp/citrix-ica",
"DestinationSecurity": {
"kind": "SecurityTag",
"value": "1"
},
"ID": "3371063501",
"Interface": "",
"InterfaceType": "Global",
"IsActive": true,
"Permit": false,
"Position": 30,
"Remarks": [],
"Source": "0.0.0.0/24",
"SourceKind": "IPv4Network",
"SourceSecurity": {
"kind": "SecurityTag",
"value": "2"
},
"SourceService": "tcp/cifs",
"User": {
"kind": "objectRef#UserObj",
"objectId": "api"
}
}
}
}
Human Readable Output
Rule 3371063501
ID Source Dest Permit Interface InterfaceType IsActive Position SourceService DestService 3371063501 0.0.0.0/24 5.5.5.5 false Global true 30 tcp/cifs tcp/citrix-ica
cisco-asa-create-rule
Creates a rule.
Base Command
cisco-asa-create-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| source | The source. Can be the value of an IPv4, an address block, or the name of a network object. | Required |
| destination | The destination. Can be the value of an IPv4, an address block, or the name of a network object. | Required |
| permit | Whether the rule is a permit. If True, the rule is a permit. Possible values are: True, False. | Required |
| remarks | A list of remarks for the rule. | Optional |
| position | The position in which to create the rule. | Optional |
| log_level | The log level of the rule. Possible values are: Default, Emergencies, Alerts, Critical, Errors, Warnings, Notifications, Informational, Debugging. | Optional |
| active | Whether the rule will be active. If True, the rule will be active. Possible values are: True, False. | Optional |
| interface_type | The interface type. Possible values are: In, Out, Global. | Required |
| interface_name | The interface name. | Optional |
| service | The service of the rule. | Optional |
| destination_kind | The destination address kind in the ace. Possible values are: AnyIPAddress, IPv4Address, IPv4FQDN, IPv4Network, IPv4Range, IPv6Address, IPv6FQDN, IPv6Network, IPv6Range, SecurityName, SecurityTag, interfaceIP, NetworkObj, NetworkObjGroup. | Optional |
| source_kind | The source address kind in the ace. Possible values are: AnyIPAddress, IPv4Address, IPv4FQDN, IPv4Network, IPv4Range, IPv6Address, IPv6FQDN, IPv6Network, IPv6Range, SecurityName, SecurityTag, interfaceIP, NetworkObj, NetworkObjGroup. | Optional |
| service_kind | The source service kind. Possible values are: AnyService, ICMP6Service, ICMPService, NetworkProtocol, NetworkServiceGroups, NetworkServiceObjects, TcpUdpService. | Optional |
| destination_service | The destination service value. | Optional |
| destination_service_kind | The destination service kind. Possible values are: AnyService, ICMP6Service, ICMPService, NetworkProtocol, NetworkServiceGroups, NetworkServiceObjects, TcpUdpService. | Optional |
| time_range | Object ID of for the time range object. Can be received with the command cisco-asa-list-time-range. | Optional |
| user | The object ID to the user. Can be one of LocalUserObjGroup, UserGroupObj, UserObj. Can be received with existing commands; cisco-asa-list-local-user-group, cisco-asa-list-local-user, cisco-asa-list-user-object. | Optional |
| user_kind | The type of the user. Possible values are: LocalUserObjGroup, UserGroupObj, UserObj. | Optional |
| source_security | Source security group in the ace. Possible values are SecurityName, SecurityTag and SecurityObjGroup. Can be received with the existing command cisco-asa-list-security-object-group. | Optional |
| source_security_kind | The source security type. Possible values are: SecurityName, SecurityTag, SecurityObjGroup. | Optional |
| destination_security | Destination security group in the ace. Possible values are SecurityName, SecurityTag and SecurityObjGroup. Can be received with the existing command cisco-asa-list-security-object-group. | Optional |
| destination_security_kind | The destination security type. Possible values are: SecurityName, SecurityTag, SecurityObjGroup. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoASA.Rules.Source | String | The rule’s source. |
| CiscoASA.Rules.Dest | String | The rule’s destination. |
| CiscoASA.Rules.InterfaceType | String | The interface type. Can be “In”, “Out”, or “Global”. |
| CiscoASA.Rules.IsActive | Boolean | Whether the rule is active. |
| CiscoASA.Rules.Interface | String | The name of the interface. |
| CiscoASA.Rules.Position | Number | The position of the rule. |
| CiscoASA.Rules.ID | String | The rule ID. |
| CiscoASA.Rules.Remarks | Unknown | A list of all rule remarks. |
| CiscoASA.Rules.Permit | Boolean | Whether the rule permits traffic from source to destination. |
| CiscoASA.Rules.DestService | String | The destination service. |
| CiscoASA.Rules.SourceService | String | The source service. |
| CiscoASA.Rules.SourceKind | String | One of AnyIPAddress, IPv4Address, IPv4FQDN, IPv4Network, IPv4Range, IPv6Address, IPv6FQDN, IPv6Network, IPv6Range, SecurityName, SecurityTag, interfaceIP, objectRef#NetworkObj, objectRef#NetworkObjGroup. |
| CiscoASA.Rules.DestKind | String | One of AnyIPAddress, IPv4Address, IPv4FQDN, IPv4Network, IPv4Range, IPv6Address, IPv6FQDN, IPv6Network, IPv6Range, SecurityName, SecurityTag, interfaceIP, objectRef#NetworkObj, objectRef#NetworkObjGroup. |
| CiscoASA.Rules.SourceSecurity.kind | String | The type of the security group; SecurityName, SecurityTag, objectRef#SecurityObjGroup. |
| CiscoASA.Rules.SourceSecurity.value | String | The value of the SecurityName or SecurityTag |
| CiscoASA.Rules.SourceSecurity.objectId | String | The object ID of objectRef#SecurityObjGroup. |
| CiscoASA.Rules.DestinationSecurity.kind | String | The type of the security group; SecurityName, SecurityTag, objectRef#SecurityObjGroup. |
| CiscoASA.Rules.DestinationSecurity.value | String | The value of the SecurityName or SecurityTag |
| CiscoASA.Rules.DestinationSecurity.objectId | String | The object ID of objectRef#SecurityObjGroup. |
| CiscoASA.Rules.User.kind | String | One of AnyUser, NoneUser, objectRef#LocalUserObjGroup, objectRef#UserGroupObj, objectRef#UserObj |
| CiscoASA.Rules.User.value | String | The user value. |
| CiscoASA.Rules.User.objectId | String | The object ID of the user. |
| CiscoASA.Rules.TimeRange.kind | String | The object reference type or the actual TimeRange value. |
| CiscoASA.Rules.TimeRange.value | String | The value of the time range. |
| CiscoASA.Rules.TimeRange.objectId | String | The object ID of the time range. |
Command example
!cisco-asa-create-rule destination=1.1.1.1 source=0.0.0.0/24 interface_type=Global permit=False destination_kind=IPv4Address source_kind=IPv4Network active=False service_kind=TcpUdpService service=tcp/cifs destination_service=tcp/citrix-ica destination_service_kind=TcpUdpService destination_security_kind=SecurityTag destination_security=1 source_security_kind=SecurityTag source_security=2 timerange=trUserTest user_kind=UserObj user=api
Context Example
{
"CiscoASA": {
"Rules": {
"Dest": "1.1.1.1",
"DestKind": "IPv4Address",
"DestService": "tcp/citrix-ica",
"DestinationSecurity": {
"kind": "SecurityTag",
"value": "1"
},
"ID": "3152305802",
"Interface": "",
"InterfaceType": "Global",
"IsActive": false,
"Permit": false,
"Position": 37,
"Remarks": [],
"Source": "0.0.0.0/24",
"SourceKind": "IPv4Network",
"SourceSecurity": {
"kind": "SecurityTag",
"value": "2"
},
"SourceService": "tcp/cifs",
"User": {
"kind": "objectRef#UserObj",
"objectId": "api"
}
}
}
}
Human Readable Output
Created new rule. ID: 3152305802
ID Source Dest Permit Interface InterfaceType IsActive Position SourceService DestService 3152305802 0.0.0.0/24 1.1.1.1 false Global false 37 tcp/cifs tcp/citrix-ica
cisco-asa-delete-rule
Deletes a rule.
Base Command
cisco-asa-delete-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| rule_id | The rule ID. | Required |
| interface_name | The name of the interface. | Optional |
| interface_type | The interface type. Possible values are: In, Out, Global. | Required |
Context Output
There is no context output for this command.
Command example
!cisco-asa-delete-rule rule_id=2152246838 interface_type=Global
Human Readable Output
Rule 2152246838 deleted successfully.
cisco-asa-edit-rule
Updates an existing rule.
Base Command
cisco-asa-edit-rule
Input
| Argument Name | Description | Required |
|---|---|---|
| interface_type | The interface type. Possible values are: In, Out, Global. | Required |
| interface_name | The interface name. | Optional |
| rule_id | The rule ID. | Required |
| active | Whether the rule will be active. If True, will be active. Possible values are: True, False. | Optional |
| log_level | The log level of the rule. | Optional |
| position | The position the rule will be in. . | Optional |
| remarks | A list of remarks for the rule. | Optional |
| permit | True if the rule is a permit. Possible values are: True, False. | Optional |
| destination | The destination. Can be the value of an IPv4, an address block, or the name of a network object. | Optional |
| source | The source. Can be the value of an IPv4, an address block, or the name of a network object. | Optional |
| service | The service of the rule. | Optional |
| destination_kind | The destination address kind in the ace. Possible values are: AnyIPAddress, IPv4Address, IPv4FQDN, IPv4Network, IPv4Range, IPv6Address, IPv6FQDN, IPv6Network, IPv6Range, SecurityName, SecurityTag, interfaceIP, NetworkObj, NetworkObjGroup. | Optional |
| source_kind | The source address kind in the ace. Possible values are: AnyIPAddress, IPv4Address, IPv4FQDN, IPv4Network, IPv4Range, IPv6Address, IPv6FQDN, IPv6Network, IPv6Range, SecurityName, SecurityTag, interfaceIP, NetworkObj, NetworkObjGroup. | Optional |
| service_kind | The source service kind. Possible values are: AnyService, ICMP6Service, ICMPService, NetworkProtocol, NetworkServiceGroups, NetworkServiceObjects, TcpUdpService. | Optional |
| destination_service | The destination service value. | Optional |
| destination_service_kind | The destination service kind. Possible values are: AnyService, ICMP6Service, ICMPService, NetworkProtocol, NetworkServiceGroups, NetworkServiceObjects, TcpUdpService. | Optional |
| time_range | Object ID of for the time range object. Can be received with the command cisco-asa-list-time-range. | Optional |
| user | The object ID to the user. Can be one of LocalUserObjGroup, UserGroupObj, UserObj. Can be received with existing commands; cisco-asa-list-local-user-group, cisco-asa-list-local-user, cisco-asa-list-user-object. | Optional |
| user_kind | The type of the user. Possible values are: LocalUserObjGroup, UserGroupObj, UserObj. | Optional |
| source_security | Source security group in the ace. Possible values are SecurityName, SecurityTag and SecurityObjGroup. Can be received with the existing command cisco-asa-list-security-object-group. | Optional |
| source_security_kind | The source security type. Possible values are: SecurityName, SecurityTag, SecurityObjGroup. | Optional |
| destination_security | Destination security group in the ace. Possible values are SecurityName, SecurityTag and SecurityObjGroup. Can be received with the existing command cisco-asa-list-security-object-group. | Optional |
| destination_security_kind | The destination security type. Possible values are: SecurityName, SecurityTag, SecurityObjGroup. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoASA.Rules.Source | String | The rule’s source. |
| CiscoASA.Rules.Dest | String | The rule’s destination. |
| CiscoASA.Rules.InterfaceType | String | The interface type. Can be “In”, “Out”, or “Global”. |
| CiscoASA.Rules.IsActive | Boolean | Whether the rule is active. |
| CiscoASA.Rules.Interface | String | The name of the interface. |
| CiscoASA.Rules.Position | Number | The position of the rule. |
| CiscoASA.Rules.ID | String | The rule ID. |
| CiscoASA.Rules.Remarks | Unknown | A list of all rule remarks. |
| CiscoASA.Rules.Permit | Boolean | Whether the rule permits traffic from source to destination. |
| CiscoASA.Rules.DestService | String | The destination service. |
| CiscoASA.Rules.SourceService | String | The source service. |
| CiscoASA.Rules.SourceKind | String | One of AnyIPAddress, IPv4Address, IPv4FQDN, IPv4Network, IPv4Range, IPv6Address, IPv6FQDN, IPv6Network, IPv6Range, SecurityName, SecurityTag, interfaceIP, objectRef#NetworkObj, objectRef#NetworkObjGroup. |
| CiscoASA.Rules.DestKind | String | One of AnyIPAddress, IPv4Address, IPv4FQDN, IPv4Network, IPv4Range, IPv6Address, IPv6FQDN, IPv6Network, IPv6Range, SecurityName, SecurityTag, interfaceIP, objectRef#NetworkObj, objectRef#NetworkObjGroup. |
| CiscoASA.Rules.SourceSecurity.kind | String | The type of the security group; SecurityName, SecurityTag, objectRef#SecurityObjGroup. |
| CiscoASA.Rules.SourceSecurity.value | String | The value of the SecurityName or SecurityTag |
| CiscoASA.Rules.SourceSecurity.objectId | String | The object ID of objectRef#SecurityObjGroup. |
| CiscoASA.Rules.DestinationSecurity.kind | String | The type of the security group; SecurityName, SecurityTag, objectRef#SecurityObjGroup. |
| CiscoASA.Rules.DestinationSecurity.value | String | The value of the SecurityName or SecurityTag |
| CiscoASA.Rules.DestinationSecurity.objectId | String | The object ID of objectRef#SecurityObjGroup. |
| CiscoASA.Rules.User.kind | String | One of AnyUser, NoneUser, objectRef#LocalUserObjGroup, objectRef#UserGroupObj, objectRef#UserObj |
| CiscoASA.Rules.User.value | String | The user value. |
| CiscoASA.Rules.User.objectId | String | The object ID of the user. |
| CiscoASA.Rules.TimeRange.kind | String | The object reference type or the actual TimeRange value. |
| CiscoASA.Rules.TimeRange.value | String | The value of the time range. |
| CiscoASA.Rules.TimeRange.objectId | String | The object ID of the time range. |
Command example
!cisco-asa-edit-rule rule_id=3371063501 interface_type=Global active=True
Context Example
{
"CiscoASA": {
"Rules": {
"Dest": "5.5.5.5",
"DestKind": "IPv4Address",
"DestService": "tcp/citrix-ica",
"DestinationSecurity": {
"kind": "SecurityTag",
"value": "1"
},
"ID": "3371063501",
"Interface": "",
"InterfaceType": "Global",
"IsActive": true,
"Permit": false,
"Position": 30,
"Remarks": [],
"Source": "0.0.0.0/24",
"SourceKind": "IPv4Network",
"SourceSecurity": {
"kind": "SecurityTag",
"value": "2"
},
"SourceService": "tcp/cifs",
"User": {
"kind": "objectRef#UserObj",
"objectId": "api"
}
}
}
}
Human Readable Output
Edited rule 3371063501
ID Source Dest Permit Interface InterfaceType IsActive Position SourceService DestService 3371063501 0.0.0.0/24 5.5.5.5 false Global true 30 tcp/cifs tcp/citrix-ica
cisco-asa-list-network-objects
Gets a list all configured network objects.
Base Command
cisco-asa-list-network-objects
Input
| Argument Name | Description | Required |
|---|---|---|
| object_name | A comma-separated list of network object names for which to get the network. | Optional |
| object_id | A comma-separated list of object IDs for which to get the network object. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoASA.NetworkObject.ID | String | The ID of the network object. |
| CiscoASA.NetworkObject.Host | String | The host information of the network object. |
| CiscoASA.NetworkObject.Description | String | A description of the network object. |
| CiscoASA.NetworkObject.Name | String | The name of the network object. |
Command example
!cisco-asa-list-network-objects object_name=Test_Lior
Context Example
{
"CiscoASA": {
"NetworkObject": {
"Host": {
"kind": "IPv4Address",
"value": "0.0.0.0"
},
"ID": "Test_Lior",
"Name": "Test_Lior"
}
}
}
Human Readable Output
Network Objects
ID Name Host Description Test_Lior Test_Lior kind: IPv4Address
value: 0.0.0.0
cisco-asa-create-network-object
Creates a network object.
Base Command
cisco-asa-create-network-object
Input
| Argument Name | Description | Required |
|---|---|---|
| object_type | The type of network object to create. Possible values are: IPv4, IP-Network. | Required |
| object_name | The name of the object to create. | Required |
| object_value | The value of the network object to create. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoASA.NetworkObject.ID | String | The ID of the network object. |
| CiscoASA.NetworkObject.Host | String | The host information of the network object. |
| CiscoASA.NetworkObject.Description | String | A description of the network object, if exists. |
| CiscoASA.NetworkObject.Name | String | The name of the network object. |
Command example
!cisco-asa-create-network-object object_name=HelloThereLiorSB object_type=IPv4 object_value=1.1.1.1
Context Example
{
"CiscoASA": {
"NetworkObject": {
"Host": {
"kind": "IPv4Address",
"value": "1.1.1.1"
},
"ID": "HelloThereLiorSB",
"Name": "HelloThereLiorSB"
}
}
}
Human Readable Output
Network Objects
ID Name Host Description HelloThereLiorSB HelloThereLiorSB kind: IPv4Address
value: 1.1.1.1
cisco-asa-list-interfaces
Gets a list of all interfaces.
Base Command
cisco-asa-list-interfaces
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| CiscoASA.Interface.ID | String | The interface ID. |
| CiscoASA.Interface.Name | String | The interface name. |
| CiscoASA.Interface.Type | String | The type of interface. |
Command example
#### Context Example
```json
{
"CiscoASA": {
"Interface": [
{
"ID": "-1",
"Name": null,
"Type": "Global"
},
{
"ID": "GigabitEthernet0_API_SLASH_0",
"Name": "outside",
"Type": "In"
},
{
"ID": "Management0_API_SLASH_0",
"Name": "inside",
"Type": "Out"
}
]
}
}
Human Readable Output
Interfaces
Type ID Name Global -1 In GigabitEthernet0_API_SLASH_0 outside Out Management0_API_SLASH_0 inside
Configuration parameters
server— Server URL (e.g. https://192.168.0.1) (required)credentials— Credentials (required)proxy— Use system proxy settingsinsecure— Trust any certificate (not secure)isASAv— Is ASAv
Commands (16)
-
cisco-asa-backupCreates a backup of the current settings (i.e., the backup.cfg file).
-
cisco-asa-create-network-objectCreates a network object.
-
cisco-asa-create-ruleCreates a rule.
-
cisco-asa-delete-ruleDeletes a rule.
-
cisco-asa-edit-ruleUpdates an existing rule.
-
cisco-asa-get-rule-by-idGets a specific rule by rule ID.
-
cisco-asa-list-interfacesGets a list of all interfaces.
-
cisco-asa-list-local-userRetrieve information about individual local user accounts within a network system. These local users can be part of local user groups and groups imported from Active Directory.
-
cisco-asa-list-local-user-groupRetrieve information about local user groups, which are collections of user accounts, either from the local database or imported from Active Directory, that manage access to network resources not defined globally.
-
cisco-asa-list-network-object-groupRetrieve information about network object groups. Network object groups can contain multiple network objects as well as inline networks or hosts. Network object groups can include a mix of both IPv4 and IPv6 addresses/network.
-
cisco-asa-list-network-objectsGets a list all configured network objects.
-
cisco-asa-list-rulesGets a list all rules for the supplied interface.
-
cisco-asa-list-security-object-groupRetrieve information about security groups, which are collections of security groups or identifiers that manage access and permissions to network resources. These groups can be used in features like Cisco TrustSec and are often part of extended access control lists, enabling centralized and localized security policy management.
-
cisco-asa-list-time-rangeRetrieve information about time range objects. A time range object defines a specific time consisting of a start time, an end time, and optional recurring entries. You use these objects on ACL rules to provide time-based access to certain features or assets. For example, you could create an access rule that allows access to a particular server during working hours only.
-
cisco-asa-list-user-objectRetrieve information about user definitions within the system. This helps in managing and configuring user access and permissions in a network security context.
-
cisco-asa-write-memorySaves the running configuration to the default location for the startup configuration.
import traceback from collections.abc import Callable from copy import deepcopy from functools import wraps from http import HTTPStatus from typing import Any import demistomock as demisto # noqa: F401 import urllib3 from CommonServerPython import * # noqa: F401 from requests import Response from CommonServerUserPython import * # Disable insecure warnings urllib3.disable_warnings() """ GLOBAL VARIABLES""" API_LIMIT = 100 INTEGRATION_COMMAND = "cisco-asa" OBJECT_TYPES_DICT = {"IPv4": "IPv4Address", "IP-Network": "IPv4Network"} DEFAULT_LIMIT = 50 DEFAULT_KEYS_MAPPING = { "objectId": "object_id", "name": "name", "description": "description", "members": { "_include": True, "kind": "kind", "objectId": "object_id", "value": "value", }, } """PAGINATION DECORATOR """ class Pagination: """ Pagination decorator wrapper to control functionality within the decorator. Args: api_limit (int): Maximum number of items that can be returned from the API request. items_key_path (list[str], optional): A list of keys to the items within an API response. Defaults to None. start_count_from_zero (bool | None): Whether the count of the first item is 0 or 1. Defaults to True. default_limit (int): The number of default items to return with an API request. Defaults to DEFAULT_LIMIT. Returns: Callable: Pagination decorator. """ def __init__( self, api_limit: int, items_key_path: list[str] | None = None, start_count_from_zero: bool = True, default_limit: int = DEFAULT_LIMIT, ) -> None: self.api_limit = api_limit self.items_key_path = items_key_path self.start_count_from_zero = start_count_from_zero self.default_limit = default_limit def __call__(self, func: Callable) -> Callable: """ The __call__ method takes a function and returns a wrapped function that handles the pagination logic. Args: func (Callable): The function to be wrapped with pagination. Returns: Callable: The wrapped function with added pagination functionality. """ @wraps(func) def wrapper( client_instance: BaseClient, page: int | None, page_size: int | None, limit: int = DEFAULT_LIMIT, *args, **kwargs, ) -> tuple[list | dict, list | dict]: """ The wrapper function handles the pagination logic before calling the original function. Args: client_instance (BaseClient): The instance of the Client class used to call the API request function. page (int | None): Page number to return. page_size (int | None): Number of items to return in a page. *args: Positional arguments to be passed to the original function. **kwargs: Keyword arguments to be passed to the original function. Returns: tuple[list | dict, list | dict]: All the items combined within raw response, All the raw responses combined. """ remaining_items, offset = self._get_pagination_arguments(page=page, page_size=page_size, limit=limit) return self._handle_pagination( client_instance, func, remaining_items, offset, *args, **kwargs, ) return wrapper def _get_pagination_arguments( self, page: int | None, page_size: int | None, limit: int = DEFAULT_LIMIT ) -> tuple[int, int | None]: """ Determine if pagination is automatic or manual and compute remaining items and offset values. Args: page (int | None): Page number to return. page_size (int | None): Number of items to return in a page. Returns: tuple[bool, int, int | None]: remaining_items: The number of remaining items to fetch. offset: The offset for the next API request. """ is_manual = page is not None if is_manual: page = page or 1 page_size = page_size or self.default_limit remaining_items = page_size offset = (page - 1) * page_size + (0 if self.start_count_from_zero else 1) else: remaining_items = page_size or limit offset = None return remaining_items, offset def _handle_pagination( self, client_instance: BaseClient, func: Callable, remaining_items: int, offset: int | None, *args, **kwargs, ) -> tuple[list | dict, list | dict]: """ Handle pagination when the API supports both limit and offset parameters. Args: client_instance (BaseClient): The instance of the Client class used to call the API request function. func (Callable): API request function to be called. remaining_items (int): The number of remaining items to fetch. offset (int | None): The offset for the next API request. args: Positional arguments to be passed to the API request function. kwarg: Keyword arguments to be passed to the API request function. Returns: tuple[list | dict, list | dict]: All the items combined within raw response, All the raw responses combined """ kwargs["self"] = client_instance raw_items: list[dict[str, Any]] = [] raw_responses: list[dict[str, Any]] = [] # Keep calling the API until the required amount of items have been met. while remaining_items > 0: limit = min(remaining_items, self.api_limit) kwargs |= { "limit": limit, "offset": offset, } raw_response = func( *args, **kwargs, ) raw_item = raw_response if self.items_key_path: raw_item = dict_safe_get(raw_item, self.items_key_path) if raw_item is None: break raw_responses.append(raw_response) raw_items += raw_item if (received_items := len(raw_item)) < limit: break # Calculate the offset and limit for the next run. remaining_items -= received_items offset = (offset or 0) + received_items return raw_items, raw_responses """Client""" class Client(BaseClient): isASAv = False auth_token = "" def login(self, isASAv) -> None: """ Receive an auth token from the headers after a basic authentication has been made. Args: isASAv (bool): Whether Cisco Adaptive Security Virtual Appliance is in use. """ if isASAv: self.isASAv = True res = self._http_request("POST", "/api/tokenservices", resp_type="response") auth_token = res.headers._store.get("x-auth-token")[1] self._headers["X-Auth-Token"] = auth_token self.auth_token = auth_token def logoff(self): """ Delete the generated auth token. """ try: if self.isASAv and self.auth_token: self._http_request("DELETE", f"/api/tokenservices/{self.auth_token}", resp_type="response") except Exception as e: # if failed to logoof just write to log. no need to raise error demisto.debug(f"Logoff error: {e!s}") def get_all_rules(self, specific_interface: str | None = None, rule_type: str = "All") -> list: """ Gets a list all rules for the supplied interface. Args: specific_interface): the name of the interface rule_type: All/Global/In Returns: all rules in Cisco ASA of the specified type/interface """ rules = [] # type: list # Get global rules if specific_interface is None and rule_type in ["All", "Global"]: res = self._http_request("GET", "/api/access/global/rules") items = res.get("items", []) for item in items: item["interface_type"] = "Global" rules.extend(items) # Get in rules if rule_type in ["All", "In"]: res = self._http_request("GET", "/api/access/in") interfaces = [] for item in res.get("items", []): interface_name = item.get("interface", {}).get("name") if interface_name and specific_interface and specific_interface == interface_name: interfaces.append(interface_name) if interface_name and not specific_interface: interfaces.append(interface_name) for interface in interfaces: res = self._http_request("GET", f"/api/access/in/{interface}/rules") items = res.get("items", []) for item in items: item["interface"] = interface item["interface_type"] = "In" rules.extend(items) # Get out rules if rule_type in ["All", "Out"]: res = self._http_request("GET", "/api/access/out") interfaces = [] for item in res.get("items", []): interface_name = item.get("interface", {}).get("name") if interface_name and specific_interface and specific_interface == interface_name: interfaces.append(interface_name) if interface_name and not specific_interface: interfaces.append(interface_name) for interface in interfaces: res = self._http_request("GET", f"/api/access/out/{interface}/rules") items = res.get("items", []) for item in items: item["interface"] = interface item["interface_type"] = "Out" rules.extend(items) return rules def rule_action( self, rule_id: str, interface_name: str, interface_type: str, command: str = "GET", data: dict = None ) -> dict: """ Get, update or delete a rule. Args: rule_id: The Rule ID. interface_name: the name of the interface. interface_type: The type of interface. command: The operation to do on the rule. data: The data of the rule to update. Returns: Does the command on the rule. Delete - delete rule GET - rule info PATCH - edit rule """ rule = {} resp_type = {"GET": "json", "DELETE": "text", "PATCH": "response"} if interface_type == "Global": rule = self._http_request( command, f"/api/access/global/rules/{rule_id}", resp_type=resp_type[command], json_data=data ) if interface_type == "In": rule = self._http_request( command, f"/api/access/in/{interface_name}/rules/{rule_id}", resp_type=resp_type[command], json_data=data ) if interface_type == "Out": rule = self._http_request( command, f"/api/access/out/{interface_name}/rules/{rule_id}", resp_type=resp_type[command], json_data=data ) if command == "GET": rule["interface"] = interface_name rule["interface_type"] = interface_type return rule def create_rule(self, interface_type: str, interface_name: str, rule_body: dict) -> dict: """ Create a rule. Args: interface_type: The interface type of the rule, can be one of: Global/In/Out. interface_name: The name of the provided interface, applies to In/Out interface types. rule_body: The information about the rule. Returns: The new created rule's information. """ res = Response() if interface_type == "Global": res = self._http_request("POST", "/api/access/global/rules", json_data=rule_body, resp_type="response") if interface_type == "In": res = self._http_request("POST", f"/api/access/in/{interface_name}/rules", json_data=rule_body, resp_type="response") if interface_type == "Out": res = self._http_request("POST", f"/api/access/out/{interface_name}/rules", json_data=rule_body, resp_type="response") loc = res.headers.get("Location", "") rule = self._http_request("GET", loc[loc.find("/api") :]) rule["interface"] = interface_name rule["interface_type"] = interface_type return rule def test_command(self): """ A command to test the connection to the Cisco ASA server. """ self._http_request("GET", "/api/aaa/authorization") def backup(self, data: dict): """ Creates a backup of the current settings (i.e., the backup.cfg file). Args: data (dict): The backup name and passphrase. """ self._http_request("POST", "/api/backup", json_data=data, resp_type="response") def restore(self, data: dict): """ Restore a backup. Currently this command isn't in use through XSOAR. Args: data (dict): The backup name and passphrase. """ self._http_request("POST", "/api/restore", json_data=data, resp_type="response") def get_network_obejcts(self): """ Gets a list of all the configured network objects. """ obj_res = self._http_request("GET", "/api/objects/networkobjects") return obj_res.get("items", []) def create_object(self, obj_name, obj_type, obj_value): """ Creates a network object. Args: obj_name (str): The name of the network object. obj_type (str): The kind of the network object. obj_value (_type_): The value of the network object. Returns: Whether the network object was created successfully. """ data = { "kind": "object#NetworkObj", "name": obj_name, "host": {"kind": OBJECT_TYPES_DICT.get(obj_type), "value": obj_value}, } try: return self._http_request( "POST", "/api/objects/networkobjects", json_data=data, ok_codes=(200, 201, 204), resp_type="response" ) except Exception: raise def list_interfaces(self): """ Returns a list of interfaces. """ interfaces = [] # type: ignore for type in ["global", "in", "out"]: resp = self._http_request("GET", f"/api/access/{type}") interfaces.extend(resp.get("items", [])) return interfaces @Pagination(api_limit=API_LIMIT, items_key_path=["items"]) def list_network_object_group(self, limit: int = DEFAULT_LIMIT, offset: int = None) -> dict[str, Any]: """ This command is decorated by Pagination class, therefore the arguments that must be passed to it are: page, page_size and limit. Retrieves information about network object groups. Args: limit (int, optional): The number of results to return. Defaults to None. offset (int, optional): The offset from where to start returning results. Defaults to None. Returns: dict[str, Any]: Information about network object groups. """ return self._http_request( method="GET", url_suffix="api/objects/networkobjectgroups", params=assign_params(limit=limit, offset=offset), ) def get_network_object_group(self, object_id: str) -> dict[str, Any]: """ Retrieve information about a network object group. Args: object_id (str): The object ID of the network group to retrieve Returns: dict[str, Any]: Information about a network object group. """ return self._http_request( method="GET", url_suffix=f"api/objects/networkobjectgroups/{object_id}", ) @Pagination(api_limit=API_LIMIT, items_key_path=["items"]) def list_local_user_group(self, limit: int = DEFAULT_LIMIT, offset: int = None) -> dict[str, Any]: """ This command is decorated by Pagination class, therefore the arguments that must be passed to it are: page, page_size and limit. Retrieves information about local user groups. Args: limit (int, optional): The number of results to return. Defaults to None. offset (int, optional): The offset from where to start returning results. Defaults to None. Returns: dict[str, Any]: Information about local user groups. """ return self._http_request( "GET", "api/objects/localusergroups", params=assign_params(limit=limit, offset=offset), ) def get_local_user_group(self, object_id: str) -> dict[str, Any]: """ Retrieve information about a local user group. Args: object_id (str): The object ID of the local user group to retrieve Returns: dict[str, Any]: Information about the local user group. """ return self._http_request( method="GET", url_suffix=f"api/objects/localusergroups/{object_id}", ) @Pagination(api_limit=API_LIMIT, items_key_path=["items"]) def list_local_user(self, limit: int = DEFAULT_LIMIT, offset: int = None) -> dict[str, Any]: """ This command is decorated by Pagination class, therefore the arguments that must be passed to it are: page, page_size and limit. Retrieves information about local users. Args: limit (int, optional): The number of results to return. Defaults to None. offset (int, optional): The offset from where to start returning results. Defaults to None. Returns: dict[str, Any]: Information about local users. """ return self._http_request( method="GET", url_suffix="api/objects/localusers", params=assign_params(limit=limit, offset=offset), ) def get_local_user(self, object_id: str) -> dict[str, Any]: """ Retrieve information about a local user. Args: object_id (str): The object ID of the local user to retrieve Returns: dict[str, Any]: Information about the local user. """ return self._http_request( method="GET", url_suffix=f"api/objects/localusers/{object_id}", ) @Pagination(api_limit=API_LIMIT, items_key_path=["items"]) def list_time_range(self, limit: int = DEFAULT_LIMIT, offset: int = None) -> dict[str, Any]: """ This command is decorated by Pagination class, therefore the arguments that must be passed to it are: page, page_size and limit. Retrieves information about time ranges. Args: limit (int, optional): The number of results to return. Defaults to None. offset (int, optional): The offset from where to start returning results. Defaults to None. Returns: dict[str, Any]: Information about time ranges. """ return self._http_request( method="GET", url_suffix="api/objects/timeranges", params=assign_params(limit=limit, offset=offset), ) def get_time_range(self, object_id: str) -> dict[str, Any]: """ Retrieve information about a time range. Args: object_id (str): The object ID of the time range to retrieve Returns: dict[str, Any]: Information about the time range. """ return self._http_request( method="GET", url_suffix=f"api/objects/timeranges/{object_id}", ) @Pagination(api_limit=API_LIMIT, items_key_path=["items"]) def list_security_object_group(self, limit: int = DEFAULT_LIMIT, offset: int = None) -> dict[str, Any]: """ This command is decorated by Pagination class, therefore the arguments that must be passed to it are: page, page_size and limit. Retrieves information about security object groups. Args: limit (int, optional): The number of results to return. Defaults to None. offset (int, optional): The offset from where to start returning results. Defaults to None. Returns: dict[str, Any]: Information about security object groups. """ return self._http_request( method="GET", url_suffix="api/objects/securityobjectgroups", params=assign_params(limit=limit, offset=offset), ) def get_security_object_group(self, object_id: str) -> dict[str, Any]: """ Retrieve information about a security object group. Args: object_id (str): The object ID of the security object group to retrieve Returns: dict[str, Any]: Information about the security object group. """ return self._http_request( method="GET", url_suffix=f"api/objects/securityobjectgroups/{object_id}", ) @Pagination(api_limit=API_LIMIT, items_key_path=["items"]) def list_user_object(self, limit: int = DEFAULT_LIMIT, offset: int = None) -> dict[str, Any]: """ This command is decorated by Pagination class, therefore the arguments that must be passed to it are: page, page_size and limit. Retrieves information about user objects. Args: limit (int, optional): The number of results to return. Defaults to None. offset (int, optional): The offset from where to start returning results. Defaults to None. Returns: dict[str, Any]: Information about user objects. """ return self._http_request( method="GET", url_suffix="api/objects/userobjects", params=assign_params(limit=limit, offset=offset), ) def get_user_object(self, object_id: str) -> dict[str, Any]: """ Retrieve information about a user object. Args: object_id (str): The object ID of the user object to retrieve Returns: dict[str, Any]: Information about the user object. """ return self._http_request( method="GET", url_suffix=f"api/objects/userobjects/{object_id}", ) def write_memory(self) -> dict[str, Any]: """ The write memory command saves the running configuration to the default location for the startup configuration. Returns: dict[str, Any]: shows a successful 'writemem' command execution on a Cisco ASA device, building the configuration and generating a cryptochecksum for integrity. The process is completed with an "[OK]" message. """ return self._http_request( method="POST", url_suffix="api/commands/writemem", headers=self._headers | {"Content-Type": "application/json"} ) """HELPER COMMANDS""" @logger def set_up_ip_kind(dict_body: dict, field_to_add: str, data: str) -> None: """ Takes the data, checks what kind of source/dest it is (IP, network, any or network object) and inserts to the dict the field_to_add as key and the source/dest as value in the correct format. Args: dict_body: The dict to add the data to. field_to_add: the name of the field to add to json. data: the string to check its kind and insert to dict. """ if is_ip_valid(data): dict_body[field_to_add] = {"kind": "IPv4Address", "value": data} elif data == "any": dict_body[field_to_add] = {"kind": "AnyIPAddress", "value": "any4"} elif "/" in data: dict_body[field_to_add] = {"kind": "IPv4Network", "value": data} else: dict_body[field_to_add] = {"kind": "objectRef#NetworkObj", "objectId": data} @logger def raw_to_rules(raw_rules): """ :param raw_rules: :return: Gets raw rules as received from API and extracts only the relevant fields """ rules = [] for rule in raw_rules: source_services = rule.get("sourceService", {}) if isinstance(source_services, list): source_services_list = [v["value"] for v in source_services] else: source_services_list = source_services.get("value") dest_services = rule.get("destinationService", {}) if isinstance(dest_services, list): dest_services_list = [v["value"] for v in dest_services] else: dest_services_list = dest_services.get("value") rule_object_mapping: dict = remove_empty_elements( { new_object_key: { "kind": dict_safe_get(rule, [object_key, "kind"]), "value": dict_safe_get(rule, [object_key, "value"]), "objectId": dict_safe_get(rule, [object_key, "objectId"]), } for new_object_key, object_key in [ ("SourceSecurity", "srcSecurity"), ("DestinationSecurity", "dstSecurity"), ("User", "user"), ("TimeRange", "timeRange"), ] } ) rules.append( { "Source": safe_get_all_values(obj=rule.get("sourceAddress"), key="value"), "SourceService": source_services_list, "Dest": safe_get_all_values(obj=rule.get("destinationAddress"), key="value"), "DestService": dest_services_list, "IsActive": rule.get("active"), "Interface": rule.get("interface"), "InterfaceType": rule.get("interface_type"), "Remarks": rule.get("remarks"), "Position": rule.get("position"), "ID": rule.get("objectId"), "Permit": rule.get("permit"), "SourceKind": dict_safe_get(rule, ["sourceAddress", "kind"]), "DestKind": dict_safe_get(rule, ["destinationAddress", "kind"]), } | rule_object_mapping ) if not rules[-1].get("Source"): rules[-1]["Source"] = safe_get_all_values(obj=rule.get("sourceAddress"), key="objectId") if not rules[-1].get("Dest"): rules[-1]["Dest"] = safe_get_all_values(obj=rule.get("destinationAddress"), key="objectId") return rules @logger def is_get_request_type(get_args: list, list_args: list) -> bool: """ Determine whether the request arguments are for a GET or LIST request. Args: get_args (list): GET request arguments. list_args (list): LIST request arguments. Raises: ValueError: In case the user has entered both GET and LIST arguments, raise an error. Returns: bool: True if the arguments are for a GET request, False otherwise. """ is_get_request = any(get_args) is_list_request = any(list_args) if is_get_request and is_list_request: raise ValueError("GET and LIST arguments can not be supported simultaneously.") return is_get_request @logger def extract_data(obj: list[dict | list] | dict[str, Any], keys_mapping: dict[str, Any]) -> list[dict | list] | dict[str, Any]: """ Extract specific keys from a nested dictionary or a list of dictionaries based on the provided keys_mapping structure. Args: obj (list[dict | list] | dict[str, Any]): The input object, either a dictionary or a list of dictionaries. keys_mapping (dict[str, Any]): A dictionary specifying the mapping of keys to extract and their new names. Returns: list[dict | list] | dict[str, Any]: The extracted object, either a dictionary or a list of dictionaries. """ if isinstance(obj, list): return [extract_data(nested_obj, keys_mapping) for nested_obj in obj] return extract_data_from_dict(obj, keys_mapping) @logger def extract_data_from_dict(dict_obj: dict[str, Any], keys_mapping: dict[str, Any]) -> dict[str, Any]: """ Extract specific keys from a dictionary based on the provided keys_mapping structure. Args: dict_obj (dict[str, Any]): The input dictionary to extract keys from. keys_mapping (dict[str, Any]): A dictionary specifying the mapping of keys to extract and their new names. The keys of this dictionary should correspond to keys in the dict_obj. The values can be either: - a string: the corresponding key in the output dictionary will have the same name. - a nested dictionary: the key-value pairs in the nested dictionary will be extracted recursively. Returns: dict[str, Any]: The extracted dictionary. """ extracted: dict[str, Any] = {} for key, new_key in keys_mapping.items(): if isinstance(new_key, dict) and (nested_obj := dict_obj.get(key)) is not None: nested_keys_mapping = deepcopy(new_key) include_key = nested_keys_mapping.pop("_include", True) extracted_data = extract_data(nested_obj, nested_keys_mapping) extracted |= {key: extracted_data} if include_key else extracted_data elif (value := dict_obj.get(key)) is not None: extracted[new_key] = value return extracted def arg_to_optional_bool(arg: Any | None) -> bool | None: """ Wrapper to argToBoolean function that will allow Optional arguments. Args: arg (Optional[Any]): The value to evaluate. Defaults to None. Returns: Optional[bool]: a boolean representation of 'arg' or None. """ return argToBoolean(arg) if arg is not None else None def setup_address( rule_body: dict[str, Any], address_direction: str, address_value: str, address_kind: str, ) -> None: """ Sets up the source or destination address in the rule_body. Args: rule_body (dict[str, Any]): The rule body to set up the address. address_direction (str): 'sourceAddress' or 'destinationAddress'. address_value (str): The value of the address. address_kind (str): The kind of the address. """ if address_kind in ["NetworkObj", "NetworkObjGroup"]: key = "objectId" address_kind = f"objectRef#{address_kind}" else: key = "value" rule_body[address_direction] = {"kind": address_kind, key: address_value} def handle_address_in_rule( rule_body: dict[str, Any], direction: str, address_value: str = None, address_kind: str = None, ) -> None: """ Handles the address kind and value in the rule update. Args: rule_body (dict[str, Any]): The rule body to set up the address. direction (str): The direction of the address, 'source' or 'destination'. address_value (str, optional): The value of the address. Defaults to None. address_kind (str, optional): The kind of the address. Defaults to None. """ address_direction = f"{direction}Address" if address_value and address_kind: setup_address( rule_body=rule_body, address_direction=address_direction, address_value=address_value, address_kind=address_kind, ) elif address_value: set_up_ip_kind(rule_body, address_direction, address_value) def setup_service( rule_body: dict[str, Any], source_service: str, source_service_kind: str = None, destination_service: str = None, destination_service_kind: str = None, ) -> None: """ Sets up the source and destination services. Args: rule_body (dict[str, Any]): The rule body to update. source_service (str): The source service. source_service_kind (str, optional): The kind of the source service. Defaults to None. destination_service (str, optional): The destination service. Defaults to None. destination_service_kind (str, optional): The kind of the destination service. Defaults to None. Raises: ValueError: Incase the user has only provided one of the destination service arguments. """ rule_body["sourceService"] = {"kind": source_service_kind or "NetworkProtocol", "value": source_service} if destination_service and destination_service_kind: rule_body["destinationService"] = {"kind": destination_service_kind, "value": destination_service} elif destination_service or destination_service_kind: raise ValueError("Missing arg in destination service, please provide both destination kind and value.") else: rule_body["destinationService"] = {"kind": "NetworkProtocol", "value": source_service} def setup_security( rule_body: dict[str, Any], direction: str, security_kind: str = None, security_value: str = None, ) -> None: """ Sets up the source or destination security in the rule_body. Args: rule_body (dict[str, Any]): The rule body to set up the security. direction (str): The direction of the security, 'source' or 'destination'. security_kind (str, optional): The kind of the security. Defaults to None. security_value (str, optional): The value of the security. Defaults to None. Raises: ValueError: Incase the user has only provided one of the security arguments. """ if security_kind and security_value: if security_kind == "SecurityObjGroup": security_kind = f"objectRef#{security_kind}" key = "objectId" else: key = "value" rule_body[f"{direction}Security"] = {"kind": security_kind, key: security_value} elif security_kind or security_value: raise ValueError(f"Missing arg in {direction} security, please provide both security kind and value.") def setup_user( rule_body: dict[str, Any], user: str = None, user_kind: str = None, ) -> None: """ Sets up the user in the rule_body. Args: rule_body (dict[str, Any]): The rule body to set up the user. user (str, optional): The user. Defaults to None. user_kind (str, optional): The kind of the user. Defaults to None. Raises: ValueError: Incase the user has only provided one of the user arguments. """ if user_kind and user: rule_body["user"] = {"kind": f"objectRef#{user_kind}", "objectId": user} elif user_kind or user: raise ValueError("Missing arg in user. Please provide both user kind and value.") def setup_time_range(rule_body: dict[str, Any], time_range: str = None) -> None: """ Sets up the time range in the rule_body. Args: rule_body (dict[str, Any]): The rule body to set up the time range. time range (str, optional): The time range to add. Defaults to None. """ if time_range: rule_body["timeRange"] = {"kind": "objectRef#TimeRange", "objectId": time_range} def handle_rule_configurations_setup(rule_body: dict[str, Any], args: dict[str, Any]) -> None: """Sets up the configurations for the rule. Add to the given rule_body the service, security, user and time range objects if they exist within args. Args: rule_body (dict[str, Any]): A reference to the dictionary to modify. args (dict[str, Any]): The args to add to the rule_body. """ if service := args.get("service"): setup_service( rule_body=rule_body, source_service=service, source_service_kind=args.get("service_kind"), destination_service=args.get("destination_service"), destination_service_kind=args.get("destination_service_kind"), ) setup_security( rule_body=rule_body, direction="src", security_kind=args.get("source_security_kind"), security_value=args.get("source_security"), ) setup_security( rule_body=rule_body, direction="dst", security_kind=args.get("destination_security_kind"), security_value=args.get("destination_security"), ) setup_user( rule_body=rule_body, user=args.get("user"), user_kind=args.get("user_kind"), ) setup_time_range(rule_body=rule_body, time_range=args.get("time_range")) rule_body["active"] = argToBoolean(args["active"]) if position := args.get("position"): rule_body["position"] = position if log_level := args.get("log_level"): rule_body["ruleLogging"] = {"logStatus": log_level} if permit := args.get("permit"): rule_body["permit"] = arg_to_optional_bool(permit) if remarks := argToList(args.get("remarks")): rule_body["remarks"] = remarks def safe_get_all_values( obj: list[dict[str, Any]] | dict[str, Any] | None, key: str, default_value: Any = None, ) -> Any: """Get all values from a list of dicts or a dict. Args: obj (list[dict[str, Any]] | dict[str, Any] | None): The object to extract values from. key (str): The key to the value to be extracted. default_value (Any, optional): The default value to return in case of failure. Defaults to None. Returns: Any: _description_ """ if not obj: return default_value if isinstance(obj, dict): return obj.get(key, default_value) return [item.get(key, default_value) for item in obj if key in obj] """COMMANDS""" @logger def list_rules_command(client: Client, args: dict[str, Any]) -> CommandResults: """ Gets a list all rules for the supplied interface. Args: client (Client): Session to Cisco ASA to run desired requests. args (dict[str, Any]): Arguments passed down by the CLI to configure the request. Interface_name - get rules from a specific interface. Interface_type - get rules from a specific type of interface. Raises: ValueError: The given interface couldn't be found. e: Unknown error. Returns: CommandResults: A CommandResults object containing the results of the rules. """ interface = args.get("interface_name") interface_type = args.get("interface_type", "All") try: raw_rules = client.get_all_rules(interface, interface_type) # demisto.getRules() # rules = raw_to_rules(raw_rules) hr = tableToMarkdown( "Rules:", rules, [ "ID", "Source", "Dest", "Permit", "Interface", "InterfaceType", "IsActive", "Position", "SourceService", "DestService", ], ) return CommandResults( readable_output=hr, outputs_prefix="CiscoASA.Rules", outputs=rules, raw_response=raw_rules, ) except Exception as e: if "404" in str(e) and interface: raise ValueError("Could not find interface") from e else: raise e @logger def backup_command(client: Client, args: dict[str, Any]) -> CommandResults: """ Creates a backup. Returns a message if backup was created successfully. Args: client (Client): Session to Cisco ASA to run desired requests. args (dict[str, Any]): Arguments passed down by the CLI to configure the request. Returns: CommandResults: A CommandResults object containing the results of the backup operation. """ location = "disk0:/" + args.get("backup_name", "") passphrase = args.get("passphrase") data = {"location": location} if passphrase: data["passphrase"] = passphrase client.backup(data) return CommandResults(readable_output=f"Created backup successfully in:\nLocation: {location}\nPassphrase: {passphrase}") @logger def restore_command(client: Client, args: dict[str, Any]) -> CommandResults: """ Restore a backup. Currently this command isn't in use through XSOAR. Args: client (Client): Session to Cisco ASA to run desired requests. args (dict[str, Any]): Arguments passed down by the CLI to configure the request. Returns: CommandResults: A CommandResults object containing the results of the restore operation. """ location = "disk0:/" + args.get("backup_name", "") passphrase = args.get("passphrase") data = {"location": location} if passphrase: data["passphrase"] = passphrase client.restore(data) return CommandResults(readable_output="Restored backup successfully.") @logger def rule_by_id_command(client: Client, args: dict[str, Any]) -> CommandResults: """ Gets a specific rule by rule ID. Args: client (Client): Session to Cisco ASA to run desired requests. args (dict[str, Any]): Arguments passed down by the CLI to configure the request. Raises: ValueError: The provided interface type was inbound/outbound and no interface name was given. Returns: CommandResults: A CommandResults object containing the results of the rule. """ rule_id = args.get("rule_id", "") interface_type = args.get("interface_type", "") interface = args.get("interface_name", "") if interface_type != "Global" and not interface: raise ValueError("Please state the name of the interface when it's not a global interface.") interface = "" if interface_type == "Global" else interface raw_rules = client.rule_action(rule_id, interface, interface_type, "GET") rules = raw_to_rules([raw_rules]) hr = tableToMarkdown( f"Rule {rule_id}:", rules, ["ID", "Source", "Dest", "Permit", "Interface", "InterfaceType", "IsActive", "Position", "SourceService", "DestService"], ) return CommandResults( readable_output=hr, outputs_prefix="CiscoASA.Rules", outputs=rules, raw_response=raw_rules, ) @logger def create_rule_command(client: Client, args: dict[str, Any]) -> CommandResults: """ Creates a rule. Args: client (Client): Session to Cisco ASA to run desired requests. args (dict[str, Any]): Arguments passed down by the CLI to configure the request. Raises: ValueError: The provided interface type was inbound/outbound and no interface name was given. ValueError: The rule already exists. ValueError: The interface couldn't be found. ValueError: Unknown error. Returns: CommandResults: A CommandResults object containing the results of the created rule. """ interface_name = args.get("interface_name") interface_type = args.get("interface_type", "") if interface_type == "Global": interface_name = "" elif not interface_name: raise ValueError("For In/Out interfaces, an interface name is mandatory.") rule_body = {} # type: dict # setup the source and destination address handle_address_in_rule( rule_body=rule_body, direction="source", address_value=args.get("source"), address_kind=args.get("source_kind"), ) handle_address_in_rule( rule_body=rule_body, direction="destination", address_value=args.get("destination"), address_kind=args.get("destination_kind"), ) args["service"] = args.get("service", "ip") handle_rule_configurations_setup(rule_body, args) try: raw_rule = client.create_rule(interface_type, interface_name, rule_body) rules = raw_to_rules([raw_rule]) hr = tableToMarkdown( f'Created new rule. ID: {raw_rule.get("objectId")}', rules, [ "ID", "Source", "Dest", "Permit", "Interface", "InterfaceType", "IsActive", "Position", "SourceService", "DestService", ], ) return CommandResults( readable_output=hr, outputs_prefix="CiscoASA.Rules", outputs=rules, raw_response=raw_rule, ) except Exception as e: if "DUPLICATE" in str(e): raise ValueError("You are trying to create a rule that already exists.") from e if "[500]" in str(e): raise ValueError(f"Could not find interface: {interface_name}") from e else: raise ValueError(f"Could not create rule. Error {e!s}") @logger def delete_rule_command(client: Client, args: dict[str, Any]) -> CommandResults: """ Deletes a rule. Args: client (Client): Session to Cisco ASA to run desired requests. args (dict[str, Any]): Arguments passed down by the CLI to configure the request. Raises: ValueError: The provided interface type was inbound/outbound and no interface name was given. ValueError: Incase the rule doesn't exist. ValueError: The rule cannot be deleted. Returns: CommandResults: A CommandResults object containing the results of the deleted rule. """ rule_id = args.get("rule_id", "") interface = args.get("interface_name", "") interface_type = args.get("interface_type", "") if interface_type != "Global" and not interface: raise ValueError("Please state the name of the interface when it's not a global interface.") try: client.rule_action(rule_id, interface, interface_type, "DELETE") except Exception as e: if "Not Found" in str(e): raise ValueError(f"Rule {rule_id} does not exist in interface {interface} of type {interface_type}.") from e else: raise ValueError(f"Could not delete rule. Error {e!s}") return CommandResults(readable_output=f"Rule {rule_id} deleted successfully.") @logger def edit_rule_command(client: Client, args: dict[str, Any]) -> CommandResults: """ Updates an existing rule. Args: client (Client): Session to Cisco ASA to run desired requests. args (dict[str, Any]): Arguments passed down by the CLI to configure the request. Raises: ValueError: In case the rule already exists. ValueError: The provided interface cannot be found. ValueError: Unexpected error. Returns: CommandResults: A CommandResults object containing the results of the edited rule. """ rule_id = args.get("rule_id", "") interface_type = args.get("interface_type", "") interface_name = args.get("interface_name") if interface_type == "Global": interface_name = "" elif not interface_name: raise ValueError("Please state the name of the interface when it's not a global interface.") rule_body = {} # type: dict # setup the source and destination address handle_address_in_rule( rule_body=rule_body, direction="source", address_value=args.get("source"), address_kind=args.get("source_kind"), ) handle_address_in_rule( rule_body=rule_body, direction="destination", address_value=args.get("destination"), address_kind=args.get("destination_kind"), ) handle_rule_configurations_setup(rule_body, args) try: rule = client.rule_action(rule_id, interface_name, interface_type, "PATCH", rule_body) try: raw_rule = client.rule_action(rule_id, interface_name, interface_type, "GET") except Exception: location = rule.headers._store.get("location")[1] # type: ignore rule_id = location[location.rfind("/") + 1 :] raw_rule = client.rule_action(rule_id, interface_name, interface_type, "GET") rules = raw_to_rules([raw_rule]) hr = tableToMarkdown( f'Edited rule {raw_rule.get("objectId")}', rules, [ "ID", "Source", "Dest", "Permit", "Interface", "InterfaceType", "IsActive", "Position", "SourceService", "DestService", ], ) return CommandResults( readable_output=hr, outputs_prefix="CiscoASA.Rules", outputs=rules, raw_response=raw_rule, ) except Exception as e: if "DUPLICATE" in str(e): raise ValueError("You are trying to create a rule that already exists.") from e if "[500]" in str(e): raise ValueError(f"Could not find interface: {interface_name}.") from e raise @logger def list_objects_command(client: Client, args: dict[str, Any]) -> CommandResults: """ Gets a list of all the configured network objects. Args: client (Client): Session to Cisco ASA to run desired requests. args (dict[str, Any]): Arguments passed down by the CLI to configure the request. Returns: CommandResults: A CommandResults object containing the results of network objects. """ objects = client.get_network_obejcts() obj_names = argToList(args.get("object_name")) obj_ids = argToList(args.get("object_id")) formated_objects = [] for object in objects: if (not obj_names and not obj_ids) or object.get("name") in obj_names or object.get("objectId") in obj_ids: object.pop("selfLink") object.pop("kind") formated_obj = camelize(object) formated_obj["ID"] = formated_obj.pop("Objectid") formated_objects.append(formated_obj) hr = tableToMarkdown("Network Objects", formated_objects, headers=["ID", "Name", "Host", "Description"]) return CommandResults( readable_output=hr, outputs_prefix="CiscoASA.NetworkObject", outputs=formated_objects, raw_response=formated_objects, ) @logger def create_object_command(client: Client, args: dict[str, Any]) -> CommandResults: """ Creates a network object. Args: client (Client): Session to Cisco ASA to run desired requests. args (dict[str, Any]): Arguments passed down by the CLI to configure the request. Raises: ValueError: Incase a user hasn't entered an object type from the provided list. Returns: CommandResults: A CommandResults object containing the results of the created network object. """ obj_type = args.get("object_type") obj_name = args.get("object_name") obj_value = args.get("object_value") if obj_type not in OBJECT_TYPES_DICT: raise ValueError("Please enter an object type from the given dropdown list.") client.create_object(obj_name, obj_type, obj_value) return list_objects_command(client, {"object_name": obj_name}) @logger def list_interfaces_command(client: Client, args: dict[str, Any]) -> CommandResults: """ Gets a list of all interfaces. Args: client (Client): Session to Cisco ASA to run desired requests. args (dict[str, Any]): Arguments passed down by the CLI to configure the request. Returns: CommandResults: A CommandResults object containing the results of the interfaces. """ raw_interfaces = client.list_interfaces() interface_list = [] for interface in raw_interfaces: temp_interface = { "Type": interface.get("direction", "").capitalize(), "ID": interface.get("interface", {}).get("objectId", "-1"), "Name": interface.get("interface", {}).get("name"), } interface_list.append(temp_interface) ec = {"CiscoASA.Interface(val.ID && val.ID== obj.ID)": interface_list} hr = tableToMarkdown("Interfaces", interface_list, ["Type", "ID", "Name"]) return CommandResults( readable_output=hr, outputs=ec, raw_response=raw_interfaces, ) @logger def test_command(client: Client, isASAv: bool) -> str: """ Args: client (Client): Session to Cisco ASA to run desired requests. isASAv (bool): Whether Cisco Adaptive Security Virtual Appliance is in use. Returns: Runs a random GET API request just to see if successful. """ try: client.login(isASAv) client.test_command() except DemistoException as exc: if exc.res is not None and exc.res.status_code == HTTPStatus.UNAUTHORIZED: return "Authorization Error: invalid username or password" return exc.message return "ok" @logger def list_object_command( client_get_command: Callable, client_list_command: Callable, args: dict[str, Any], keys_mapping: dict[str, Any], title: str, outputs_prefix: str, readable_headers: list[str] = None, ) -> CommandResults: """ A generic function to list objects using the provided get and list commands. Args: client_get_command (Callable): The client's GET method for a single object. client_list_command (Callable): The client's LIST method for multiple objects. args (dict[str, Any]): Arguments passed down by the CLI to configure the request. keys_mapping (dict[str, Any]): A dictionary to map response keys to desired output keys. title (str): The title for the table in the human-readable output. outputs_prefix (str): The prefix for the output context path. Returns: CommandResults: A CommandResults object containing the command's results. """ # GET arguments object_id = args.get("object_id", "") # LIST arguments limit = arg_to_number(args.get("limit"), required=False) page = arg_to_number(args.get("page"), required=False) page_size = arg_to_number(args.get("page_size"), required=False) raw_items = None if is_get_request_type( get_args=[object_id], list_args=[page, page_size], ): raw_response = client_get_command(object_id) else: # is_list_request raw_items, raw_response = client_list_command( page=page, page_size=page_size, limit=limit, ) outputs = extract_data( obj=raw_items or raw_response, keys_mapping=keys_mapping, ) readable_output = tableToMarkdown( name=title, t=outputs, headers=readable_headers or [camel_case_to_underscore(key) for key in keys_mapping], headerTransform=string_to_table_header, removeNull=True, ) return CommandResults( outputs_prefix=f"CiscoASA.{outputs_prefix}", outputs_key_field="object_id", outputs=outputs, readable_output=readable_output, raw_response=raw_response, ) @logger def list_network_object_group_command(client: Client, args: dict[str, Any]) -> CommandResults: """ Lists network object groups using the provided client and arguments. Args: client (Client): Session to Cisco ASA to run desired requests. args (dict[str, Any]): Arguments passed down by the CLI to configure the request. Returns: CommandResults: A CommandResults object containing the results of the network object group. """ return list_object_command( client_get_command=client.get_network_object_group, client_list_command=client.list_network_object_group, args=args, keys_mapping=DEFAULT_KEYS_MAPPING, title="Network Object Groups", outputs_prefix="NetworkObjectGroup", ) @logger def list_local_user_group_command(client: Client, args: dict[str, Any]) -> CommandResults: """ Lists local user groups using the provided client and arguments. Args: client (Client): Session to Cisco ASA to run desired requests. args (dict[str, Any]): Arguments passed down by the CLI to configure the request. Returns: CommandResults: A CommandResults object containing the results of the local user groups. """ return list_object_command( client_get_command=client.get_local_user_group, client_list_command=client.list_local_user_group, args=args, keys_mapping=DEFAULT_KEYS_MAPPING, title="Local User Groups", outputs_prefix="LocalUserGroup", ) @logger def list_local_user_command(client: Client, args: dict[str, Any]) -> CommandResults: """ Lists local users using the provided client and arguments. Args: client (Client): Session to Cisco ASA to run desired requests. args (dict[str, Any]): Arguments passed down by the CLI to configure the request. Returns: CommandResults: A CommandResults object containing the results of the local user. """ return list_object_command( client_get_command=client.get_local_user, client_list_command=client.list_local_user, args=args, keys_mapping={ "objectId": "object_id", "name": "name", "MSCHAPauthenticated": "mschap_authenticated", "privilegeLevel": "privilege_level", "ASDM_CLIAccessType": "asdm_cli_access_type", }, title="Local Users", outputs_prefix="LocalUser", ) @logger def list_time_range_command(client: Client, args: dict[str, Any]) -> CommandResults: """ Lists time ranges using the provided client and arguments. Args: client (Client): Session to Cisco ASA to run desired requests. args (dict[str, Any]): Arguments passed down by the CLI to configure the request. Returns: CommandResults: A CommandResults object containing the results of the time range. """ return list_object_command( client_get_command=client.get_time_range, client_list_command=client.list_time_range, args=args, keys_mapping={ "objectId": "object_id", "name": "name", "value": { "_include": False, "start": "start", "end": "end", "periodic": { "_include": True, "frequency": "frequency", "startHour": "start_hour", "startMinute": "start_minute", "endHour": "end_hour", "endMinute": "end_minute", }, }, }, title="Time Ranges", outputs_prefix="TimeRange", readable_headers=["object_id", "name", "start", "end", "periodic"], ) @logger def list_security_object_group_command(client: Client, args: dict[str, Any]) -> CommandResults: """ Lists security object groups using the provided client and arguments. Args: client (Client): Session to Cisco ASA to run desired requests. args (dict[str, Any]): Arguments passed down by the CLI to configure the request. Returns: CommandResults: A CommandResults object containing the results of the security object group. """ return list_object_command( client_get_command=client.get_security_object_group, client_list_command=client.list_security_object_group, args=args, keys_mapping=DEFAULT_KEYS_MAPPING, title="Security Object Groups", outputs_prefix="SecurityObjectGroup", ) @logger def list_user_object_command(client: Client, args: dict[str, Any]) -> CommandResults: """ Lists user objects using the provided client and arguments. Args: client (Client): Session to Cisco ASA to run desired requests. args (dict[str, Any]): Arguments passed down by the CLI to configure the request. Returns: CommandResults: A CommandResults object containing the results of the user object. """ return list_object_command( client_get_command=client.get_user_object, client_list_command=client.list_user_object, args=args, keys_mapping={ "objectId": "object_id", "userName": "user_name", "user": { "_include": False, "objectId": "local_user_object_id", "value": "value", }, }, title="User Objects", outputs_prefix="UserObject", ) @logger def write_memory_command(client: Client, *_) -> CommandResults: """ The write memory command saves the running configuration to the default location for the startup configuration. Args: client (Client): Session to Cisco ASA to run desired requests. args (dict[str, Any]): Arguments passed down by the CLI to configure the request. Returns: CommandResults: shows a successful 'write memory' command execution on a Cisco ASA device, building the configuration and generating a cryptochecksum for integrity. The process is completed with an "[OK]" message. """ raw_response = client.write_memory() return CommandResults(outputs_prefix="CiscoASA.WriteMemory", outputs=raw_response, raw_response=raw_response) """MAIN""" def main(): params: dict[str, Any] = demisto.params() args: dict[str, Any] = demisto.args() command: str = demisto.command() username = params["credentials"].get("identifier") password = params["credentials"].get("password") verify_certificate = not params.get("insecure", False) proxy = params.get("proxy", False) isASAv = params.get("isASAv", False) # Remove trailing slash to prevent wrong URL path to service server_url = params.get("server", "").rstrip("/") commands = { f"{INTEGRATION_COMMAND}-list-rules": list_rules_command, f"{INTEGRATION_COMMAND}-backup": backup_command, f"{INTEGRATION_COMMAND}-get-rule-by-id": rule_by_id_command, f"{INTEGRATION_COMMAND}-create-rule": create_rule_command, f"{INTEGRATION_COMMAND}-delete-rule": delete_rule_command, f"{INTEGRATION_COMMAND}-edit-rule": edit_rule_command, f"{INTEGRATION_COMMAND}-list-network-objects": list_objects_command, f"{INTEGRATION_COMMAND}-create-network-object": create_object_command, f"{INTEGRATION_COMMAND}-list-interfaces": list_interfaces_command, f"{INTEGRATION_COMMAND}-list-network-object-group": list_network_object_group_command, f"{INTEGRATION_COMMAND}-list-local-user-group": list_local_user_group_command, f"{INTEGRATION_COMMAND}-list-local-user": list_local_user_command, f"{INTEGRATION_COMMAND}-list-time-range": list_time_range_command, f"{INTEGRATION_COMMAND}-list-security-object-group": list_security_object_group_command, f"{INTEGRATION_COMMAND}-list-user-object": list_user_object_command, f"{INTEGRATION_COMMAND}-write-memory": write_memory_command, } LOG(f"Command being called is {command}") client = Client( server_url, auth=(username, password), verify=verify_certificate, proxy=proxy, headers={}, ) try: if command == "test-module": return_results(test_command(client, isASAv)) elif command in commands: client.login(isASAv) return_results(commands[command](client, args)) else: raise NotImplementedError(f"{command} command is not implemented.") # Log exceptions except Exception as exc: # pylint: disable=broad-except return_error(f"Failed to execute {command} command. Error: {exc}", error=traceback.format_exc()) finally: client.logoff() if __name__ in ["__main__", "__builtin__", "builtins"]: main()