DUO Admin
DUO for admins. Must have access to the admin api in order to use this.
Authentication & Identity Management · DUO Admin
Details
| ID | DUO Admin |
|---|---|
| Provider | Cisco Systems |
| Category | Authentication & Identity Management |
| From Version | 5.0.0 |
| Docker Image | demisto/vendors-sdk:1.0.0.10120494 |
| Supported Modules | Agentix XSIAM |
README
DUO for admins.
Must have access to the admin api in order to use this.
This integration was integrated and tested with version 4.4.0 of DUO Admin
Configure DUO Admin in Cortex
| Parameter | Required |
|---|---|
| API Hostname | True |
| Integration Key | True |
| Secret Key | True |
| Trust any certificate (not secure) | False |
| Use system proxy settings | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
duoadmin-get-authentication-logs-by-user
Returns authentication logs associated with a user. Limited to 30 at a time
Base Command
duoadmin-get-authentication-logs-by-user
Input
| Argument Name | Description | Required |
|---|---|---|
| username | The user associated with the logs. | Required |
| from | Fetch logs from this time until now. Possible values are: 10_seconds_ago, 1_minute_ago, 10_minutes_ago, 1_hour_ago, 10_hours_ago, 1_day_ago, 1_week_ago, 1_month_ago, 1_year_ago, 5_years_ago, 10_years_ago. | Required |
| limit | The maximum number of authentication logs to return. Default is 50. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| DuoAdmin.UserDetails.auth_logs.result | string | Result of the authentication attempt |
| DuoAdmin.UserDetails.auth_logs.event_type | string | Type of activity logged |
| DuoAdmin.UserDetails.auth_logs.reason | string | Reason for the authentication attempt result |
| DuoAdmin.UserDetails.auth_logs.access_device.ip | string | The GeoIP location of the access device. IP field |
| DuoAdmin.UserDetails.auth_logs.access_device.hostname | string | The GeoIP location of the access device. Hostname field |
| DuoAdmin.UserDetails.auth_logs.access_device.location.city | string | The GeoIP location of the access device. City field |
| DuoAdmin.UserDetails.auth_logs.access_device.location.state | string | The GeoIP location of the access device. State field |
| DuoAdmin.UserDetails.auth_logs.access_device.location.country | string | The GeoIP location of the access device. Country field |
| DuoAdmin.UserDetails.auth_logs.auth_device.ip | string | The GeoIP location of the authentication device. IP field |
| DuoAdmin.UserDetails.auth_logs.auth_device.hostname | string | The GeoIP location of the authentication device. Hostname field |
| DuoAdmin.UserDetails.auth_logs.auth_device.location.city | string | The GeoIP location of the authentication device. City field |
| DuoAdmin.UserDetails.auth_logs.auth_device.location.state | string | The GeoIP location of the authentication device. State field |
| DuoAdmin.UserDetails.auth_logs.auth_device.location.country | string | The GeoIP location of the authentication device. Country field |
| DuoAdmin.UserDetails.auth_logs.timestamp | date | Timestamp of the event |
| DuoAdmin.UserDetails.auth_logs.application.name | string | Name of the application accessed |
| DuoAdmin.UserDetails.auth_logs.factor | string | The authentication factor |
duoadmin-dissociate-device-from-user
Dissociates a device from a user
Base Command
duoadmin-dissociate-device-from-user
Input
| Argument Name | Description | Required |
|---|---|---|
| username | user to dissociate a device from. | Required |
| device_id | the device id to dissociate. | Required |
Context Output
There is no context output for this command.
duoadmin-delete-u2f-token
Delete a u2f token
Base Command
duoadmin-delete-u2f-token
Input
| Argument Name | Description | Required |
|---|---|---|
| token_id | the id of the token to delete. | Required |
Context Output
There is no context output for this command.
duoadmin-get-users
Return usernames and their user id
Base Command
duoadmin-get-users
Input
| Argument Name | Description | Required |
| — | — | — |
Context Output
| Path | Type | Description |
|---|---|---|
| DuoAdmin.UserDetails.username | string | Username |
| DuoAdmin.UserDetails.user_id | string | User Id |
| DuoAdmin.UserDetails.status | string | Status |
| DuoAdmin.UserDetails.is_enrolled | boolean | is_enrolled |
| DuoAdmin.UserDetails.last_login | date | Last_login |
| DuoAdmin.UserDetails.realname | string | Real Name |
| DuoAdmin.UserDetails.email | string | |
| DuoAdmin.UserDetails.phones | unknown | Phone numbers |
duoadmin-get-devices-by-user
Return devices associated with a user
Base Command
duoadmin-get-devices-by-user
Input
| Argument Name | Description | Required |
|---|---|---|
| username | Username. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| DuoAdmin.UserDetails.phones.phone_id | string | Device Id |
| DuoAdmin.UserDetails.phones.number | string | Device number |
| DuoAdmin.UserDetails.phones.platform | string | Device platform |
| DuoAdmin.UserDetails.phones.last_seen | date | Last time the device was used |
duoadmin-get-u2f-tokens-by-user
Returns a list of U2F tokens associated with the given username
Base Command
duoadmin-get-u2f-tokens-by-user
Input
| Argument Name | Description | Required |
|---|---|---|
| username | username. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| DuoAdmin.UserDetails.u2ftokens | Unknown | The list of tokens |
duoadmin-get-devices
Returns all existing devices
Base Command
duoadmin-get-devices
Input
| Argument Name | Description | Required |
| — | — | — |
Context Output
| Path | Type | Description |
|---|---|---|
| DuoAdmin.Phones.phone_id | Unknown | Device Id |
| DuoAdmin.Phones.number | Unknown | Device number |
| DuoAdmin.Phones.platform | Unknown | Device platform |
| DuoAdmin.Phones.last_seen | Unknown | Last time the device was used |
| DuoAdmin.Phones.users | Unknown | Users associated with this device |
duoadmin-associate-device-to-user
Associates a device to a user
Base Command
duoadmin-associate-device-to-user
Input
| Argument Name | Description | Required |
|---|---|---|
| username | Username. | Required |
| device_id | Device Id. | Required |
Context Output
There is no context output for this command.
duoadmin-get-admins
Returns administrator accounts
Base Command
duoadmin-get-admins
Input
| Argument Name | Description | Required |
| — | — | — |
Context Output
| Path | Type | Description |
|---|---|---|
| DuoAdmin.UserDetails.admin_id | string | Admin_id |
| DuoAdmin.UserDetails.admin_units | unknown | Admin Units |
| DuoAdmin.UserDetails.created | date | Created |
| DuoAdmin.UserDetails.email | string | |
| DuoAdmin.UserDetails.last_login | date | Last Login |
| DuoAdmin.UserDetails.name | string | Name |
| DuoAdmin.UserDetails.phone | unknown | Phone |
| DuoAdmin.UserDetails.role | string | Admin Role |
| DuoAdmin.UserDetails.status | string | Admin Status |
duoadmin-get-bypass-codes
Retrieves the information from the bypass code table
Base Command
duoadmin-get-bypass-codes
Input
| Argument Name | Description | Required |
| — | — | — |
Context Output
| Path | Type | Description |
|---|---|---|
| DuoAdmin.UserDetails.bypass_code_id | unknown | Bypass Code Id |
| DuoAdmin.UserDetails.admin_email | string | Admin Email |
| DuoAdmin.UserDetails.created | date | Bypass Created |
| DuoAdmin.UserDetails.expiration | unknown | Bypass Expiration |
| DuoAdmin.UserDetails.reuse_count | unknown | Bypass Reuse Count |
| DuoAdmin.UserDetails.user.username | unknown | Username |
| DuoAdmin.UserDetails.user.created | unknown | Created |
| DuoAdmin.UserDetails.user.email | unknown | |
| DuoAdmin.UserDetails.user.last_login | unknown | Last Login |
| DuoAdmin.UserDetails.user.status | unknown | Status |
| DuoAdmin.UserDetails.user.user_id | unknown | User Id |
duoadmin-modify-admin
Modify the administrator user.
Base Command
duoadmin-modify-admin
Input
| Argument Name | Description | Required |
|---|---|---|
| admin_id | The id of the admin. | Required |
| name | The name of the admin. | Optional |
| phone | The phone number of the admin. | Optional |
| password | the password of the admin. | Optional |
| password_change_required | a flag to determine if the password should change. Possible values are: false, true. Default is false. | Optional |
Context Output
There is no context output for this command.
duoadmin-modify-user
Modify the user account.
Base Command
duoadmin-modify-user
Input
| Argument Name | Description | Required |
|---|---|---|
| user_id | The user id of the user. | Required |
| user_name | The user name of the user. | Optional |
| realname | The real name of the user. | Optional |
| status | The status of the user. Possible values are: active, disabled. | Optional |
| notes | Notes for the user. | Optional |
| The email of the user. | Optional | |
| first_name | The first name of the user. | Optional |
| last_name | The last name of the user. | Optional |
| alias1 | The first alias of the user. | Optional |
| alias2 | The second alias of the user. | Optional |
| alias3 | The third alias of the user. | Optional |
| alias4 | The fourth alias of the user. | Optional |
| aliases | The aliases list of the user. | Optional |
Context Output
There is no context output for this command.
Configuration parameters
hostname— API Hostname (required)integration_key— Integration Keysecret_key— Secret Keycredentials_key— Integration Keyinsecure— Trust any certificate (not secure)proxy— Use system proxy settings
Commands (12)
-
duoadmin-associate-device-to-userAssociates a device to a user.
-
duoadmin-delete-u2f-tokenDelete a u2f token.
-
duoadmin-dissociate-device-from-userDissociates a device from a user.
-
duoadmin-get-adminsReturns administrator accounts.
-
duoadmin-get-authentication-logs-by-userReturns authentication logs associated with a user. Limited to 30 at a time.
-
duoadmin-get-bypass-codesRetrieves the information from the bypass code table.
-
duoadmin-get-devicesReturns all existing devices.
-
duoadmin-get-devices-by-userReturn devices associated with a user.
-
duoadmin-get-u2f-tokens-by-userReturns a list of U2F tokens associated with the given username.
-
duoadmin-get-usersReturn usernames and their user id.
-
duoadmin-modify-adminModify the administrator user.
-
duoadmin-modify-userModify the user account.
import json import demistomock as demisto import duo_client def util_load_json(path: str): with open(path, encoding="utf-8") as f: return json.loads(f.read()) def mock_client(): from DuoAdminApi import create_api_call return create_api_call() def test_modify_user(mocker): """ Given - A user id and status. When - Calling modify_user method. Then - Validate that the user were successfully update. """ from DuoAdminApi import modify_user args = {"user_id": "1", "status": "active"} user_id = args.get("user_id") client = mock_client() mocker.patch.object(duo_client.Admin, "update_user", return_value=None) result = modify_user(client, **args) assert result.readable_output == f"The user id {user_id} successfully updated" def test_modify_admin_user(mocker): """ Given - An admin id and name. When - Calling modify_admin_user method. Then - Validate that the admin were successfully update. """ from DuoAdminApi import modify_admin_user args = {"admin_id": "1", "name": "test"} admin_id = args.get("admin_id") client = mock_client() mocker.patch.object(duo_client.Admin, "update_admin", return_value=None) result = modify_admin_user(client, **args) assert result.readable_output == f"The admin id {admin_id} successfully updated" def test_get_users(mocker): """ Given - A duo admin client. When - Calling get_all_users method. Then - Validate that all users were successfully retrieve. """ from DuoAdminApi import get_all_users client = mock_client() mock_res = util_load_json("test_data/get_users.json") mocker.patch.object(duo_client.Admin, "get_users", return_value=mock_res) mocker.patch.object(demisto, "results") get_all_users(client) res = demisto.results content = res.call_args[0][0].get("Contents") assert content.get("alias1") == "test.1" assert content.get("email") == "test.1@test.com" assert content.get("status") == "active" def test_get_bypass_codes(mocker): """ Given - A duo admin client. When - Calling get_all_bypass_codes method. Then - Validate that all bypass codes were successfully retrieve. """ from DuoAdminApi import get_all_bypass_codes client = mock_client() mock_res = util_load_json("test_data/get_all_bypass_codes.json") mocker.patch.object(duo_client.Admin, "get_bypass_codes", return_value=mock_res) mocker.patch.object(demisto, "results") get_all_bypass_codes(client) res = demisto.results content = res.call_args[0][0].get("Contents") assert content.get("bypass_code_id") == "1" def test_get_authentication_logs_by_user(mocker): """ Given - A duo admin client user name and from date time. When - Calling get_authentication_logs_by_user method. Then - Validate that all the logs were successfully retrieve. """ from DuoAdminApi import get_authentication_logs_by_user client = mock_client() args = {"username": "test@demisto.com", "from": "10_years_ago"} mock_res = util_load_json("test_data/get_authentication_logs_by_user.json") mocker.patch.object(duo_client.Admin, "get_authentication_log", return_value=mock_res) mocker.patch.object(duo_client.Admin, "get_users_by_name", return_value=[{"user_id": "1"}]) mocker.patch.object(demisto, "results") get_authentication_logs_by_user(client, args) res = demisto.results content = res.call_args[0][0].get("Contents")[0] assert content.get("user").get("name") == args.get("username") assert content.get("auth_device").get("ip") == "1.1.1.1" assert content.get("auth_device").get("location").get("city") == "test_city" def test_get_all_devices(mocker): """ Given - A duo admin client. When - Calling get_all_devices method. Then - Validate that all the devices were successfully retrieve. """ from DuoAdminApi import get_all_devices client = mock_client() mock_res = util_load_json("test_data/get_all_devices.json") mocker.patch.object(duo_client.Admin, "get_phones", return_value=mock_res) mocker.patch.object(demisto, "results") get_all_devices(client) res = demisto.results content = res.call_args[0][0].get("Contents") assert content.get("activated") assert content.get("phone_id") == "1" assert content.get("type") == "Mobile" def test_dissociate_device_by_user(mocker): """ Given - A duo admin client user name and device id. When - Calling dissociate_device_by_user method. Then - Validate that the phone id was successfully dissociated. """ from DuoAdminApi import dissociate_device_by_user client = mock_client() args = {"username": "test@demisto.com", "device_id": "1"} mock_res = util_load_json("test_data/get_authentication_logs_by_user.json") mocker.patch.object(duo_client.Admin, "delete_user_phone", return_value=mock_res) mocker.patch.object(duo_client.Admin, "get_users_by_name", return_value=[{"user_id": "1"}]) mocker.patch.object(demisto, "results") dissociate_device_by_user(client, args) res = demisto.results hr = res.call_args[0][0] assert hr == f"Phone with ID {args.get('device_id')} was dissociated to user {args.get('username')}" def test_associate_device_to_user(mocker): """ Given - A duo admin client user name and device id. When - Calling associate_device_by_user method. Then - Validate that the phone id was successfully associated. """ from DuoAdminApi import associate_device_to_user client = mock_client() args = {"username": "test@demisto.com", "device_id": "1"} mock_res = util_load_json("test_data/get_authentication_logs_by_user.json") mocker.patch.object(duo_client.Admin, "add_user_phone", return_value=mock_res) mocker.patch.object(duo_client.Admin, "get_users_by_name", return_value=[{"user_id": "1"}]) mocker.patch.object(demisto, "results") associate_device_to_user(client, args) res = demisto.results hr = res.call_args[0][0] assert hr == f"Phone with ID {args.get('device_id')} was associated to user {args.get('username')}" def test_get_all_admins(mocker): """ Given - A duo admin client. When - Calling get_all_admins method. Then - Validate that all admins were successfully retrieve. """ from DuoAdminApi import get_all_admins client = mock_client() mock_res = { "admin_id": "1", "created": None, "email": "test.1@test.com", "last_login": 1662468518, "name": "test1-Demisto", "phone": "+972111111111", } mocker.patch.object(duo_client.Admin, "get_admins", return_value=mock_res) mocker.patch.object(demisto, "results") get_all_admins(client) res = demisto.results content = res.call_args[0][0].get("Contents") assert content.get("admin_id") == mock_res.get("admin_id") assert content.get("email") == mock_res.get("email") def test_get_u2f_tokens_by_user(mocker): """ Given - A duo admin client. When - Calling get_u2f_tokens_by_user method. Then - Validate that all u2f tokens were successfully retrieve. """ from DuoAdminApi import get_u2f_tokens_by_user client = mock_client() mock_res = util_load_json("test_data/get_users.json") mock_res.update({"credential_name": "test_credential", "date_added": 1662468518, "label": "Security Key"}) mock_res = [mock_res] args = {"username": "test1"} mocker.patch.object(duo_client.Admin, "get_user_u2ftokens", return_value=mock_res) mocker.patch.object(duo_client.Admin, "get_users_by_name", return_value=[{"user_id": "1"}]) mocker.patch.object(demisto, "results") get_u2f_tokens_by_user(client, args) res = demisto.results content = res.call_args[0][0].get("Contents")[0] assert content.get("credential_name") == "test_credential" def test_delete_u2f_token(mocker): """ Given - A duo admin client. When - Calling delete_u2f_token method. Then - Validate that u2f token was successfully deleted. """ from DuoAdminApi import delete_u2f_token client = mock_client() args = {"token_id": "test_token"} mocker.patch.object(duo_client.Admin, "delete_u2ftoken") mocker.patch.object(demisto, "results") delete_u2f_token(client, args) res = demisto.results content = res.call_args[0][0] assert content == f"Token with ID {args.get('token_id')} deleted successfully"