SafeNet Trusted Access

This integration enables you to process alerts from SafeNet Trusted Access (STA) indicating security risks to end user accounts, and apply security remediation actions on SafeNet Trusted Access through security orchestration playbooks.

Authentication & Identity Management · Thales SafeNet Trusted Access

Details

IDSafeNet Trusted Access
ProviderThales
CategoryAuthentication & Identity Management
From Version6.0.0
Docker Imagedemisto/python3:3.12.8.3296088
Supported ModulesAgentix XSIAM

README

This integration enables you to process alerts from SafeNet Trusted Access (STA) indicating security risks to end user accounts, and apply security remediation actions on SafeNet Trusted Access through security orchestration playbooks. For information about the configuration steps, visit our Help Documentation.

Commands

You can execute these commands from the Cortex XSOAR 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.

NOTE : Perform create, update and delete operations using commands only for internal users or groups. Such operations aren’t recommended for synchronized users or groups.

sta-get-user-list


Get list of users in the tenant.

Base Command

sta-get-user-list

Input

Argument Name Description Required
limit The maximum number of results to return. Optional

Context Output

Path Type Description
STA.USER.ID string User ID of the user.
STA.USER.SCHEMA string Schema version number.
STA.USER.USERNAME string Username of the user.
STA.USER.FIRSTNAME string First name of the user.
STA.USER.LASTNAME string Last name of the user.
STA.USER.EMAIL string Email ID of the user.
STA.USER.MOBILENUMBER number Mobile number of the user.
STA.USER.ALIAS1 string Alias for the user.
STA.USER.ALIAS2 string Additional alias for the user.
STA.USER.ALIAS3 string Additional alias for the user.
STA.USER.ALIAS4 string Additional alias for the user.
STA.USER.ADDRESS string Address of the user.
STA.USER.CITY string City of the user.
STA.USER.STATE string State of the user.
STA.USER.COUNTRY string Country of the user.
STA.USER.POSTALCODE number Postal Code of the user.
STA.USER.SYNCHRONIZED boolean Is the user synchronized.

Command Example


#### Context Example

```json
{
    "STA": {
        "USER": [
            {
                "email": "demo.user@demisto.com",
                "firstName": "Demo",
                "id": "CNlM6Pyq3nADXA4rWyUAAAAc",
                "isSynchronized": false,
                "lastName": "User",
                "schemaVersionNumber": "1.0",
                "userName": "demouser"
            },
            {
                "email": "test.user@demisto.com",
                "firstName": "Hello",
                "id": "CNlM6rvB0uQDXA4rWyUAAAAc",
                "isSynchronized": false,
                "lastName": "User",
                "schemaVersionNumber": "1.0",
                "userName": "hellouser"
            }
        ]
    }
}

Human Readable Output

List of users in the tenant

Id Schema Version Number User Name First Name Last Name Email Is Synchronized
CNlM6Pyq3nADXA4rWyUAAAAc 1.0 demouser Demo User demo.user@demisto.com false
CNlM6rvB0uQDXA4rWyUAAAAc 1.0 hellouser Hello User test.user@demisto.com false

sta-get-user-info


Get the profile information for a specific user.

Base Command

sta-get-user-info

Input

Argument Name Description Required
userName Username of the user. Required

Context Output

Path Type Description
STA.USER.ID string User ID of the user.
STA.USER.SCHEMA string Schema version number.
STA.USER.USERNAME string Username of the user.
STA.USER.FIRSTNAME string First name of the user.
STA.USER.LASTNAME string Last name of the user.
STA.USER.EMAIL string Email ID of the user.
STA.USER.MOBILENUMBER string Mobile number of the user.
STA.USER.ALIAS1 string Alias for the user.
STA.USER.ALIAS2 string Additional alias for the user.
STA.USER.ALIAS3 string Additional alias for the user.
STA.USER.ALIAS4 string Additional alias for the user.
STA.USER.CUSTOM1 string Custom value for the user.
STA.USER.CUSTOM2 string Additional custom value for the user.
STA.USER.CUSTOM3 string Additional custom value for the user.
STA.USER.ADDRESS string Address of the user.
STA.USER.CITY string City of the user.
STA.USER.STATE string State of the user.
STA.USER.COUNTRY string Country of the user.
STA.USER.POSTALCODE string Postal Code of the user.
STA.USER.SYNCHRONIZED boolean Is user synchronized.

Command Example

!sta-get-user-info userName="demouser"

Context Example

{
    "STA": {
        "USER": {
            "email": "demo.user@demisto.com",
            "firstName": "Demo",
            "id": "CNlM6Pyq3nADXA4rWyUAAAAc",
            "isSynchronized": false,
            "lastName": "User",
            "schemaVersionNumber": "1.0",
            "userName": "demouser"
        }
    }
}

Human Readable Output

Information for user - demouser

Id Schema Version Number User Name First Name Last Name Email Is Synchronized
CNlM6Pyq3nADXA4rWyUAAAAc 1.0 demouser Demo User demo.user@demisto.com false

sta-create-user


Create a new user in the tenant.

Base Command

sta-create-user

Input

Argument Name Description Required
userName User ID of the user. Required
first_name First name of the user. Required
last_name Last name of the user. Required
email Email ID of the user. Required
mobile_number Mobile number of the user. Optional
alias1 Alias for the user. Optional
alias2 Additional alias for the user. Optional
custom1 Custom value for the user. Optional
custom2 Additional custom value for the user. Optional
custom3 Additional custom value for the user. Optional
address Address of the user. Optional
city City of the user. Optional
state State of the user. Optional
country Country of the user. Optional
postal_code Postal Code of the user. Optional
synchronized Is user synchronized. Optional

Context Output

Path Type Description
STA.USER.ID string User ID of the user.
STA.USER.SCHEMA string Schema version number.
STA.USER.USERNAME string Username of the user.
STA.USER.FIRSTNAME string First name of the user.
STA.USER.LASTNAME string Last name of the user.
STA.USER.EMAIL string Email ID of the user.
STA.USER.MOBILENUMBER string Mobile number of the user.
STA.USER.ALIAS1 string Alias for the user.
STA.USER.ALIAS2 string Additional alias for the user.
STA.USER.CUSTOM1 string Custom value for the user.
STA.USER.CUSTOM2 string Additional custom value for the user.
STA.USER.CUSTOM3 string Additional custom value for the user.
STA.USER.ADDRESS string Address of the user.
STA.USER.CITY string City of the user.
STA.USER.STATE string State of the user.
STA.USER.COUNTRY string Country of the user.
STA.USER.POSTALCODE string Postal Code of the user.
STA.USER.SYNCHRONIZED boolean Is user synchronized.

Command Example

!sta-create-user email="test.user@demisto.com" first_name="User" last_name="Test" userName="usertest123"

Context Example

{
    "STA": {
        "USER": {
            "email": "test.user@demisto.com",
            "firstName": "User",
            "id": "iNlsjym+x1MLesvCSusAAAAc",
            "isSynchronized": false,
            "lastName": "Test",
            "schemaVersionNumber": "1.0",
            "userName": "usertest123"
        }
    }
}

Human Readable Output

STA user successfully created

Id Schema Version Number User Name First Name Last Name Email Is Synchronized
iNlsjym+x1MLesvCSusAAAAc 1.0 usertest123 User Test test.user@demisto.com false

sta-update-user-info


Update the profile for a specific user.

Base Command

sta-update-user-info

Input

Argument Name Description Required
userName User ID of the user. Required
first_name First name of the user. Optional
last_name Last name of the user. Optional
email Email ID of the user. Optional
mobile_number Mobile number of the user. Optional
alias1 Alias for the user. Optional
alias2 Additional alias for the user. Optional
address Address of the user. Optional
city City of the user. Optional
state State of the user. Optional
country Country of the user. Optional
postal_code Postal Code of the user. Optional
userName_new New userName to be updated. Optional

Context Output

Path Type Description
STA.USER.ID string User ID of the user.
STA.USER.SCHEMA string Schema version number.
STA.USER.USERNAME string Username of the user.
STA.USER.FIRSTNAME string First name of the user.
STA.USER.LASTNAME string Last name of the user.
STA.USER.EMAIL string Email ID of the user.
STA.USER.MOBILENUMBER number Mobile number for the user.
STA.USER.ALIAS1 string Alias for the user.
STA.USER.ALIAS2 string Additional alias for the user.
STA.USER.CUSTOM1 string Custom value for the user.
STA.USER.CUSTOM2 string Additional custom value for the user.
STA.USER.CUSTOM3 string Additional custom value for the user.
STA.USER.ADDRESS string Address of the user.
STA.USER.CITY string City of the user.
STA.USER.STATE string State of the user.
STA.USER.COUNTRY string Country of the user.
STA.USER.POSTALCODE number Postal Code of the user.
STA.USER.SYNCHRONIZED boolean Is user synchronized.

Command Example

!sta-update-user-info userName="usertest123" userName_new="testuser1" first_name="Demo" last_name="Name"

Context Example

{
    "STA": {
        "USER": {
            "email": "test.user@demisto.com",
            "firstName": "Demo",
            "id": "iNlsjym+x1MLesvCSusAAAAc",
            "isSynchronized": false,
            "lastName": "Name",
            "schemaVersionNumber": "1.0",
            "userName": "testuser1"
        }
    }
}

Human Readable Output

STA user successfully updated

Id Schema Version Number User Name First Name Last Name Email Is Synchronized
iNlsjym+x1MLesvCSusAAAAc 1.0 testuser1 Demo Name test.user@demisto.com false

sta-delete-user


Delete a user from the tenant.

Base Command

sta-delete-user

Input

Argument Name Description Required
userName Username of the user to be deleted. Required

Context Output

Path Type Description
STA.USER.ID string User ID of the user to be deleted from the tenant.
STA.USER.USERNAME string Username of the user to be deleted from the tenant.
STA.USER.DELETED boolean Returns true, if the user is deleted from the tenant.

Command Example

!sta-delete-user userName="testuser1"

Context Example

{
    "STA": {
        "USER": {
            "Deleted": true,
            "id": "iNlsjym+x1MLesvCSusAAAAc",
            "userName": "testuser1"
        }
    }
}

Human Readable Output

STA user - testuser1 successfully deleted

sta-get-user-groups


Return all the groups associated with a specific user.

Base Command

sta-get-user-groups

Input

Argument Name Description Required
userName Username of the user. Required
limit The maximum number of results to return. Optional

Context Output

Path Type Description
STA.USER.ID string User ID of the user.
STA.USER.SCHEMA string Schema version number.
STA.USER.USERNAME string Username of the user.
STA.USER.FIRSTNAME string First name of the user.
STA.USER.LASTNAME string Last name of the user.
STA.USER.EMAIL string Email ID of the user.
STA.USER.MOBILENUMBER number Mobile number for the user.
STA.USER.ALIAS1 string Alias for the user.
STA.USER.ALIAS2 string Additional alias for the user.
STA.USER.CUSTOM1 string Custom value for the user.
STA.USER.CUSTOM2 string Additional custom value for the user.
STA.USER.CUSTOM3 string Additional custom value for the user.
STA.USER.ADDRESS string Address of the user.
STA.USER.CITY string City of the user.
STA.USER.STATE string State of the user.
STA.USER.COUNTRY string Country of the user.
STA.USER.POSTALCODE number Postal Code of the user.
STA.USER.SYNCHRONIZED boolean Is user synchronized.
STA.USER.GROUP.ID string Group ID of the group.
STA.USER.GROUP.SCHEMA string Schema version for the group.
STA.USER.GROUP.NAME string Name of the group.
STA.USER.GROUP.DESCRIPTION string Description of the group.
STA.USER.GROUP.SYNCHRONIZED boolean Is group synchronized.

Command Example

!sta-get-user-groups userName="hellouser"

Context Example

{
    "STA": {
        "USER": {
            "email": "test.user@demisto.com",
            "firstName": "Hello",
            "groups": [
                {
                    "description": "User would be added to unusual activity group on denying Push Notification.",
                    "id": "50331650",
                    "isSynchronized": false,
                    "name": "TestUnusualActivityGroup",
                    "schemaVersionNumber": "1.0"
                },
                {
                    "description": "Group for testing.",
                    "id": "50331652",
                    "isSynchronized": false,
                    "name": "TestGroup0",
                    "schemaVersionNumber": "1.0"
                }
            ],
            "id": "CNlM6rvB0uQDXA4rWyUAAAAc",
            "isSynchronized": false,
            "lastName": "User",
            "schemaVersionNumber": "1.0",
            "userName": "hellouser"
        }
    }
}

Human Readable Output

Groups associated with user - hellouser

Id Schema Version Number Name Description Is Synchronized
50331650 1.0 TestUnusualActivityGroup Group for testing. false
50331652 1.0 TestGroup0 Group for testing. false

sta-get-group-list


Get list of groups in the tenant.

Base Command

sta-get-group-list

Input

Argument Name Description Required
limit The maximum number of results to return. Optional

Context Output

Path Type Description
STA.GROUP.ID string Group ID of the group.
STA.GROUP.SCHEMA string Schema version for the group.
STA.GROUP.NAME string Name of the group.
STA.GROUP.DESCRIPTION string Description of the group.
STA.GROUP.SYNCHRONIZED boolean Is group synchronized.

Command Example


#### Context Example

```json
{
    "STA": {
        "GROUP": [
            {
                "description": "Description has been updated.",
                "id": "50331649",
                "isSynchronized": false,
                "name": "TestGroup1",
                "schemaVersionNumber": "1.0"
            },
            {
                "description": "Unusual Activity Group for Testing",
                "id": "50331650",
                "isSynchronized": false,
                "name": "TestUnusualActivityGroup",
                "schemaVersionNumber": "1.0"
            },
            {
                "description": "Group for testing.",
                "id": "50331652",
                "isSynchronized": false,
                "name": "TestGroup0",
                "schemaVersionNumber": "1.0"
            }
        ]
    }
}

Human Readable Output

STA groups in the tenant

Id Schema Version Number Name Description Is Synchronized
50331649 1.0 TestGroup1 Description has been updated. false
50331650 1.0 TestUnusualActivityGroup Unusual Activity Group for Testing false
50331652 1.0 TestGroup0 Group for testing. false

sta-get-group-info


Get information for a specific group.

Base Command

sta-get-group-info

Input

Argument Name Description Required
groupName Name of the group. Required

Context Output

Path Type Description
STA.GROUP.ID string Group ID of the group.
STA.GROUP.SCHEMA string Schema version for the group.
STA.GROUP.NAME string Name of the group.
STA.GROUP.DESCRIPTION string Description of the group.
STA.GROUP.SYNCHRONIZED boolean Is group synchronized.

Command Example

!sta-get-group-info groupName="TestGroup1"

Context Example

{
    "STA": {
        "GROUP": {
            "description": "Description has been updated.",
            "id": "50331649",
            "isSynchronized": false,
            "name": "TestGroup1",
            "schemaVersionNumber": "1.0"
        }
    }
}

Human Readable Output

Group - TestGroup1

Id Schema Version Number Name Description Is Synchronized
50331649 1.0 TestGroup1 Description has been updated. false

sta-get-group-members


Get list of users in a specific group.

Base Command

sta-get-group-members

Input

Argument Name Description Required
groupName Name of the group. Required
limit The maximum number of results to return. Optional

Context Output

Path Type Description
STA.GROUP.ID string Group ID of the group.
STA.GROUP.SCHEMA string Schema version for the group.
STA.GROUP.NAME string Name of the group.
STA.GROUP.DESCRIPTION string Description of the group.
STA.GROUP.SYNCHRONIZED boolean Is group synchronized.
STA.GROUP.USER.ID string User ID of the user.
STA.GROUP.USER.NAME string Username of the user.
STA.GROUP.USER.TYPE string Type of the user.
STA.GROUP.USER.LINKS.SELF string Link for the user details.

Command Example

!sta-get-group-members groupName="TestGroup0"

Context Example

{
    "STA": {
        "GROUP": {
            "description": "Group for testing.",
            "id": "50331652",
            "isSynchronized": false,
            "name": "TestGroup0",
            "schemaVersionNumber": "1.0",
            "users": [
                {
                    "id": "CNlM6Pyq3nADXA4rWyUAAAAc",
                    "links": {
                        "self": "https://api.stademo.com/api/v1/tenants/HNISOUTHA4/users/CNlM6Pyq7nADXA4rWyUAAATc?isUid=true"
                    },
                    "name": "demouser",
                    "type": "User"
                },
                {
                    "id": "CNlM6rvB0uQDXA4rWyUAAAAc",
                    "links": {
                        "self": "https://api.stademo.com/api/v1/tenants/HNISOUTHA4/users/CNlM6rvB9uQDXA4rWyUAAATc?isUid=true"
                    },
                    "name": "hellouser",
                    "type": "User"
                }
            ]
        }
    }
}

Human Readable Output

Members of group - TestGroup0

Id Name Type
CNlM6Pyq3nADXA4rWyUAAAAc demouser User
CNlM6rvB0uQDXA4rWyUAAAAc hellouser User

sta-create-group


Create a new group in the tenant.

Base Command

sta-create-group

Input

Argument Name Description Required
groupName Name of the group. Required
description Description of the group. Optional
synchronized Is group synchronized. Optional

Context Output

Path Type Description
STA.GROUP.ID string Group ID of the group.
STA.GROUP.SCHEMA string Schema version for the group.
STA.GROUP.NAME string Name of the group.
STA.GROUP.DESCRIPTION string Description of the group.
STA.GROUP.SYNCHRONIZED boolean Is group synchronized.

Command Example

!sta-create-group groupName="TestGroup2" description="Group description." synchronized=False

Context Example

{
    "STA": {
        "GROUP": {
            "description": "Group description.",
            "id": "16777228",
            "isSynchronized": false,
            "name": "TestGroup2",
            "schemaVersionNumber": "1.0"
        }
    }
}

Human Readable Output

STA group - TestGroup2 successfully created

Id Schema Version Number Name Description Is Synchronized
16777228 1.0 TestGroup2 Group description. false

sta-delete-group


Delete group from the tenant.

Base Command

sta-delete-group

Input

Argument Name Description Required
groupName Name of the group to be deleted. Required

Context Output

Path Type Description
STA.GROUP.ID string Group ID of the group to be deleted.
STA.GROUP.GROUPNAME string Name of the group to be deleted.
STA.GROUP.DELETED boolean Returns true, if the group is deleted from the tenant.

Command Example

!sta-delete-group groupName="TestGroup2"

Context Example

{
    "STA": {
        "GROUP": {
            "Deleted": true,
            "groupName": "TestGroup2",
            "id": "16777228"
        }
    }
}

Human Readable Output

STA group - TestGroup2 successfully deleted

sta-update-group-info


Update information for a specific group.

Base Command

sta-update-group-info

Input

Argument Name Description Required
groupName Name of the group to be updated. Required
description Description of the group. Optional
groupName_new New name in case you want to update the group name. Optional

Context Output

Path Type Description
STA.GROUP.ID string Group ID of the group.
STA.GROUP.SCHEMA string Schema version for the group.
STA.GROUP.NAME string Name of the group.
STA.GROUP.DESCRIPTION string Description of the group.
STA.GROUP.SYNCHRONIZED boolean Is group synchronized.

Command Example

!sta-update-group-info groupName="TestGroup1" description="Description has been updated."

Context Example

{
    "STA": {
        "GROUP": {
            "description": "Description has been updated.",
            "id": "50331649",
            "isSynchronized": false,
            "name": "TestGroup1",
            "schemaVersionNumber": "1.0"
        }
    }
}

Human Readable Output

STA user successfully updated

Id Schema Version Number Name Description Is Synchronized
50331649 1.0 TestGroup1 Description has been updated. false

sta-user-exist-group


Check if user exists in a specific group.

Base Command

sta-user-exist-group

Input

Argument Name Description Required
userName Username of the user to be checked. Required
groupName Group name in which you want to search for the user. Required

Context Output

Path Type Description
STA.EXIST.USER.GROUP boolean Check if user exists in group. Returns true, if the user is a member of the group.

Command Example

!sta-user-exist-group groupName="TestGroup1" userName="hellouser"

Context Example

{
    "STA": {
        "EXIST": {
            "USER": {
                "GROUP": true
            }
        }
    }
}

Human Readable Output

Yes, user - hellouser is a member of group - TestGroup1

sta-add-user-group


Add user to a specific group.

Base Command

sta-add-user-group

Input

Argument Name Description Required
userName User name of the user to be added. Required
groupName Name of the group in which the user needs to be added. Required

Context Output

Path Type Description
STA.UPDATE.USER.GROUP.USERID string User ID of the user.
STA.UPDATE.USER.GROUP.USERNAME string Username of the user.
STA.UPDATE.USER.GROUP.GROUPID string Group ID of the group.
STA.UPDATE.USER.GROUP.GROUPNAME string Groupname of the group.
STA.UPDATE.USER.GROUP.STATUS boolean Returns true, if the user successfully added to the group.

Command Example

!sta-add-user-group groupName="TestGroup1" userName="hellouser"

Context Example

{
    "STA": {
        "UPDATE": {
            "USER": {
                "GROUP": {
                    "groupName": "TestGroup1",
                    "group_id": "50331649",
                    "status": true,
                    "userName": "hellouser",
                    "user_id": "CNlM6rvB0uQDXA4rWyUAAAAc"
                }
            }
        }
    }
}

Human Readable Output

User - hellouser successfully added to the group - TestGroup1

sta-remove-user-group


Remove user from a group.

Base Command

sta-remove-user-group

Input

Argument Name Description Required
userName User name of the user to be deleted from the group. Required
groupName Group name from which the user needs to be deleted. Required

Context Output

Path Type Description
STA.UPDATE.USER.GROUP.USERID string User ID of the user.
STA.UPDATE.USER.GROUP.USERNAME string Username of the user.
STA.UPDATE.USER.GROUP.GROUPID string Group ID of the group.
STA.UPDATE.USER.GROUP.GROUPNAME string Groupname of the group.
STA.UPDATE.USER.GROUP.STATUS boolean Returns false, if the user successfully removed from the group.

Command Example

!sta-remove-user-group groupName="TestGroup1" userName="hellouser"

Context Example

{
    "STA": {
        "UPDATE": {
            "USER": {
                "GROUP": {
                    "groupName": "TestGroup1",
                    "group_id": "50331649",
                    "status": false,
                    "userName": "hellouser",
                    "user_id": "CNlM6rvB0uQDXA4rWyUAAAAc"
                }
            }
        }
    }
}

Human Readable Output

User - hellouser successfully removed from the group - TestGroup1

sta-get-logs


Get access, authentication, and audit logs.

Base Command

sta-get-logs

Input

Argument Name Description Required
userName Username of the user. Optional
since Filter logs since the specified date and time in Universal Time Coordinated time zone. Format : yyyy-mm-ddTHH:mm:ss.fffZ .Example : 2021-06-03T06:27:00.000Z Optional
until Filter logs until the specified date and time in Universal Time Coordinated time zone. Format : yyyy-mm-ddTHH:mm:ss.fffZ .Example : 2021-06-03T07:40:00.000Z Optional
limit The maximum number of results to return. Optional

Context Output

Path Type Description
STA.LOGS.TIMESTAMP string Timestamp of event.
STA.LOGS.USERNAME string Username of the user.
STA.LOGS.TYPE string Type of event log.
STA.LOGS.CREDENTIAL string Credential type of the event.
STA.LOGS.ACTION string Authentication action.
STA.LOGS.RESULT string Authentication Action Result.
STA.LOGS.MESSAGE string Message or description of the event.
STA.LOGS.APPLICATION string Application name.
STA.LOGS.POLICY string Policy applied for the application.
STA.LOGS.STATE string State of the access request.
STA.LOGS.OPERATIONTYPE string Operation type.
STA.LOGS.OPERATIONOBJECT string Operation object type.
STA.LOGS.OPERATIONNAME string Operation object name.
STA.LOGS.SERIAL string Serial number of authentication.
STA.LOGS.IP string IP address of the user.

Command Example

!sta-get-logs userName="demouser" since="2021-07-21T12:22:16.718Z"

Context Example

{
    "STA": {
        "LOGS": [
            {
                "actionText": "AUTH_ATTEMPT",
                "applicationName": "",
                "credentialType": "MobilePASS",
                "ip": "8.8.8.8",
                "logType": "AUTHENTICATION",
                "message": "Login from SafeNet Authentication Service Console.",
                "operationObjectName": "",
                "operationObjectType": "",
                "operationType": "",
                "policyName": "",
                "resultText": "CHALLENGE",
                "serial": "1000014514",
                "state": "",
                "timeStamp": "2021-07-22T08:19:05.5905986Z",
                "userName": "demouser"
            },
            {
                "actionText": "AUTH_ATTEMPT",
                "applicationName": "",
                "credentialType": "MobilePASS",
                "ip": "8.8.8.8",
                "logType": "AUTHENTICATION",
                "message": "Login from SafeNet Authentication Service Console.",
                "operationObjectName": "",
                "operationObjectType": "",
                "operationType": "",
                "policyName": "",
                "resultText": "AUTH_SUCCESS",
                "serial": "1000014514",
                "state": "",
                "timeStamp": "2021-07-22T08:20:45.5326006Z",
                "userName": "demouser"
            },
            {
                "actionText": "",
                "applicationName": "",
                "credentialType": "otp",
                "ip": "8.8.8.8",
                "logType": "OPERATOR_LOGIN",
                "message": "",
                "operationObjectName": "",
                "operationObjectType": "",
                "operationType": "",
                "policyName": "",
                "resultText": "",
                "serial": "",
                "state": "Accepted",
                "timeStamp": "2021-07-22T08:20:45.638Z",
                "userName": "demouser"
            }
        ]
    }
}

Human Readable Output

Logs

Time Stamp User Name Log Type Credential Type Action Text Result Text Message State Serial Ip
2021-07-22T08:19:05.5905986Z demouser AUTHENTICATION MobilePASS AUTH_ATTEMPT CHALLENGE Login from SafeNet Authentication Service Console.   1000014514 8.8.8.8
2021-07-22T08:20:45.5326006Z demouser AUTHENTICATION MobilePASS AUTH_ATTEMPT AUTH_SUCCESS Login from SafeNet Authentication Service Console.   1000014514 8.8.8.8
2021-07-22T08:20:45.638Z demouser OPERATOR_LOGIN otp       Accepted   8.8.8.8

sta-validate-tenant


Checks if you have permission to access the requested tenant.

Base Command

sta-validate-tenant

Input

| Argument Name | Description | Required |
| — | — | — |

Context Output

Path Type Description
STA.VALIDATE.TENANT boolean Checks if you have permission to access the requested tenant.

Command Example


#### Context Example

```json
{
    "STA": {
        "VALIDATE": {
            "TENANT": true
        }
    }
}

Human Readable Output

The requested tenant is accessible

sta-get-application-list


Get the list of the applications in the tenant.

Base Command

sta-get-application-list

Input

Argument Name Description Required
limit The maximum number of results to return. Optional

Context Output

Path Type Description
STA.APPLICATION.ID string ID of the application.
STA.APPLICATION.NAME string Name of the application.
STA.APPLICATION.STATUS string Status of the application.

Command Example


#### Context Example

```json
{
    "STA": {
        "APPLICATION": [
            {
                "id": "g444faf1-6d7a-44t2-98c1-43572422b409",
                "name": "Application1",
                "status": "Active"
            },
            {
                "id": "k0de1afc-59ef-66bc-9abd-dacca890a390",
                "name": "Application2",
                "status": "Active"
            }
        ]
    }
}

Human Readable Output

List of applications in the tenant

Id Name Status
g444faf1-6d7a-44t2-98c1-43572422b409 Application1 Active
k0de1afc-59ef-66bc-9abd-dacca890a390 Application2 Active

sta-get-application-info


Get the information for a specific application in the tenant.

Base Command

sta-get-application-info

Input

Argument Name Description Required
applicationName Name of the application. Required

Context Output

Path Type Description
STA.APPLICATION.ID string ID of the application.
STA.APPLICATION.NAME string Name of the application.
STA.APPLICATION.STATUS string Status of the application.
STA.APPLICATION.TYPE string Status of the application.
STA.APPLICATION.TEMPLATE string Name of the template.
STA.APPICATION.ASSIGNMENT string Groups or users authorized to access an application.
STA.APPICATION.SCHEMA string Schema version number.
STA.APPICATION.LASTMODIFIED string Last modified date and time of application.

Command Example

!sta-get-application-info applicationName="Application1"

Context Example

{
    "STA": {
        "APPLICATION": {
            "applicationType": "Saml",
            "assignment": {
                "everyone": true
            },
            "id": "9ccbad94-06c2-4af2-bb9b-af9f811ccfdb",
            "lastModified": "2021-08-27T12:25:47.998Z",
            "name": "Application1",
            "schemaVersionNumber": "1.0",
            "status": "Active",
            "templateName": "Template1"
        }
    }
}

Human Readable Output

Information of application - Application1

Id Name Status Application Type Template Name Assignment Schema Version Number Last Modified
9ccbad94-06c2-4af2-bb9b-af9f811ccfdb Application1 Active Saml Template1 All 1.0 2021-08-27T12:25:47.998Z

sta-get-user-applications


Get the list of the applications assigned to a specific user.

Base Command

sta-get-user-applications

Input

Argument Name Description Required
userName Username of the user. Required
limit The maximum number of results to return. Optional

Context Output

Path Type Description
STA.USER.ID string User ID of the user.
STA.USER.SCHEMA string Schema version number.
STA.USER.USERNAME string Username of the user.
STA.USER.FIRSTNAME string First name of the user.
STA.USER.LASTNAME string Last name of the user.
STA.USER.EMAIL string Email ID of the user.
STA.USER.MOBILENUMBER number Mobile number for the user.
STA.USER.ALIAS1 string Alias for the user.
STA.USER.ALIAS2 string Additional alias for the user.
STA.USER.CUSTOM1 string Custom value for the user.
STA.USER.CUSTOM2 string Additional custom value for the user.
STA.USER.CUSTOM3 string Additional custom value for the user.
STA.USER.ADDRESS string Address of the user.
STA.USER.CITY string City of the user.
STA.USER.STATE string State of the user.
STA.USER.COUNTRY string Country of the user.
STA.USER.POSTALCODE number Postal Code of the user.
STA.USER.SYNCHRONIZED boolean Is user synchronized.
STA.USER.APPLICATION.ID string ID of the application.
STA.USER.APPLICATION.NAME string Name of the application.
STA.USER.APPLICATION.STATUS string Status of the application.

Command Example

!sta-get-user-applications userName="hellouser"

Context Example

{
    "STA": {
        "USER": {
            "applications": [
                {
                    "id": "9570b825-961e-4ed3-aa51-e53b732b16ec",
                    "name": "Application1",
                    "status": "Active"
                },
                {
                    "id": "66df07af-7c95-42e7-b0cd-2e97b6827d59",
                    "name": "Application2",
                    "status": "Active"
                }
            ],
            "email": "test.user@demisto.com",
            "firstName": "Hello",
            "id": "ONksETu5i8cDs0k67bQAAAD9",
            "isSynchronized": false,
            "lastName": "User",
            "schemaVersionNumber": "1.0",
            "userName": "hellouser"
        }
    }
}

Human Readable Output

Applications associated with user - hellouser

Id Name Status
9570b825-961e-4ed3-aa51-e53b732b16ec Application1 Active
66df07af-7c95-42e7-b0cd-2e97b6827d59 Application2 Active

sta-get-user-sessions


Get sessions for a specific user.

Base Command

sta-get-user-sessions

Input

Argument Name Description Required
userName Username of the user. Required

Context Output

Path Type Description
STA.USER.ID string User ID of the user.
STA.USER.SCHEMA string Schema version number.
STA.USER.USERNAME string Username of the user.
STA.USER.FIRSTNAME string First name of the user.
STA.USER.LASTNAME string Last name of the user.
STA.USER.EMAIL string Email ID of the user.
STA.USER.MOBILENUMBER number Mobile number for the user.
STA.USER.ALIAS1 string Alias for the user.
STA.USER.ALIAS2 string Additional alias for the user.
STA.USER.CUSTOM1 string Custom value for the user.
STA.USER.CUSTOM2 string Additional custom value for the user.
STA.USER.CUSTOM3 string Additional custom value for the user.
STA.USER.ADDRESS string Address of the user.
STA.USER.CITY string City of the user.
STA.USER.STATE string State of the user.
STA.USER.COUNTRY string Country of the user.
STA.USER.POSTALCODE number Postal Code of the user.
STA.USER.SYNCHRONIZED boolean Is user synchronized.
STA.USER.SESSION.ID string Session ID for the user.
STA.USER.SESSION.START string Session start timestamp.
STA.USER.SESSION.EXPIRY string Session end timestamp.
STA.USER.SESSION.APPLICATION.ID string Name of the application.
STA.USER.SESSION.APPLICATION.NAME boolean Returns true, if the user session is deleted for an application.

Command Example

!sta-get-user-sessions userName="hellouser"

Context Example

{
    "STA": {
        "USER": {
            "email": "test.user@demisto.com",
            "firstName": "Hello",
            "id": "ONksETu5i8cDs0k67bQAAAD9",
            "isSynchronized": false,
            "lastName": "User",
            "schemaVersionNumber": "1.0",
            "sessions": [
                {
                    "applications": [
                        {
                            "id": "entity-id1",
                            "name": "Application1"
                        },
                        {
                            "id": "entity-id2",
                            "name": "Application2"
                        }
                    ],
                    "expiry": 1633086960,
                    "id": "86f4593d-fb8a-4f62-byd9-ceb833a8090b",
                    "start": 1633079752
                }
            ],
            "userName": "hellouser"
        }
    }
}

Human Readable Output

Sessions associated with user - hellouser

Id Start Expiry Applications
86f4593d-fb8a-4f62-byd9-ceb833a8090b 1633079752 1633086960 Application1, Application2

sta-delete-user-sessions


Delete all the active SSO sessions for a specific user from STA.

Base Command

sta-delete-user-sessions

Input

Argument Name Description Required
userName Username of the user. Required

Context Output

Path Type Description
STA.USER.ID string User ID of the user.
STA.USER.USERNAME string Username of the user.
STA.USER.SESSION.DELETED boolean Returns true, if all the user SSO sessions are deleted successfully.

Command Example

!sta-delete-user-sessions userName="hellouser"

Context Example

{
    "STA": {
        "USER": {
            "id": "",
            "sessions": {
                "Deleted": true
            },
            "userName": "hellouser"
        }
    }
}

Human Readable Output

IDP Sessions for the user - hellouser successfully deleted

Configuration parameters

  • url — URL (required)
  • tenant_code — Tenant Code (required)
  • api_key — API Key (required)
  • insecure — Trust any certificate (not secure)
  • proxy — Use system proxy settings

Commands (22)

  • sta-add-user-group

    Add user to a specific group.

  • sta-create-group

    Create a new group in the tenant.

  • sta-create-user

    Create a new user in the tenant.

  • sta-delete-group

    Delete group from the tenant.

  • sta-delete-user

    Delete user from the tenant.

  • sta-delete-user-sessions

    Delete all the active SSO sessions for a specific user from the STA.

  • sta-get-application-info

    Get the information for a specific application in the tenant.

  • sta-get-application-list

    Get the list of the applications in the tenant.

  • sta-get-group-info

    Get information for a specific group.

  • sta-get-group-list

    Get list of groups in the tenant.

  • sta-get-group-members

    Get list of users in a specific group.

  • sta-get-logs

    Get access, authentication, and audit logs.

  • sta-get-user-applications

    Get the list of the applications assigned to a specific user.

  • sta-get-user-groups

    Return all the groups associated with a specific user.

  • sta-get-user-info

    Get the profile information for a specific user.

  • sta-get-user-list

    Get list of users in the tenant.

  • sta-get-user-sessions

    Get sessions for a specific user.

  • sta-remove-user-group

    Remove user from a group.

  • sta-update-group-info

    Update information for a specific group.

  • sta-update-user-info

    Update the profile for a specific user.

  • sta-user-exist-group

    Check if user exists in a specific group.

  • sta-validate-tenant

    Checks if you have permission to access the requested tenant.

import copy
import json
import re
import traceback
from datetime import datetime
from typing import Any
from urllib.parse import quote_plus

import demistomock as demisto  # noqa: F401
import urllib3
from CommonServerPython import *  # noqa: F401

# Disable insecure warnings
urllib3.disable_warnings()

""" CONSTANTS """


NO_RESULT_MSG = "No results found for the command."

""" CLIENT CLASS """


class Client(BaseClient):
    """
    Client will implement the service API, and should not contain any Demisto logic.
    Should only do requests and return data.
    """

    # Sends request to API Endpoint URL using _http_request() method.
    def http_request(
        self, method, url_suffix, data=None, headers=None, json_data=None, params=None, full_url=None, resp_type="response"
    ):
        return self._http_request(
            method=method,
            url_suffix=url_suffix,
            data=data,
            headers=headers,
            resp_type=resp_type,
            json_data=json_data,
            params=params,
            full_url=full_url,
        )

    # Validate limit value
    def validate_limit_sta(self, limit):
        limit = arg_to_number(arg=limit)
        if limit not in range(1, 10001):
            raise Exception("Limit must be between 1 to 10000.")
        return limit

    # Validate date value
    def validate_date_sta(self, datestring):
        pattern = re.compile("[0-9]{4}-[0-9]{2}-[0-9]{2}T([0-9]{2}:){2}[0-9]{2}.[0-9]{3}Z")
        if re.match(pattern, datestring):
            try:
                datetime.fromisoformat(datestring.replace("Z", "+00:00"))
                return datestring
            except DemistoException as e:
                raise Exception(f"Please enter a valid date. \nError:\n{e!s}")
        raise Exception("Date must be in format yyyy-mm-ddTHH:mm:ss.fffZ \nExample: 2021-05-16T02:30:00.234Z")

    # Validate mandatory argument.
    def validate_mandatory_argument_sta(self, fields={}):
        for key, value in fields.items():
            if not value or value == "":
                raise Exception(f"Please provide the value for {key}.")

    # Get paginated results from API endpoint URL.
    def get_paged_results_sta(self, uri, query_params=None, limit=None):
        response = self.http_request(method="GET", url_suffix=uri, params=query_params)
        request_count = 1
        quotient = 0
        if limit:
            items_count = len(response.json()["page"]["items"])
            quotient = limit // items_count
            reminder = limit % items_count
        else:
            reminder = 0
            demisto.debug(f"{limit=} -> {reminder=}")
        paged_results = response.json()["page"]["items"]

        while "next" in response.json()["links"] and len(response.json()["page"]["items"]) > 0:
            if request_count >= 10:
                raise Exception(
                    "You have reached the maximum number of request attempts."
                    " Please use the limit argument to get the required result."
                )

            next_page = response.json()["links"]["next"]
            if quotient == request_count:
                query_params = (
                    ("pageIndex", quotient),
                    ("pageSize", reminder),
                )
                response = self.http_request(method="GET", url_suffix=uri, params=query_params)
                paged_results += response.json()["page"]["items"]
                break

            response = self.http_request(method="GET", full_url=next_page, url_suffix="", params=query_params)
            request_count = request_count + 1
            paged_results += response.json()["page"]["items"]

        return paged_results

    # Get list of all the users in the tenant.
    def get_userlist_sta(self, limit=None):
        uri = "/users"
        if limit:
            limit = self.validate_limit_sta(limit)
            if limit <= 100:
                query_params = (
                    ("pageIndex", 0),
                    ("pageSize", limit),
                )
                return self.http_request(
                    method="GET",
                    url_suffix=uri,
                    params=query_params,
                ).json()["page"]["items"]
            else:
                return self.get_paged_results_sta(uri=uri, limit=limit)
        else:
            return self.get_paged_results_sta(uri=uri)

    # Get profile information of a specific user.
    def get_user_info_sta(self, userName):
        self.validate_mandatory_argument_sta(fields={"username": userName})
        return self.http_request(
            method="GET",
            url_suffix=urljoin("/users/", quote_plus(userName)),
        ).json()

    # Get information of a group in a tenant.
    def get_group_info_sta(self, groupName):
        self.validate_mandatory_argument_sta(fields={"group": groupName})
        response = self.http_request(
            method="GET",
            url_suffix="/groups",
        )
        paged_results = response.json()["page"]["items"]
        while "next" in response.json()["links"] and len(response.json()["page"]["items"]) > 0:
            next_page = response.json()["links"]["next"]
            response = self.http_request(
                method="GET",
                full_url=next_page,
                url_suffix="",
            )
            paged_results += response.json()["page"]["items"]
        for group in paged_results:
            if group["name"] == groupName:
                return group
        raise Exception(f"The group {groupName} was not found.")

    # Create a new user in the tenant.
    def create_user_sta(self, args):
        data = {
            "userName": args.get("userName"),
            "firstName": args.get("first_name"),
            "lastName": args.get("last_name"),
            "email": args.get("email"),
            "mobileNumber": args.get("mobile_number"),
            "alias1": args.get("alias1"),
            "alias2": args.get("alias2"),
            "custom1": args.get("custom1"),
            "custom2": args.get("custom2"),
            "custom3": args.get("custom3"),
            "address": args.get("address"),
            "city": args.get("city"),
            "state": args.get("state"),
            "country": args.get("country"),
            "postalCode": args.get("postal_code"),
            "isSynchronized": args.get("synchronized"),
        }

        return self.http_request(method="POST", url_suffix="/users", data=json.dumps(data)).json()

    # Update profile of a specific user.
    def update_user_sta(self, args):
        data = {}
        if args.get("userName_new") is not None:
            data["userName"] = args.get("userName_new")
        if args.get("first_name") is not None:
            data["firstName"] = args.get("first_name")
        if args.get("last_name") is not None:
            data["lastName"] = args.get("last_name")
        if args.get("email") is not None:
            data["email"] = args.get("email")
        if args.get("mobile_number") is not None:
            data["mobileNumber"] = args.get("mobile_number")
        if args.get("alias1") is not None:
            data["alias1"] = args.get("alias1")
        if args.get("alias2") is not None:
            data["alias2"] = args.get("alias2")
        if args.get("address") is not None:
            data["address"] = args.get("address")
        if args.get("city") is not None:
            data["city"] = args.get("city")
        if args.get("state") is not None:
            data["state"] = args.get("state")
        if args.get("country") is not None:
            data["country"] = args.get("country")
        if args.get("postal_code") is not None:
            data["postalCode"] = args.get("postal_code")

        return self.http_request(
            method="PATCH", url_suffix=urljoin("/users/", quote_plus(args.get("userName"))), data=json.dumps(data)
        ).json()

    # Get user ID from username.
    def get_user_id_sta(self, userName):
        return self.get_user_info_sta(userName=userName)["id"]

    # Get group ID from groupname.
    def get_group_id_sta(self, groupName):
        return self.get_group_info_sta(groupName=groupName)["id"]

    # Delete user from the tenant.
    def delete_user_sta(self, userName):
        user_id = self.get_user_id_sta(userName=userName)
        self.http_request(
            method="DELETE",
            url_suffix=urljoin("/users/", quote_plus(userName)),
        )
        return {"id": user_id, "userName": userName, "Deleted": True}

    # Get all the groups associated with a specific user.
    def get_user_groups_sta(self, userName, limit=None):
        user_id = self.get_user_id_sta(userName=userName)
        uri = urljoin(urljoin("/users/", quote_plus(user_id)), "/groups")

        if limit:
            limit = self.validate_limit_sta(limit)
            if limit <= 100:
                query_params = (
                    ("pageIndex", 0),
                    ("pageSize", limit),
                )
                return self.http_request(
                    method="GET",
                    url_suffix=uri,
                    params=query_params,
                ).json()["page"]["items"]

            else:
                return self.get_paged_results_sta(uri=uri, limit=limit)

        else:
            return self.get_paged_results_sta(uri=uri)

    # Returns output data for group members.
    def user_groups_data(self, userName, limit=None):
        response = self.get_user_groups_sta(userName=userName, limit=limit)
        data = self.get_user_info_sta(userName=userName)
        data["groups"] = response

        return response, data

    # Get list of groups in the tenant.
    def get_group_list_sta(self, limit=None):
        uri = "/groups"
        if limit:
            limit = self.validate_limit_sta(limit)
            if limit <= 100:
                query_params = (
                    ("pageIndex", 0),
                    ("pageSize", limit),
                )
                return self.http_request(
                    method="GET",
                    url_suffix=uri,
                    params=query_params,
                ).json()["page"]["items"]
            else:
                return self.get_paged_results_sta(uri=uri, limit=limit)
        else:
            return self.get_paged_results_sta(uri=uri)

    # Get list of all the users in a group.
    def get_group_members_sta(self, groupName, limit=None):
        group_id = self.get_group_id_sta(groupName=groupName)
        uri = urljoin(urljoin("/groups/", quote_plus(group_id)), "/members")

        if limit:
            limit = self.validate_limit_sta(limit)
            if limit <= 100:
                query_params = (
                    ("pageIndex", 0),
                    ("pageSize", limit),
                )
                return self.http_request(
                    method="GET",
                    url_suffix=uri,
                    params=query_params,
                ).json()["page"]["items"]
            else:
                return self.get_paged_results_sta(uri=uri, limit=limit)
        else:
            return self.get_paged_results_sta(uri=uri)

    # Returns output data for group members.
    def group_members_data(self, groupName, limit=None):
        response = self.get_group_members_sta(groupName=groupName, limit=limit)
        data = self.get_group_info_sta(groupName=groupName)
        data["users"] = response

        return response, data

    # Create a group in the tenant.
    def create_group_sta(self, args):
        data = {
            "name": args.get("groupName"),
            "description": args.get("description"),
            "isSynchronized": args.get("synchronized"),
        }

        return self.http_request(method="POST", url_suffix="/groups", data=json.dumps(data)).json()

    # Delete a group from the tenant.
    def delete_group_sta(self, groupName):
        group_id = self.get_group_id_sta(groupName=groupName)
        self.http_request(
            method="DELETE",
            url_suffix=urljoin("/groups/", quote_plus(group_id)),
        )
        return {"id": group_id, "groupName": groupName, "Deleted": True}

    # Update information of a specific group.
    def update_group_sta(self, args):
        group_id = self.get_group_id_sta(groupName=args.get("groupName"))
        data = {}
        if args.get("groupName_new") is not None:
            data["name"] = args.get("groupName_new")
        if args.get("description") is not None:
            data["description"] = args.get("description")

        return self.http_request(
            method="PATCH", url_suffix=urljoin("/groups/", quote_plus(group_id)), data=json.dumps(data)
        ).json()

    # Check if a user exist in a group.
    def user_exist_group_sta(self, userName, groupName):
        user_id = self.get_user_id_sta(userName=userName)
        group_id = self.get_group_id_sta(groupName=groupName)

        user_groups = self.http_request(
            method="GET",
            url_suffix=urljoin(urljoin("/users/", quote_plus(user_id)), "/groups"),
        ).json()["page"]["items"]

        if user_groups is not None:
            for group in user_groups:
                if group["id"] == group_id:
                    return True

        return False

    # Add user in a group.
    def add_user_group_sta(self, userName, groupName):
        if self.user_exist_group_sta(userName=userName, groupName=groupName) is False:
            user_id = self.get_user_id_sta(userName=userName)
            group_id = self.get_group_id_sta(groupName=groupName)
            data = {
                "id": user_id,
                "type": "User",
            }
            self.http_request(
                method="POST",
                url_suffix=urljoin(urljoin("/groups/", quote_plus(group_id)), "/members"),
                data=json.dumps(data),
            )
            return {"user_id": user_id, "userName": userName, "group_id": group_id, "groupName": groupName, "status": True}
        else:
            raise Exception(f"Username - {userName} is already a member of the group - {groupName}.")

    # Remove user from a group.
    def remove_user_group_sta(self, userName, groupName):
        if self.user_exist_group_sta(userName=userName, groupName=groupName) is True:
            user_id = self.get_user_id_sta(userName=userName)
            group_id = self.get_group_id_sta(groupName=groupName)

            self.http_request(
                method="DELETE",
                url_suffix=urljoin(urljoin(urljoin("/groups/", quote_plus(group_id)), "/members/"), quote_plus(user_id)),
            )
            return {"user_id": user_id, "userName": userName, "group_id": group_id, "groupName": groupName, "status": False}
        else:
            raise Exception(f"Username - {userName} is not a member of the group - {groupName}.")

    # Creates a log's attribute dictionary from API's response data.
    def logs_attributes_sta(self, response):
        logs_attributes = {
            "timeStamp": response["timeStamp"],
            "userName": response["context"]["principalId"],
            "logType": response["details"]["type"],
            "ip": response["context"]["originatingAddress"],
            "credentialType": "",
            "resultText": "",
            "actionText": "",
            "applicationName": "",
            "policyName": "",
            "state": "",
            "operationType": "",
            "operationObjectType": "",
            "operationObjectName": "",
            "message": "",
            "serial": "",
        }
        if "credentialType" in response["details"]:
            logs_attributes["credentialType"] = response["details"]["credentialType"]
        elif "credentials" in response["details"]:
            logs_attributes["credentialType"] = response["details"]["credentials"][0]["type"]
        if "resultText" in response["details"]:
            logs_attributes["resultText"] = response["details"]["resultText"]
        if "actionText" in response["details"]:
            logs_attributes["actionText"] = response["details"]["actionText"]
        if "applicationName" in response["context"]:
            logs_attributes["applicationName"] = response["context"]["applicationName"]
        if "policyName" in response["context"]:
            logs_attributes["policyName"] = response["context"]["policyName"]
        if "state" in response["details"]:
            logs_attributes["state"] = response["details"]["state"]
        if "operationType" in response["details"]:
            logs_attributes["operationType"] = response["details"]["operationType"]
        if "operationObjectType" in response["details"]:
            logs_attributes["operationObjectType"] = response["details"]["operationObjectType"]
        if "operationObjectName" in response["details"]:
            logs_attributes["operationObjectName"] = response["details"]["operationObjectName"]
        if "message" in response["details"]:
            logs_attributes["message"] = response["details"]["message"]
        elif "description" in response["details"]:
            logs_attributes["message"] = response["details"]["description"]
        if "serial" in response["details"]:
            logs_attributes["serial"] = response["details"]["serial"]

        return logs_attributes

    # Filter out the required data from total items as per limit and userName argument.
    def logs_data_filter_sta(self, total_items, userName=None, limit=None, count=1, logs_items=None):
        if logs_items is None:
            logs_items = []
        if userName:
            for response in total_items:
                if "principalId" in response["context"] and response["context"]["principalId"] == userName:
                    if limit:
                        if limit >= count:
                            count = count + 1
                        else:
                            break
                    logs_items.append(self.logs_attributes_sta(response=response))

        else:
            for response in total_items:
                if "principalId" in response["context"]:
                    if limit:
                        if limit >= count:
                            count = count + 1
                        else:
                            break
                    logs_items.append(self.logs_attributes_sta(response=response))

        return logs_items, count

    # Get user's logs.
    def get_logs_sta(self, userName=None, since=None, until=None, limit=None):
        uri = "/logs"
        query_params = {}
        if userName:
            self.get_user_info_sta(userName=userName)
        if since:
            query_params["since"] = self.validate_date_sta(datestring=since)
        if until:
            query_params["until"] = self.validate_date_sta(datestring=until)
        if since and until and until <= since:
            raise Exception("Until argument's date and time must be greater than since.")
        if not since and until:
            raise Exception("Use until argument only while using since.")

        query_params = tuple(query_params.items())
        response = self.http_request(
            method="GET",
            url_suffix=uri,
            params=query_params,
        )
        if since and not limit:
            limit = 10000

        if limit:
            limit = self.validate_limit_sta(limit)
            request_count = 1
            paged_results, count = self.logs_data_filter_sta(response.json()["page"]["items"], userName=userName, limit=limit)
            while "next" in response.json()["links"] and len(response.json()["page"]["items"]) > 0 and limit >= count:
                if request_count >= 10:
                    if userName:
                        break
                    raise Exception(
                        "You have reached the maximum number of request attempts."
                        " Please use either the since or until argument to get the required result."
                    )

                next_page = response.json()["links"]["next"]
                response = self.http_request(
                    method="GET",
                    full_url=next_page,
                    url_suffix="",
                )

                request_count = request_count + 1
                paged_results, count = self.logs_data_filter_sta(
                    response.json()["page"]["items"], userName=userName, limit=limit, count=count, logs_items=paged_results
                )
        else:
            paged_results = self.logs_data_filter_sta(response.json()["page"]["items"], userName)[0]

        return paged_results

    # Validate tenant and permission.
    def validate_tenant_sta(self):
        return self.http_request(method="GET", url_suffix="/authorized")

    # Get list of all the applications in the tenant.
    def get_application_list_sta(self, limit=None):
        uri = "/applications"
        if limit:
            limit = self.validate_limit_sta(limit)
            if limit <= 100:
                query_params = (
                    ("pageIndex", 0),
                    ("pageSize", limit),
                )
                return self.http_request(
                    method="GET",
                    url_suffix=uri,
                    params=query_params,
                ).json()["page"]["items"]
            else:
                return self.get_paged_results_sta(uri=uri, limit=limit)
        else:
            return self.get_paged_results_sta(uri=uri)

    # Returns basic information of an application if exist in the tenant.
    def get_basic_application_info_sta(self, applicationName):
        self.validate_mandatory_argument_sta(fields={"applicationName": applicationName})
        response = self.http_request(
            method="GET",
            url_suffix="/applications",
        )
        paged_results = response.json()["page"]["items"]
        while "next" in response.json()["links"] and len(response.json()["page"]["items"]) > 0:
            next_page = response.json()["links"]["next"]
            response = self.http_request(
                method="GET",
                full_url=next_page,
                url_suffix="",
            )
            paged_results += response.json()["page"]["items"]
        for application in paged_results:
            if application["name"] == applicationName:
                return application
        raise Exception(f"The application - {application} was not found.")

    # Get application id of an application.
    def get_application_id_sta(self, applicationName):
        return self.get_basic_application_info_sta(applicationName=applicationName)["id"]

    # Get information for a specific application.
    def get_application_info_sta(self, applicationName):
        application_id = self.get_application_id_sta(applicationName=applicationName)
        response = self.http_request(method="GET", url_suffix=urljoin("/applications/", quote_plus(application_id))).json()

        context_data = {
            "id": response["id"],
            "name": response["name"],
            "status": response["status"],
            "applicationType": response["applicationType"],
            "templateName": response["templateName"],
            "assignment": response["assignment"],
            "schemaVersionNumber": response["schemaVersionNumber"],
            "lastModified": response["lastModified"],
        }
        readable_output = dict(context_data)
        if "everyone" in readable_output["assignment"]:
            if readable_output["assignment"]["everyone"] is True:
                readable_output["assignment"] = "All"
            else:
                readable_output["assignment"] = "None"
        elif "groups" in readable_output["assignment"]:
            readable_output["assignment"] = ", ".join(readable_output["assignment"]["groups"])

        return readable_output, context_data

    # Get the list of applications assigned to a user.
    def get_user_applications_sta(self, userName, limit=None):
        user_id = self.get_user_id_sta(userName=userName)
        uri = urljoin(urljoin("/users/", quote_plus(user_id)), "/applications")

        if limit:
            limit = self.validate_limit_sta(limit)
            if limit <= 1000:
                query_params = (
                    ("pageIndex", 0),
                    ("pageSize", limit),
                )
                return self.http_request(
                    method="GET",
                    url_suffix=uri,
                    params=query_params,
                ).json()["page"]["items"]

            else:
                return self.get_paged_results_sta(uri=uri, limit=limit)

        else:
            return self.get_paged_results_sta(uri=uri)

    # Returns output data for group members.
    def user_applications_data(self, userName, limit=None):
        response = self.get_user_applications_sta(userName=userName, limit=limit)
        data = self.get_user_info_sta(userName=userName)
        data["applications"] = response

        return response, data

    # Get the sessions for a specific user.
    def get_user_sessions_sta(self, userName):
        user_id = self.get_user_id_sta(userName=userName)
        uri = urljoin(urljoin("/users/", quote_plus(user_id)), "/sessions")

        return self.http_request(
            method="GET",
            url_suffix=uri,
        ).json()["sessions"]

    # Returns output data for group members.
    def user_sessions_data(self, userName):
        data = self.get_user_info_sta(userName=userName)
        response = self.get_user_sessions_sta(userName=userName)
        data["sessions"] = copy.deepcopy(response)
        if response:
            numb = 0
            for session in response:
                session["start"] = datetime.fromtimestamp(session["start"]).strftime("%Y-%m-%dT%H:%M:%S.000Z")
                session["expiry"] = datetime.fromtimestamp(session["expiry"]).strftime("%Y-%m-%dT%H:%M:%S.000Z")
                applications = []
                for application in session["applications"]:
                    applications.append(application["name"])

                if applications:
                    response[numb]["applications"] = ", ".join(applications)
                else:
                    response[numb]["applications"] = "No applications."
                numb = numb + 1

        return response, data

    # Delete all the IDP session for a specific user.
    def delete_sessions_sta(self, userName):
        user_id = self.get_user_id_sta(userName=userName)
        self.http_request(
            method="DELETE",
            url_suffix=urljoin(urljoin("/users/", quote_plus(user_id)), "/sessions"),
        )
        data = {"id": user_id, "userName": userName, "sessions": {"Deleted": True}}

        return data


""" COMMAND FUNCTIONS """


def test_module(client, args):
    """
    Returning 'ok' indicates that the integration works like it is supposed to. Connection to the service is successful.

    Args:
        client: SafeNet Trusted Access

    Returns:
        'ok' if test passed, anything else will fail the test.
    """

    try:
        client._http_request(method="GET", url_suffix="/users")
    except DemistoException as e:
        if "Forbidden" in str(e):
            return "Authorization Error: Ensure that the API key is correct."
        else:
            raise e
    return "ok"


def get_userlist_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-get-user-list command. Get list of all the users in the tenant."""

    response = client.get_userlist_sta(limit=args.get("limit"))
    if not response:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )
    header_sequence = [
        "id",
        "schemaVersionNumber",
        "userName",
        "firstName",
        "lastName",
        "email",
        "mobileNumber",
        "alias1",
        "alias2",
        "alias3",
        "alias4",
        "address",
        "city",
        "state",
        "country",
        "postalCode",
        "isSynchronized",
    ]
    return CommandResults(
        readable_output=tableToMarkdown(
            "List of users in the tenant :", response, headers=header_sequence, headerTransform=pascalToSpace, removeNull=True
        ),
        outputs_prefix="STA.USER",
        outputs_key_field=["id"],
        outputs=response,
    )


def get_user_info_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-get-user-info command. Get profile information of a specific user."""

    response = client.get_user_info_sta(userName=args.get("userName"))
    if not response:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )
    header_sequence = [
        "id",
        "schemaVersionNumber",
        "userName",
        "firstName",
        "lastName",
        "email",
        "mobileNumber",
        "alias1",
        "alias2",
        "alias3",
        "alias4",
        "custom1",
        "custom2",
        "custom3",
        "address",
        "city",
        "state",
        "country",
        "postalCode",
        "isSynchronized",
    ]

    return CommandResults(
        readable_output=tableToMarkdown(
            f"Information for user - {args.get('userName')} :",
            response,
            headers=header_sequence,
            headerTransform=pascalToSpace,
            removeNull=True,
        ),
        outputs_prefix="STA.USER",
        outputs_key_field=["id"],
        outputs=response,
    )


def create_user_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-create-user command. Create a new user in the tenant."""

    response = client.create_user_sta(args=args)
    if not response:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )
    header_sequence = [
        "id",
        "schemaVersionNumber",
        "userName",
        "firstName",
        "lastName",
        "email",
        "mobileNumber",
        "alias1",
        "alias2",
        "custom1",
        "custom2",
        "custom3",
        "address",
        "city",
        "state",
        "country",
        "postalCode",
        "isSynchronized",
    ]

    return CommandResults(
        readable_output=tableToMarkdown(
            "STA user successfully created :", response, headers=header_sequence, headerTransform=pascalToSpace, removeNull=True
        ),
        outputs_prefix="STA.USER",
        outputs_key_field=["id"],
        outputs=response,
    )


def update_user_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-update-user-info command. Update profile of a specific user."""

    response = client.update_user_sta(args=args)
    if not response:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )
    header_sequence = [
        "id",
        "schemaVersionNumber",
        "userName",
        "firstName",
        "lastName",
        "email",
        "mobileNumber",
        "alias1",
        "alias2",
        "custom1",
        "custom2",
        "custom3",
        "address",
        "city",
        "state",
        "country",
        "postalCode",
        "isSynchronized",
    ]

    return CommandResults(
        readable_output=tableToMarkdown(
            "STA user successfully updated:", response, headers=header_sequence, headerTransform=pascalToSpace, removeNull=True
        ),
        outputs_prefix="STA.USER",
        outputs_key_field=["id"],
        outputs=response,
    )


def delete_user_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-delete-user command. Delete user from the tenant."""

    response = client.delete_user_sta(userName=args.get("userName"))
    if not response:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )
    return CommandResults(
        readable_output=f"## STA user - {args.get('userName')} successfully deleted.",
        outputs_prefix="STA.USER",
        outputs_key_field=["id"],
        outputs=response,
    )


def get_user_groups_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-get-user-groups command. Get all the groups associated with a specific user."""

    response, output_data = client.user_groups_data(userName=args.get("userName"), limit=args.get("limit"))
    if not response:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )
    header_sequence = ["id", "schemaVersionNumber", "name", "description", "isSynchronized"]
    return CommandResults(
        readable_output=tableToMarkdown(
            f"Groups associated with user - {args.get('userName')} : ",
            response,
            headers=header_sequence,
            headerTransform=pascalToSpace,
            removeNull=True,
        ),
        outputs_prefix="STA.USER",
        outputs_key_field=["id"],
        outputs=output_data,
    )


def get_group_list_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-get-group-list command. Get list of all the groups in the tenant."""

    response = client.get_group_list_sta(limit=args.get("limit"))
    if not response:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )
    header_sequence = ["id", "schemaVersionNumber", "name", "description", "isSynchronized"]
    return CommandResults(
        readable_output=tableToMarkdown(
            "STA groups in the tenant : ", response, headers=header_sequence, headerTransform=pascalToSpace, removeNull=True
        ),
        outputs_prefix="STA.GROUP",
        outputs_key_field=["id"],
        outputs=response,
    )


def get_group_info_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-get-group-info command. Get information of a specific group."""

    response = client.get_group_info_sta(groupName=args.get("groupName"))
    if not response:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )
    header_sequence = ["id", "schemaVersionNumber", "name", "description", "isSynchronized"]
    return CommandResults(
        readable_output=tableToMarkdown(
            f"Group - {args.get('groupName')} :",
            response,
            headers=header_sequence,
            headerTransform=pascalToSpace,
            removeNull=True,
        ),
        outputs_prefix="STA.GROUP",
        outputs_key_field=["id"],
        outputs=response,
    )


def get_group_members_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-get-group-members command. Get list of users in a specific group."""

    response, output_data = client.group_members_data(groupName=args.get("groupName"), limit=args.get("limit"))
    if not response:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )
    header_sequence = ["id", "name", "type"]

    return CommandResults(
        readable_output=tableToMarkdown(
            f"Members of group - {args.get('groupName')} : ",
            response,
            headers=header_sequence,
            headerTransform=pascalToSpace,
            removeNull=True,
        ),
        outputs_prefix="STA.GROUP",
        outputs_key_field=["id"],
        outputs=output_data,
    )


def create_group_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-create-group command. Create a new group in the tenant."""

    response = client.create_group_sta(args=args)
    if not response:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )
    header_sequence = ["id", "schemaVersionNumber", "name", "description", "isSynchronized"]
    return CommandResults(
        readable_output=tableToMarkdown(
            f"STA group - {args.get('groupName')} successfully created:",
            response,
            headers=header_sequence,
            headerTransform=pascalToSpace,
            removeNull=True,
        ),
        outputs_prefix="STA.GROUP",
        outputs_key_field=["id"],
        outputs=response,
    )


def delete_group_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-delete-group command. Delete group from the tenant."""

    response = client.delete_group_sta(groupName=args.get("groupName"))
    if not response:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )
    return CommandResults(
        readable_output=f"## STA group - {args.get('groupName')} successfully deleted.",
        outputs_prefix="STA.GROUP",
        outputs_key_field=["id"],
        outputs=response,
    )


def update_group_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-update-group-info command. Update information of a specific group."""

    response = client.update_group_sta(args=args)
    if not response:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )
    header_sequence = ["id", "schemaVersionNumber", "name", "description", "isSynchronized"]
    return CommandResults(
        readable_output=tableToMarkdown(
            "STA user successfully updated :", response, headers=header_sequence, headerTransform=pascalToSpace, removeNull=True
        ),
        outputs_prefix="STA.GROUP",
        outputs_key_field=["id"],
        outputs=response,
    )


def user_exist_group_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-user-exist-group command. Checks if a user is a member of a specific group."""

    response = client.user_exist_group_sta(userName=args.get("userName"), groupName=args.get("groupName"))
    if response is True:
        return CommandResults(
            readable_output=f"## Yes, user - {args.get('userName')} is a member of group - {args.get('groupName')}.",
            outputs_prefix="STA.EXIST.USER.GROUP",
            outputs=response,
        )
    else:
        return CommandResults(
            readable_output=f"## No, user - {args.get('userName')} is not a member of group - {args.get('groupName')}.",
            outputs_prefix="STA.EXIST.USER.GROUP",
            outputs=response,
        )


def add_user_group_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-add-user-group command. Add user to a specific group."""

    response = client.add_user_group_sta(userName=args.get("userName"), groupName=args.get("groupName"))
    if not response:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )

    return CommandResults(
        readable_output=f"## User - {args.get('userName')} successfully added to the group - {args.get('groupName')}.",
        outputs_prefix="STA.UPDATE.USER.GROUP",
        outputs_key_field=["user_id", "group_id"],
        outputs=response,
    )


def remove_user_group_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-remove-user-group command. Remove user from a specific group."""

    response = client.remove_user_group_sta(userName=args.get("userName"), groupName=args.get("groupName"))
    if not response:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )

    return CommandResults(
        readable_output=f"## User - {args.get('userName')} successfully removed from the group - {args.get('groupName')}.",
        outputs_prefix="STA.UPDATE.USER.GROUP",
        outputs_key_field=["user_id", "group_id"],
        outputs=response,
    )


def get_logs_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-get-logs command. Get user's logs."""

    response = client.get_logs_sta(
        userName=args.get("userName"), since=args.get("since"), until=args.get("until"), limit=args.get("limit")
    )
    if not response:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )
    header_sequence = [
        "timeStamp",
        "userName",
        "logType",
        "credentialType",
        "actionText",
        "resultText",
        "message",
        "applicationName",
        "policyName",
        "state",
        "operationType",
        "operationObjectType",
        "operationObjectName",
        "serial",
        "ip",
    ]

    return CommandResults(
        readable_output=tableToMarkdown(
            "Logs : ", response, headers=header_sequence, headerTransform=pascalToSpace, removeNull=True
        ),
        outputs_prefix="STA.LOGS",
        outputs=response,
    )


def validate_tenant_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-validate-tenant command. Validate key and permissions."""

    client.validate_tenant_sta()
    return CommandResults(
        readable_output="## The requested tenant is accessible.", outputs_prefix="STA.VALIDATE.TENANT", outputs=True
    )


def get_application_list_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-get-application-list command. Get list of all the applications in the tenant."""

    response = client.get_application_list_sta(limit=args.get("limit"))
    if not response:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )
    header_sequence = ["id", "name", "status"]
    return CommandResults(
        readable_output=tableToMarkdown(
            "List of applications in the tenant :",
            response,
            headers=header_sequence,
            headerTransform=pascalToSpace,
            removeNull=True,
        ),
        outputs_prefix="STA.APPLICATION",
        outputs_key_field=["id"],
        outputs=response,
    )


def get_application_info_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-get-application-info command. Get profile information of a specific application."""

    readable_output, context_data = client.get_application_info_sta(applicationName=args.get("applicationName"))
    if not context_data:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )
    header_sequence = [
        "id",
        "name",
        "status",
        "applicationType",
        "templateName",
        "assignment",
        "schemaVersionNumber",
        "lastModified",
    ]

    return CommandResults(
        readable_output=tableToMarkdown(
            f"Information of application - {args.get('applicationName')} :",
            readable_output,
            headers=header_sequence,
            headerTransform=pascalToSpace,
            removeNull=True,
        ),
        outputs_prefix="STA.APPLICATION",
        outputs_key_field=["id"],
        outputs=context_data,
    )


def get_user_applications_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-get-user-applications. Get all the applications associated with a specific user."""

    response, output_data = client.user_applications_data(userName=args.get("userName"), limit=args.get("limit"))
    if not response:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )
    header_sequence = ["id", "name", "status"]
    return CommandResults(
        readable_output=tableToMarkdown(
            f"Applications associated with user - {args.get('userName')} : ",
            response,
            headers=header_sequence,
            headerTransform=pascalToSpace,
            removeNull=True,
        ),
        outputs_prefix="STA.USER",
        outputs_key_field=["id"],
        outputs=output_data,
    )


def get_user_sessions_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-get-user-sessions command. Get all the sessions associated with a specific user."""

    response, output_data = client.user_sessions_data(userName=args.get("userName"))
    if not response:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )
    session_header = ["id", "start", "expiry", "applications"]
    session_data = tableToMarkdown(
        f"Sessions associated with user - {args.get('userName')} : ",
        response,
        headers=session_header,
        headerTransform=pascalToSpace,
        removeNull=True,
    )

    return CommandResults(readable_output=session_data, outputs_prefix="STA.USER", outputs_key_field=["id"], outputs=output_data)


def delete_user_sessions_sta_command(client: Client, args: dict[str, Any]) -> CommandResults:
    """Function for sta-delete-user-sessions command. Delete all the IDP sessions associated with a specific user."""

    response = client.delete_sessions_sta(userName=args.get("userName"))
    if not response:
        return CommandResults(
            readable_output=NO_RESULT_MSG,
        )
    return CommandResults(
        readable_output=f"## IDP Sessions for the user - {args.get('userName')} successfully deleted.",
        outputs_prefix="STA.USER",
        outputs_key_field=["id"],
        outputs=response,
    )


""" MAIN FUNCTION """


def main() -> None:
    """
    main function, parses params and runs command functions
    """

    verify_certificate = not demisto.params().get("insecure", False)
    proxy = demisto.params().get("proxy", False)
    base_url = urljoin(urljoin(demisto.params()["url"], "api/v1/tenants/"), demisto.params()["tenant_code"])
    api_key = demisto.params().get("api_key")

    demisto.debug(f"Command being called is {demisto.command()}")
    try:
        headers = {
            "accept": "application/json",
            "Object-Id-Format": "base64",
            "Content-Type": "application/json",
            "apikey": api_key,
        }
        client = Client(base_url=base_url, verify=verify_certificate, headers=headers, proxy=proxy, ok_codes=(200, 201, 204))

        commands = {
            "test-module": test_module,
            "sta-get-user-list": get_userlist_sta_command,
            "sta-get-user-info": get_user_info_sta_command,
            "sta-create-user": create_user_sta_command,
            "sta-update-user-info": update_user_sta_command,
            "sta-delete-user": delete_user_sta_command,
            "sta-get-user-groups": get_user_groups_sta_command,
            "sta-get-group-list": get_group_list_sta_command,
            "sta-get-group-info": get_group_info_sta_command,
            "sta-get-group-members": get_group_members_sta_command,
            "sta-create-group": create_group_sta_command,
            "sta-delete-group": delete_group_sta_command,
            "sta-update-group-info": update_group_sta_command,
            "sta-user-exist-group": user_exist_group_sta_command,
            "sta-add-user-group": add_user_group_sta_command,
            "sta-remove-user-group": remove_user_group_sta_command,
            "sta-get-logs": get_logs_sta_command,
            "sta-validate-tenant": validate_tenant_sta_command,
            "sta-get-application-list": get_application_list_sta_command,
            "sta-get-application-info": get_application_info_sta_command,
            "sta-get-user-applications": get_user_applications_sta_command,
            "sta-get-user-sessions": get_user_sessions_sta_command,
            "sta-delete-user-sessions": delete_user_sessions_sta_command,
        }

        command = demisto.command()

        if command in commands:
            return_results(commands[command](client, demisto.args()))

    # Log exceptions and return errors
    except Exception as e:
        demisto.error(traceback.format_exc())  # print the traceback
        return_error(f"Failed to execute {demisto.command()} command.\nError:\n{e!s}")


""" ENTRY POINT """

if __name__ in ("__main__", "__builtin__", "builtins"):
    main()