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
| ID | SafeNet Trusted Access |
|---|---|
| Provider | Thales |
| Category | Authentication & Identity Management |
| From Version | 6.0.0 |
| Docker Image | demisto/python3:3.12.8.3296088 |
| Supported Modules | Agentix 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 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 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 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 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 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 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-groupAdd user to a specific group.
-
sta-create-groupCreate a new group in the tenant.
-
sta-create-userCreate a new user in the tenant.
-
sta-delete-groupDelete group from the tenant.
-
sta-delete-userDelete user from the tenant.
-
sta-delete-user-sessionsDelete all the active SSO sessions for a specific user from the STA.
-
sta-get-application-infoGet the information for a specific application in the tenant.
-
sta-get-application-listGet the list of the applications in the tenant.
-
sta-get-group-infoGet information for a specific group.
-
sta-get-group-listGet list of groups in the tenant.
-
sta-get-group-membersGet list of users in a specific group.
-
sta-get-logsGet access, authentication, and audit logs.
-
sta-get-user-applicationsGet the list of the applications assigned to a specific user.
-
sta-get-user-groupsReturn all the groups associated with a specific user.
-
sta-get-user-infoGet the profile information for a specific user.
-
sta-get-user-listGet list of users in the tenant.
-
sta-get-user-sessionsGet sessions for a specific user.
-
sta-remove-user-groupRemove user from a group.
-
sta-update-group-infoUpdate information for a specific group.
-
sta-update-user-infoUpdate the profile for a specific user.
-
sta-user-exist-groupCheck if user exists in a specific group.
-
sta-validate-tenantChecks 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()