From 722ce731f318ce3313339ad1ebc46d08ee216827 Mon Sep 17 00:00:00 2001 From: admingit Date: Mon, 29 Jan 2024 11:18:50 +0100 Subject: [PATCH] add_addon --- deployment-apps/msadgraph/CONTRIBUTING.md | 2 + deployment-apps/msadgraph/LICENSE | 201 + deployment-apps/msadgraph/NOTICE | 26 + deployment-apps/msadgraph/README.md | 999 +++++ deployment-apps/msadgraph/__init__.py | 14 + deployment-apps/msadgraph/logo_msadgraph.svg | 1 + .../msadgraph/logo_msadgraph_dark.svg | 1 + .../msadgraph/manual_readme_content.md | 145 + deployment-apps/msadgraph/msadgraph.json | 3871 +++++++++++++++++ .../msadgraph/msadgraph_connector.py | 1541 +++++++ deployment-apps/msadgraph/msadgraph_consts.py | 86 + .../msadgraph/msadgraph_get_group.html | 170 + .../msadgraph_list_group_members.html | 174 + .../msadgraph/msadgraph_list_groups.html | 174 + .../msadgraph_list_user_attributes.html | 175 + .../msadgraph_list_user_devices.html | 163 + .../msadgraph/msadgraph_list_users.html | 177 + deployment-apps/msadgraph/msadgraph_view.py | 58 + .../msadgraph/release_notes/1.0.5.md | 2 + .../msadgraph/release_notes/1.1.0.md | 1 + .../msadgraph/release_notes/1.2.0.md | 8 + .../msadgraph/release_notes/1.3.0.md | 2 + .../msadgraph/release_notes/1.4.0.md | 1 + .../msadgraph/release_notes/unreleased.md | 1 + .../py3/beautifulsoup4-4.9.1-py3-none-any.whl | Bin 0 -> 115057 bytes .../soupsieve-2.3.2.post1-py3-none-any.whl | Bin 0 -> 37377 bytes .../py3/soupsieve-2.4.1-py3-none-any.whl | Bin 0 -> 36379 bytes 27 files changed, 7993 insertions(+) create mode 100644 deployment-apps/msadgraph/CONTRIBUTING.md create mode 100644 deployment-apps/msadgraph/LICENSE create mode 100644 deployment-apps/msadgraph/NOTICE create mode 100644 deployment-apps/msadgraph/README.md create mode 100644 deployment-apps/msadgraph/__init__.py create mode 100644 deployment-apps/msadgraph/logo_msadgraph.svg create mode 100644 deployment-apps/msadgraph/logo_msadgraph_dark.svg create mode 100644 deployment-apps/msadgraph/manual_readme_content.md create mode 100644 deployment-apps/msadgraph/msadgraph.json create mode 100644 deployment-apps/msadgraph/msadgraph_connector.py create mode 100644 deployment-apps/msadgraph/msadgraph_consts.py create mode 100644 deployment-apps/msadgraph/msadgraph_get_group.html create mode 100644 deployment-apps/msadgraph/msadgraph_list_group_members.html create mode 100644 deployment-apps/msadgraph/msadgraph_list_groups.html create mode 100644 deployment-apps/msadgraph/msadgraph_list_user_attributes.html create mode 100644 deployment-apps/msadgraph/msadgraph_list_user_devices.html create mode 100644 deployment-apps/msadgraph/msadgraph_list_users.html create mode 100644 deployment-apps/msadgraph/msadgraph_view.py create mode 100644 deployment-apps/msadgraph/release_notes/1.0.5.md create mode 100644 deployment-apps/msadgraph/release_notes/1.1.0.md create mode 100644 deployment-apps/msadgraph/release_notes/1.2.0.md create mode 100644 deployment-apps/msadgraph/release_notes/1.3.0.md create mode 100644 deployment-apps/msadgraph/release_notes/1.4.0.md create mode 100644 deployment-apps/msadgraph/release_notes/unreleased.md create mode 100644 deployment-apps/msadgraph/wheels/py3/beautifulsoup4-4.9.1-py3-none-any.whl create mode 100644 deployment-apps/msadgraph/wheels/py3/soupsieve-2.3.2.post1-py3-none-any.whl create mode 100644 deployment-apps/msadgraph/wheels/py3/soupsieve-2.4.1-py3-none-any.whl diff --git a/deployment-apps/msadgraph/CONTRIBUTING.md b/deployment-apps/msadgraph/CONTRIBUTING.md new file mode 100644 index 00000000..b3cc5070 --- /dev/null +++ b/deployment-apps/msadgraph/CONTRIBUTING.md @@ -0,0 +1,2 @@ +# Contributing +For more information about contributing to Splunk SOAR Apps please take a look at our app [Contribution Guide](https://github.com/splunk-soar-connectors/.github/blob/main/.github/CONTRIBUTING.md)! diff --git a/deployment-apps/msadgraph/LICENSE b/deployment-apps/msadgraph/LICENSE new file mode 100644 index 00000000..573247f4 --- /dev/null +++ b/deployment-apps/msadgraph/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright (c) 2022-2023 Splunk Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/deployment-apps/msadgraph/NOTICE b/deployment-apps/msadgraph/NOTICE new file mode 100644 index 00000000..c7723d77 --- /dev/null +++ b/deployment-apps/msadgraph/NOTICE @@ -0,0 +1,26 @@ +Splunk SOAR MS Graph for Active Directory +Copyright (c) 2022-2023 Splunk Inc. + +Third-party Software Attributions: + +Library: Django +Version: 3.2.13 +License: BSD 3 +0.9.0 thru 1.2 1991-1995 CWI yes +1.3 thru 1.5.2 1.2 1995-1999 CNRI yes +2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Python Software Foundation; +Copyright 1991-1995 Stichting Mathematisch Centrum Amsterdam +Copyright 2001 Python Software Foundation; All Rights Reserved +Copyright Django Software Foundation and individual contributors + +Library: beautifulsoup4 +Version: 4.9.1 +License: MIT +Copyright 2004-2017 Leonard Richardson +Copyright 2004-2019 Leonard Richardson +Copyright 2018 Isaac Muse + +Library: requests +Version: 2.25.0 +License: Apache 2.0 +Kenneth Reitz diff --git a/deployment-apps/msadgraph/README.md b/deployment-apps/msadgraph/README.md new file mode 100644 index 00000000..8444168a --- /dev/null +++ b/deployment-apps/msadgraph/README.md @@ -0,0 +1,999 @@ +[comment]: # "Auto-generated SOAR connector documentation" +# MS Graph for Active Directory + +Publisher: Splunk +Connector Version: 1.4.0 +Product Vendor: Microsoft +Product Name: MS Graph for Active Directory +Product Version Supported (regex): ".\*" +Minimum Product Version: 6.1.0 + +Connects to Microsoft Active Directory using MS Graph REST API services to support various generic and investigative actions + +[comment]: # " File: README.md" +[comment]: # " Copyright (c) 2022-2023 Splunk Inc." +[comment]: # "" +[comment]: # "Licensed under the Apache License, Version 2.0 (the 'License');" +[comment]: # "you may not use this file except in compliance with the License." +[comment]: # "You may obtain a copy of the License at" +[comment]: # "" +[comment]: # " http://www.apache.org/licenses/LICENSE-2.0" +[comment]: # "" +[comment]: # "Unless required by applicable law or agreed to in writing, software distributed under" +[comment]: # "the License is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND," +[comment]: # "either express or implied. See the License for the specific language governing permissions" +[comment]: # "and limitations under the License." +[comment]: # "" +## Authentication + +### Microsoft Azure Application creation + +This app requires creating a Microsoft Azure Application. To do so, navigate to + in a browser and log in with a Microsoft account, then select **Azure +Active Directory** . + +1. Go to **App Registrations** and click on **+ New registration** . +2. Give the app an appropriate name. +3. Select a supported account type (configure the application to be multitenant). +4. Click on the **Register** . + - Under **Certificates & secrets** , add **New client secret** . Note this key somewhere + secure, as it cannot be retrieved after closing the window. + - Under **Redirect URIs** we will be updating the entry of https://phantom.local to reflect + the actual redirect URI. We will get this from the SOAR asset we create below in the section + titled "Configure the MS Graph for Active Directory SOAR app Asset" + +### Delegated Permissions configuration + +Use this procedure to provide non-admin permissions to the app. To do so, navigate to + in a browser and log in with a Microsoft account, then navigate to the +previously created app configuration. + +1. Under **API Permissions** , click on **Add a permission** . +2. Go to **Microsoft Graph Permissions** , the following **Delegated Permissions** need to be + added: + - User.ReadWrite.All + - Directory.ReadWrite.All + - Directory.AccessAsUser.All + - User.ManageIdentities.All + - Group.ReadWrite.All + - GroupMember.ReadWrite.All + - RoleManagement.ReadWrite.Directory + - offline_access +3. Click on the **Add permissions** . +4. After making these changes, click on **Grant admin consent** . + +### Application Permissions configuration + +Use this procedure to provide admin permissions to the app. To do so, navigate to + in a browser and log in with a Microsoft account, then navigate to the +previously created app configuration. + +1. Under **API Permissions** , click on **Add a permission** . +2. Go to **Microsoft Graph Permissions** , the following **Application Permissions** need to be + added: + - User.ReadWrite.All + - Directory.ReadWrite.All + - User.ManageIdentities.All + - Group.ReadWrite.All + - GroupMember.ReadWrite.All + - RoleManagement.ReadWrite.Directory +3. Click on the **Add permissions** . +4. After making these changes, click on **Grant admin consent** . + +#### Note: **reset password** action is not supported with Application permissions + +## Configure the MS Graph for Active Directory SOAR app Asset + +When creating an asset for the **MS Graph for Active Directory** app, place the **Application ID** +of the app created during the previous step in the **Client ID** field and place the password +generated during the app creation process in the **Client Secret** field. Then, after filling out +the **Tenant** field, click **SAVE** . + +After saving, a new field will appear in the **Asset Settings** tab. Take the URL found in the +**POST incoming for MS Graph to this location** field and place it in the **Redirect URIs** field of +the Azure Application configuration page. To this URL, add **/result** . After doing so the URL +should look something like: + +https://\/rest/handler/msgraphforactivedirectory_f2a239df-acb2-47d6-861c-726a435cfe76/\/result + + +Once again, click on Save. + +## Enable Application Permissions + +If you have received admin consent to use application permissions, make sure to check the **Admin +Access Required** and **Admin Consent Already Provided** checkboxes on the asset. + +## User Permissions + +To complete the authorization process, this app needs permission to view assets, which is not +granted by default. First, under **asset settings** , check which user is listed under **Select a +user on behalf of which automated actions can be executed** . By default, the user will be +**automation** , but this user can be changed by clicking **EDIT** at the bottom of the window. To +give this user permission to view assets, follow these steps: + +- In the main drop-down menu, select **Administration** , then select the **User Management** , + and under that tab, select **Roles** . Finally, click **+ ROLE** . +- In the **Add Role** wizard, give the role a name (e.g **Asset Viewer** ), and provide a + description. Subsequently, under **Available Users** , add the user assigned to the asset viewed + earlier. Then click the **Permissions** tab. +- On the permission tab, under **Available Privileges** , give the role the **View Assets** + privilege. Then click **SAVE** . + +## Method to Run Test Connectivity (for delegated permissions) + +After setting up the asset and user, click the **TEST CONNECTIVITY** button. A window should pop up +and display a URL. Navigate to this URL in a separate browser tab. This new tab will redirect to a +Microsoft login page. Log in to a Microsoft account with administrator privileges to the Microsoft +AD environment. After logging in, review the requested permissions listed, then click **Accept** . +Finally, close that tab. The test connectivity window should show success. + +The app should now be ready to use. + +## State File Permissions + +Please check the permissions for the state file as mentioned below. + +#### State Filepath + +- For Root Install Instance: + /opt/phantom/local_data/app_states/f2a239df-acb2-47d6-861c-726a435cfe76/{asset_id}\_state.json +- For Non-Root Install Instance: + /\/local_data/app_states/f2a239df-acb2-47d6-861c-726a435cfe76/{asset_id}\_state.json + +#### State File Permissions + +- File Rights: rw-rw-r-- (664) (The SOAR user should have read and write access for the state + file) +- File Owner: appropriate SOAR user + +## Port Details + +The app uses HTTP/ HTTPS protocol for communicating with the Microsoft Graph server. Below are the +default ports used by the Splunk SOAR Connector. + +| Service Name | Transport Protocol | Port | +|--------------|--------------------|------| +| https | tcp | 443 | + + +### Configuration Variables +The below configuration variables are required for this Connector to operate. These variables are specified when configuring a MS Graph for Active Directory asset in SOAR. + +VARIABLE | REQUIRED | TYPE | DESCRIPTION +-------- | -------- | ---- | ----------- +**tenant_id** | required | string | Tenant (Tenant ID or Tenant Name) +**client_id** | required | string | Application ID +**client_secret** | required | password | Client Secret +**region** | optional | string | Microsoft AD Region +**admin_access_required** | optional | boolean | Admin Access Required +**admin_access_granted** | optional | boolean | Admin Consent Already Provided + +### Supported Actions +[test connectivity](#action-test-connectivity) - Use supplied credentials to generate a token with MS Graph +[list users](#action-list-users) - Get a list of users +[reset password](#action-reset-password) - Reset or set a user's password in a Microsoft AD environment +[disable tokens](#action-disable-tokens) - Invalidate all active refresh tokens for a user in a Microsoft AD environment +[enable user](#action-enable-user) - Enable a user +[disable user](#action-disable-user) - Disable a user +[list user devices](#action-list-user-devices) - List devices for a specified user +[list user attributes](#action-list-user-attributes) - List attributes for all or a specified user +[set user attribute](#action-set-user-attribute) - Set an attribute for a user +[remove user](#action-remove-user) - Remove a user from a specified group +[add user](#action-add-user) - Add a user to a specified group +[list groups](#action-list-groups) - List groups in the organization +[get group](#action-get-group) - Get information about a group +[list group members](#action-list-group-members) - List the members in a group +[validate group](#action-validate-group) - Returns true if a user is in a group; otherwise, false +[list directory roles](#action-list-directory-roles) - List the directory roles that are activated in the tenant +[generate token](#action-generate-token) - Generate a token + +## action: 'test connectivity' +Use supplied credentials to generate a token with MS Graph + +Type: **test** +Read only: **True** + +#### Action Parameters +No parameters are required for this action + +#### Action Output +No Output + +## action: 'list users' +Get a list of users + +Type: **investigate** +Read only: **True** + +For more information on using the filter_string, select_string and expand_string parameters, refer to https://docs.microsoft.com/en-us/graph/query-parameters. By default, only a limited set of properties are returned, to return an alternative property set use $select query parameter. + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**filter_string** | optional | Filter string to apply to user listing | string | +**select_string** | optional | Select string to get additional user properties. Separate multiple values with commas | string | +**expand_string** | optional | Expand string to get a resource or collection referenced by a single relationship | string | +**use_advanced_query** | optional | Use advanced query capabilities | boolean | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.expand_string | string | | manager +action_result.parameter.filter_string | string | | startswith(displayName,'User') +action_result.parameter.select_string | string | | displayName +action_result.parameter.use_advanced_query | boolean | | True False +action_result.data.\*.accountEnabled | boolean | | True False +action_result.data.\*.ageGroup | string | | +action_result.data.\*.assignedLicenses.\*.skuId | string | | 189a915c-fe4f-4ffa-bde4-85b9628d07a0 +action_result.data.\*.assignedPlans.\*.assignedTimestamp | string | | 2017-08-29T02:31:40Z +action_result.data.\*.assignedPlans.\*.capabilityStatus | string | | Enabled +action_result.data.\*.assignedPlans.\*.service | string | | OfficeForms +action_result.data.\*.assignedPlans.\*.servicePlanId | string | | e212cbc7-0961-4c40-9825-01117710dcb1 +action_result.data.\*.city | string | | Palo Alto +action_result.data.\*.companyName | string | | +action_result.data.\*.consentProvidedForMinor | string | | +action_result.data.\*.country | string | | US +action_result.data.\*.createdDateTime | string | | 2019-05-21T22:27:20Z +action_result.data.\*.creationType | string | | +action_result.data.\*.deletionTimestamp | string | | +action_result.data.\*.department | string | | Sales +action_result.data.\*.dirSyncEnabled | string | | +action_result.data.\*.displayName | string | | User +action_result.data.\*.employeeId | string | | +action_result.data.\*.facsimileTelephoneNumber | string | | +action_result.data.\*.givenName | string | | testuser +action_result.data.\*.id | string | `user id` | e4c722ac-3b83-478d-8f52-c388885dc30f +action_result.data.\*.immutableId | string | | +action_result.data.\*.isCompromised | string | | +action_result.data.\*.jobTitle | string | | Sales Manager +action_result.data.\*.lastDirSyncTime | string | | +action_result.data.\*.legalAgeGroupClassification | string | | +action_result.data.\*.mail | string | `email` | user@test.com +action_result.data.\*.mailNickname | string | | testmail +action_result.data.\*.mobile | string | | +1 5556378688 +action_result.data.\*.mobilePhone | string | | +action_result.data.\*.objectType | string | | User +action_result.data.\*.odata.type | string | | test.DirectoryServices.User +action_result.data.\*.officeLocation | string | | +action_result.data.\*.onPremisesDistinguishedName | string | | +action_result.data.\*.onPremisesSecurityIdentifier | string | | +action_result.data.\*.otherMails | string | `email` | user.test@outlook.com +action_result.data.\*.passwordPolicies | string | | None +action_result.data.\*.passwordProfile | string | | +action_result.data.\*.passwordProfile.enforceChangePasswordPolicy | boolean | | True False +action_result.data.\*.passwordProfile.forceChangePasswordNextLogin | boolean | | True False +action_result.data.\*.passwordProfile.password | string | | +action_result.data.\*.physicalDeliveryOfficeName | string | | +action_result.data.\*.postalCode | string | | 94303 +action_result.data.\*.preferredLanguage | string | | en-US +action_result.data.\*.provisionedPlans.\*.capabilityStatus | string | | Enabled +action_result.data.\*.provisionedPlans.\*.provisioningStatus | string | | Success +action_result.data.\*.provisionedPlans.\*.service | string | | exchange +action_result.data.\*.proxyAddresses | string | | SMTP:user1@test.com +action_result.data.\*.refreshTokensValidFromDateTime | string | | 2017-09-27T22:54:59Z +action_result.data.\*.showInAddressList | string | | +action_result.data.\*.sipProxyAddress | string | `email` | user@test.com +action_result.data.\*.state | string | | CA +action_result.data.\*.streetAddress | string | | 2479 E. Bayshore Rd. +action_result.data.\*.surname | string | | Test_surname +action_result.data.\*.telephoneNumber | string | | +action_result.data.\*.thumbnailPhoto@odata.mediaEditLink | string | | directoryObjects/6132ca31-7a09-434f-a269-abe836d0c01e/test.DirectoryServices.User/thumbnailPhoto +action_result.data.\*.usageLocation | string | | US +action_result.data.\*.userPrincipalName | string | `user id` | user@test.com +action_result.data.\*.userState | string | | +action_result.data.\*.userStateChangedOn | string | | +action_result.data.\*.userType | string | | Member +action_result.summary.num_users | numeric | | 8 +action_result.summary.result_found | boolean | | True False +action_result.summary.total_results | numeric | | 7 +action_result.message | string | | Successfully listed users +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'reset password' +Reset or set a user's password in a Microsoft AD environment + +Type: **contain** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**user_id** | required | User ID to change password - can be user principal name or object ID | string | `user id` +**force_change** | optional | Force user to change password on next login | boolean | +**temp_password** | required | Temporary password for user | string | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.force_change | boolean | | True False +action_result.parameter.temp_password | string | | Temp_PA$$w0rd +action_result.parameter.user_id | string | `user id` | ee3dc4f2-70f9-446f-a19e-6b4e95ba030d user@test.com +action_result.data | string | | +action_result.summary.status | string | | Successfully reset user password +action_result.message | string | | Status: Successfully reset user password +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'disable tokens' +Invalidate all active refresh tokens for a user in a Microsoft AD environment + +Type: **contain** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**user_id** | required | User ID to disable tokens of - can be user principal name or object ID | string | `user id` + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.user_id | string | `user id` | ee3dc4f2-70f9-446f-a19e-6b4e95ba030d user@test.com +action_result.data | string | | +action_result.data.\*.@odata.context | string | | https://graph.test.com/v1.0/$metadata#Edm.Boolean +action_result.data.\*.odata.metadata | string | `url` | https://graph.windows.net/1t309est-db6c-4tes-t1d2-12bf3456d78d/$metadata#Edm.Null +action_result.data.\*.odata.null | boolean | | True False +action_result.data.\*.value | boolean | | True False +action_result.summary.status | string | | Successfully disabled tokens +action_result.message | string | | Successfully invalidated tokens Status: Successfully disabled tokens +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'enable user' +Enable a user + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**user_id** | required | User ID to enable - can be user principal name or object ID | string | `user id` + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.user_id | string | `user id` | user@test.com +action_result.data | string | | +action_result.summary.status | string | | Successfully enabled user user@test.com +action_result.message | string | | Status: Successfully enabled user user@test.com +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'disable user' +Disable a user + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**user_id** | required | User ID to disable - can be user principal name or object ID | string | `user id` + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.user_id | string | `user id` | user@test.com +action_result.data | string | | +action_result.summary.status | string | | Successfully disabled user user@test.com +action_result.message | string | | Status: Successfully disabled user user@test.com +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'list user devices' +List devices for a specified user + +Type: **investigate** +Read only: **True** + +By default, only a limited set of properties are returned, to return an alternative property set use $select query parameter. For more information on using the select_string parameter, refer to this documentation. + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**user_id** | required | User ID - can be user principal name or object ID | string | `user id` +**select_string** | optional | Select string to get additional user properties. Separate multiple values with commas | string | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.select_string | string | | displayName +action_result.parameter.user_id | string | `user id` | user@test.com +action_result.data.\*.@odata.type | string | | #test.graph.device +action_result.data.\*.accountEnabled | boolean | | True False +action_result.data.\*.alternativeSecurityIds.\*.identityProvider | string | | +action_result.data.\*.alternativeSecurityIds.\*.key | string | | WAA1ADAAOQA6ADwAUwBIAEEAMQAtAFQAUAAtAFAAVQBCAEsARQBZAD4AOQA5AEEARQAwADgAOABDAEUANAA1ADgAMABCADcAQgBGAEEARQA2ADEAQQBCADYANAA3ADYANgA5ADUAOAAzAEQANABFAEYARQA5ADYAOAAyAHkAcQBSAEIANwBrAGEAMQA4AEoATAByACsAegB4AE8AYwB6AE8AYgBNAFEANQBZAEgAbgB0AFQAdgBOAG0AbgA5AEQAZQA2AFgAVQBUAGgAcwBFAD0A +action_result.data.\*.alternativeSecurityIds.\*.type | numeric | | 2 +action_result.data.\*.approximateLastSignInDateTime | string | | 2019-09-26T03:42:15Z +action_result.data.\*.complianceExpirationDateTime | string | | +action_result.data.\*.createdDateTime | string | | 2019-09-26T03:42:15Z +action_result.data.\*.deletedDateTime | string | | +action_result.data.\*.deviceCategory | string | | +action_result.data.\*.deviceId | string | | +action_result.data.\*.deviceMetadata | string | | +action_result.data.\*.deviceOwnership | string | | +action_result.data.\*.deviceVersion | numeric | | +action_result.data.\*.displayName | string | | +action_result.data.\*.domainName | string | | +action_result.data.\*.enrollmentProfileName | string | | +action_result.data.\*.enrollmentType | string | | +action_result.data.\*.extensionAttributes.extensionAttribute1 | string | | +action_result.data.\*.extensionAttributes.extensionAttribute10 | string | | +action_result.data.\*.extensionAttributes.extensionAttribute11 | string | | +action_result.data.\*.extensionAttributes.extensionAttribute12 | string | | +action_result.data.\*.extensionAttributes.extensionAttribute13 | string | | +action_result.data.\*.extensionAttributes.extensionAttribute14 | string | | +action_result.data.\*.extensionAttributes.extensionAttribute15 | string | | +action_result.data.\*.extensionAttributes.extensionAttribute2 | string | | +action_result.data.\*.extensionAttributes.extensionAttribute3 | string | | +action_result.data.\*.extensionAttributes.extensionAttribute4 | string | | +action_result.data.\*.extensionAttributes.extensionAttribute5 | string | | +action_result.data.\*.extensionAttributes.extensionAttribute6 | string | | +action_result.data.\*.extensionAttributes.extensionAttribute7 | string | | +action_result.data.\*.extensionAttributes.extensionAttribute8 | string | | +action_result.data.\*.extensionAttributes.extensionAttribute9 | string | | +action_result.data.\*.externalSourceName | string | | +action_result.data.\*.id | string | | +action_result.data.\*.isCompliant | boolean | | +action_result.data.\*.isManaged | boolean | | +action_result.data.\*.isRooted | string | | +action_result.data.\*.managementType | string | | +action_result.data.\*.manufacturer | string | | +action_result.data.\*.mdmAppId | string | | +action_result.data.\*.model | string | | +action_result.data.\*.onPremisesLastSyncDateTime | string | | +action_result.data.\*.onPremisesSyncEnabled | boolean | | +action_result.data.\*.operatingSystem | string | | Windows +action_result.data.\*.operatingSystemVersion | string | | 10.0.18362.0 +action_result.data.\*.profileType | string | | RegisteredDevice +action_result.data.\*.registrationDateTime | string | | 2019-09-26T03:42:15Z +action_result.data.\*.sourceType | string | | +action_result.data.\*.trustType | string | | Workplace +action_result.summary | string | | +action_result.summary.status | string | | Successfully retrieved owned devices for user test@user.test.com +action_result.message | string | | Status: Successfully retrieved owned devices for user test@user.test.com +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'list user attributes' +List attributes for all or a specified user + +Type: **investigate** +Read only: **True** + +By default, only a limited set of properties are returned, to return an alternative property set use $select query parameter. For more information on using the select_string and expand_string parameters, refer to https://docs.microsoft.com/en-us/graph/query-parameters. + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**user_id** | optional | User ID - can be user principal name or object ID | string | `user id` +**select_string** | optional | Select string to get additional user properties. Separate multiple values with commas | string | +**expand_string** | optional | Expand string to get a resource or collection referenced by a single relationship | string | +**use_advanced_query** | optional | Use advanced query capabilities | boolean | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.expand_string | string | | manager +action_result.parameter.select_string | string | | displayName +action_result.parameter.use_advanced_query | boolean | | True False +action_result.parameter.user_id | string | `user id` | user@test.com +action_result.data.\*.@odata.context | string | | https://graph.test.com/v1.0/$metadata#users/$entity +action_result.data.\*.accountEnabled | boolean | | True False +action_result.data.\*.ageGroup | string | | +action_result.data.\*.assignedLicenses.\*.skuId | string | | f30db892-07e9-47e9-837c-80727f46fd3d +action_result.data.\*.assignedPlans.\*.assignedTimestamp | string | | 2019-04-26T07:21:18Z +action_result.data.\*.assignedPlans.\*.capabilityStatus | string | | Enabled +action_result.data.\*.assignedPlans.\*.service | string | | exchange +action_result.data.\*.assignedPlans.\*.servicePlanId | string | | 33c4f319-9bdd-48d6-9c4d-410b750a4a5a +action_result.data.\*.city | string | | +action_result.data.\*.companyName | string | | +action_result.data.\*.consentProvidedForMinor | string | | +action_result.data.\*.country | string | | +action_result.data.\*.createdDateTime | string | | 2019-05-02T20:27:59Z +action_result.data.\*.creationType | string | | +action_result.data.\*.deletionTimestamp | string | | +action_result.data.\*.department | string | | Sales +action_result.data.\*.dirSyncEnabled | string | | +action_result.data.\*.displayName | string | | Test User +action_result.data.\*.employeeId | string | | +action_result.data.\*.facsimileTelephoneNumber | string | | +action_result.data.\*.givenName | string | | +action_result.data.\*.id | string | `user id` | 7d55d7e6-cf5a-4dd2-a176-57a3c33b7fa9 +action_result.data.\*.identities.\*.issuer | string | | test.com +action_result.data.\*.identities.\*.issuerAssignedId | string | | test2@user.test.com +action_result.data.\*.identities.\*.signInType | string | | userPrincipalName +action_result.data.\*.immutableId | string | | +action_result.data.\*.isCompromised | string | | +action_result.data.\*.jobTitle | string | | +action_result.data.\*.lastDirSyncTime | string | | +action_result.data.\*.legalAgeGroupClassification | string | | +action_result.data.\*.mail | string | `email` | +action_result.data.\*.mailNickname | string | | test +action_result.data.\*.mobile | string | | +action_result.data.\*.mobilePhone | string | | +action_result.data.\*.objectId | string | | 59f51194-1998-4932-a8ac-468e59374edc +action_result.data.\*.objectType | string | | User +action_result.data.\*.odata.metadata | string | | https://graph.windows.net/1t309est-db6c-4tes-t1d2-12bf3456d78d/$metadata#directoryObjects/@Element +action_result.data.\*.odata.type | string | | test.DirectoryServices.User +action_result.data.\*.officeLocation | string | | +action_result.data.\*.onPremisesDistinguishedName | string | | +action_result.data.\*.onPremisesSecurityIdentifier | string | | +action_result.data.\*.otherMails | string | `email` | user@test.com +action_result.data.\*.passwordPolicies | string | | +action_result.data.\*.passwordProfile | string | | +action_result.data.\*.passwordProfile.enforceChangePasswordPolicy | boolean | | True False +action_result.data.\*.passwordProfile.forceChangePasswordNextLogin | boolean | | True False +action_result.data.\*.passwordProfile.password | string | | +action_result.data.\*.physicalDeliveryOfficeName | string | | +action_result.data.\*.postalCode | string | | +action_result.data.\*.preferredLanguage | string | | +action_result.data.\*.provisionedPlans.\*.capabilityStatus | string | | Enabled +action_result.data.\*.provisionedPlans.\*.provisioningStatus | string | | Success +action_result.data.\*.provisionedPlans.\*.service | string | | exchange +action_result.data.\*.proxyAddresses | string | | SMTP:test_shared_mailbox@test.com +action_result.data.\*.refreshTokensValidFromDateTime | string | | 2019-05-16T19:54:18Z +action_result.data.\*.showInAddressList | string | | +action_result.data.\*.sipProxyAddress | string | `email` | +action_result.data.\*.state | string | | +action_result.data.\*.streetAddress | string | | +action_result.data.\*.surname | string | | +action_result.data.\*.telephoneNumber | string | | +action_result.data.\*.thumbnailPhoto@odata.mediaEditLink | string | | directoryObjects/59f12345-1998-4932-a8ac-468e59374edc/test.DirectoryServices.User/thumbnailPhoto +action_result.data.\*.usageLocation | string | | US +action_result.data.\*.userPrincipalName | string | `user id` | user@test.com +action_result.data.\*.userState | string | | +action_result.data.\*.userStateChangedOn | string | | +action_result.data.\*.userType | string | | Member +action_result.summary.status | string | | Successfully retrieved user attributes Successfully retrieved attributes for user user@test.com +action_result.message | string | | Status: Successfully retrieved user attributes Status: Successfully retrieved attributes for user user@test.com, User enabled: False +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'set user attribute' +Set an attribute for a user + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**user_id** | required | User ID - can be user principal name or object ID | string | `user id` +**attribute** | required | Attribute to set | string | +**attribute_value** | required | Value of attribute to set | string | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.attribute | string | | department +action_result.parameter.attribute_value | string | | Sales +action_result.parameter.user_id | string | `user id` | user@test.com +action_result.data | string | | +action_result.data.\*.classification | string | | +action_result.data.\*.createdDateTime | string | | 2021-03-25T18:40:53Z +action_result.data.\*.deletedDateTime | string | | +action_result.data.\*.deletionTimestamp | string | | +action_result.data.\*.description | string | | This is for testing purpose +action_result.data.\*.dirSyncEnabled | string | | +action_result.data.\*.displayName | string | | Test-site +action_result.data.\*.expirationDateTime | string | | +action_result.data.\*.id | string | `user id` | 2a201c95-101b-42d9-a7af-9a2fdf8193f1 +action_result.data.\*.isAssignableToRole | string | | +action_result.data.\*.lastDirSyncTime | string | | +action_result.data.\*.mail | string | `email` | Test-site@test.com +action_result.data.\*.mailEnabled | boolean | | True False +action_result.data.\*.mailNickname | string | | Test-site +action_result.data.\*.membershipRule | string | | +action_result.data.\*.membershipRuleProcessingState | string | | +action_result.data.\*.objectType | string | | Group +action_result.data.\*.odata.type | string | | test.DirectoryServices.Group +action_result.data.\*.onPremisesDomainName | string | `domain` | +action_result.data.\*.onPremisesLastSyncDateTime | string | | +action_result.data.\*.onPremisesNetBiosName | string | | +action_result.data.\*.onPremisesSamAccountName | string | | +action_result.data.\*.onPremisesSecurityIdentifier | string | | +action_result.data.\*.onPremisesSyncEnabled | string | | +action_result.data.\*.preferredDataLocation | string | | +action_result.data.\*.preferredLanguage | string | | +action_result.data.\*.proxyAddresses | string | | SMTP:test-h@test.com +action_result.data.\*.renewedDateTime | string | | 2021-03-25T18:40:53Z +action_result.data.\*.securityEnabled | boolean | | True False +action_result.data.\*.securityIdentifier | string | | S-1-12-1-294681889-1319597617-672379543-28952017 +action_result.data.\*.theme | string | | +action_result.data.\*.visibility | string | | Private +action_result.summary.status | string | | Successfully enabled user user@test.com +action_result.message | string | | Status: Successfully enabled user user@test.com +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'remove user' +Remove a user from a specified group + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**group_object_id** | required | Object ID of group | string | `group object id` +**user_id** | required | User ID to remove from group | string | `user id` + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.group_object_id | string | `group object id` | ddb876b3-603a-437b-9814-2d46a2219a1e +action_result.parameter.user_id | string | `user id` | 17be76d0-35ed-4881-ab62-d2eb73c2ebe3 +action_result.data | string | | +action_result.summary.status | string | | Successfully removed user from group User not in group +action_result.message | string | | Status: Successfully removed user from group Status: User not in group +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'add user' +Add a user to a specified group + +Type: **generic** +Read only: **False** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**group_object_id** | required | Object ID of group | string | `group object id` +**user_id** | required | User ID to add to group | string | `user id` + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.group_object_id | string | `group object id` | ddb876b3-603a-437b-9814-2d46a2219a1e +action_result.parameter.user_id | string | `user id` | 17be76d0-35ed-4881-ab62-d2eb73c2ebe3 +action_result.data | string | | +action_result.summary.status | string | | Successfully added user to group User already in group +action_result.message | string | | Status: Successfully added user to group Status: User already in group +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'list groups' +List groups in the organization + +Type: **investigate** +Read only: **True** + +By default, only a limited set of properties are returned, to return an alternative property set use $select query parameter. For more information on using the select_string and expand_string parameters, refer to https://docs.microsoft.com/en-us/graph/query-parameters. + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**filter_string** | optional | Filter string to apply to group listing | string | +**select_string** | optional | Select string to get additional group properties. Separate multiple values with commas | string | +**expand_string** | optional | Expand string to get a resource or collection referenced by a single relationship | string | +**use_advanced_query** | optional | Use advanced query capabilities | boolean | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.expand_string | string | | members +action_result.parameter.filter_string | string | | createdDateTime ge '2014-01-01T00:00:00Z' +action_result.parameter.select_string | string | | displayName +action_result.parameter.use_advanced_query | boolean | | True False +action_result.data.\*.classification | string | | +action_result.data.\*.createdDateTime | string | | 2021-03-25T18:40:53Z +action_result.data.\*.deletedDateTime | string | | +action_result.data.\*.deletionTimestamp | string | | +action_result.data.\*.description | string | | This is for testing purpose +action_result.data.\*.dirSyncEnabled | string | | +action_result.data.\*.displayName | string | | Test-site +action_result.data.\*.expirationDateTime | string | | +action_result.data.\*.id | string | `group object id` | 2a201c95-101b-42d9-a7af-9a2fdf8193f1 +action_result.data.\*.isAssignableToRole | string | | +action_result.data.\*.lastDirSyncTime | string | | +action_result.data.\*.mail | string | `email` | Test-site@test.com +action_result.data.\*.mailEnabled | boolean | | True False +action_result.data.\*.mailNickname | string | | Test-site +action_result.data.\*.membershipRule | string | | +action_result.data.\*.membershipRuleProcessingState | string | | +action_result.data.\*.objectType | string | | Group +action_result.data.\*.odata.type | string | | test.DirectoryServices.Group +action_result.data.\*.onPremisesDomainName | string | `domain` | +action_result.data.\*.onPremisesLastSyncDateTime | string | | +action_result.data.\*.onPremisesNetBiosName | string | | +action_result.data.\*.onPremisesSamAccountName | string | | +action_result.data.\*.onPremisesSecurityIdentifier | string | | +action_result.data.\*.onPremisesSyncEnabled | string | | +action_result.data.\*.preferredDataLocation | string | | +action_result.data.\*.preferredLanguage | string | | +action_result.data.\*.proxyAddresses | string | | SMTP:test-h@test.com +action_result.data.\*.renewedDateTime | string | | 2021-03-25T18:40:53Z +action_result.data.\*.securityEnabled | boolean | | True False +action_result.data.\*.securityIdentifier | string | | S-1-12-1-294681889-1319597617-672379543-28952017 +action_result.data.\*.theme | string | | +action_result.data.\*.visibility | string | | Private +action_result.summary.num_groups | numeric | | 7 +action_result.message | string | | Num groups: 7 +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'get group' +Get information about a group + +Type: **investigate** +Read only: **True** + +By default, only a limited set of properties are returned, to return an alternative property set use $select query parameter. For more information on using the select_string and expand_string parameters, refer to https://docs.microsoft.com/en-us/graph/query-parameters. + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**object_id** | required | Object ID of group | string | `group object id` +**select_string** | optional | Select string to get additional group properties. Separate multiple values with commas | string | +**expand_string** | optional | Expand string to get a resource or collection referenced by a single relationship | string | +**use_advanced_query** | optional | Use advanced query capabilities | boolean | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.expand_string | string | | members +action_result.parameter.object_id | string | `group object id` | ddb876b3-603a-437b-9814-2d46a2219a1e +action_result.parameter.select_string | string | | displayName +action_result.parameter.use_advanced_query | boolean | | True False +action_result.data.\*.@odata.context | string | | https://graph.test.com/v1.0/$metadata#groups(id,displayName)/$entity +action_result.data.\*.classification | string | | +action_result.data.\*.createdDateTime | string | | 2020-08-05T11:59:49Z +action_result.data.\*.deletedDateTime | string | | +action_result.data.\*.deletionTimestamp | string | | +action_result.data.\*.description | string | | This is the office 365 group +action_result.data.\*.dirSyncEnabled | string | | +action_result.data.\*.displayName | string | | o365group +action_result.data.\*.expirationDateTime | string | | +action_result.data.\*.id | string | `group object id` | ddb876b3-603a-437b-9814-2d46a2219a1e +action_result.data.\*.isAssignableToRole | string | | +action_result.data.\*.lastDirSyncTime | string | | +action_result.data.\*.mail | string | `email` | bc7f9cabe@test.com +action_result.data.\*.mailEnabled | boolean | | True False +action_result.data.\*.mailNickname | string | | bc7f9cabe +action_result.data.\*.membershipRule | string | | +action_result.data.\*.membershipRuleProcessingState | string | | +action_result.data.\*.objectType | string | | Group +action_result.data.\*.odata.metadata | string | | https://graph.windows.net/1t309est-db6c-4tes-t1d2-12bf3456d78d/$metadata#directoryObjects/@Element +action_result.data.\*.odata.type | string | | test.DirectoryServices.Group +action_result.data.\*.onPremisesDomainName | string | `domain` | +action_result.data.\*.onPremisesLastSyncDateTime | string | | +action_result.data.\*.onPremisesNetBiosName | string | | +action_result.data.\*.onPremisesSamAccountName | string | | +action_result.data.\*.onPremisesSecurityIdentifier | string | | +action_result.data.\*.onPremisesSyncEnabled | string | | +action_result.data.\*.preferredDataLocation | string | | +action_result.data.\*.preferredLanguage | string | | +action_result.data.\*.proxyAddresses | string | | SMTP:bc7f9cabe@test.com +action_result.data.\*.renewedDateTime | string | | 2020-08-05T11:59:49Z +action_result.data.\*.securityEnabled | boolean | | True False +action_result.data.\*.securityIdentifier | string | | S-1-12-1-909260723-1083662375-1952945031-2402852259 +action_result.data.\*.theme | string | | +action_result.data.\*.visibility | string | | +action_result.summary.display_name | string | | o365group +action_result.summary.status | string | | Successfully retrieved group 104d4576-1544-48b5-bb7e-9f8f871aa824 +action_result.message | string | | Display name: o365group +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'list group members' +List the members in a group + +Type: **investigate** +Read only: **True** + +By default, only a limited set of properties are returned, to return an alternative property set use $select query parameter. For more information on using the select_string and expand_string parameters, refer to https://docs.microsoft.com/en-us/graph/query-parameters. + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**group_object_id** | required | Object ID of group | string | `group object id` +**select_string** | optional | Select string to get additional properties. Separate multiple values with commas | string | +**expand_string** | optional | Expand string to get a resource or collection referenced by a single relationship | string | +**use_advanced_query** | optional | Use advanced query capabilities | boolean | + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.expand_string | string | | manager +action_result.parameter.group_object_id | string | `group object id` | ebcd3130-55a1-4cbf-81b2-86408ff21203 +action_result.parameter.select_string | string | | displayName +action_result.parameter.use_advanced_query | boolean | | True False +action_result.data.\*.@odata.type | string | | #test.graph.user +action_result.data.\*.accountEnabled | boolean | | True +action_result.data.\*.ageGroup | string | | +action_result.data.\*.assignedLicenses.\*.skuId | string | | 189a915c-fe4f-4ffa-bde4-85b9628d07a0 +action_result.data.\*.assignedPlans.\*.assignedDateTime | string | | 2022-11-03T15:12:28Z +action_result.data.\*.assignedPlans.\*.capabilityStatus | string | | Deleted +action_result.data.\*.assignedPlans.\*.service | string | | AADPremiumService +action_result.data.\*.assignedPlans.\*.servicePlanId | string | | eec0eb4f-6444-4f95-aba0-50c24d67f998 +action_result.data.\*.city | string | | Palo Alto +action_result.data.\*.companyName | string | | +action_result.data.\*.consentProvidedForMinor | string | | +action_result.data.\*.country | string | | US +action_result.data.\*.createdDateTime | string | | 2016-06-09T18:33:27Z +action_result.data.\*.creationType | string | | +action_result.data.\*.deletedDateTime | string | | +action_result.data.\*.department | string | | +action_result.data.\*.displayName | string | | Firstname Lastname +action_result.data.\*.employeeHireDate | string | | +action_result.data.\*.employeeId | string | | +action_result.data.\*.employeeOrgData | string | | +action_result.data.\*.employeeType | string | | +action_result.data.\*.externalUserState | string | | +action_result.data.\*.externalUserStateChangeDateTime | string | | +action_result.data.\*.faxNumber | string | | +action_result.data.\*.givenName | string | | +action_result.data.\*.id | string | `user id` | 17be76d0-35ed-4881-ab62-d2eb73c2ebe3 +action_result.data.\*.identities.\*.issuer | string | | test.com +action_result.data.\*.identities.\*.issuerAssignedId | string | | test@user.test.com +action_result.data.\*.identities.\*.signInType | string | | userPrincipalName +action_result.data.\*.isResourceAccount | string | | +action_result.data.\*.jobTitle | string | | +action_result.data.\*.legalAgeGroupClassification | string | | +action_result.data.\*.mail | string | | +action_result.data.\*.mailNickname | string | | User +action_result.data.\*.mobilePhone | string | | +action_result.data.\*.officeLocation | string | | +action_result.data.\*.onPremisesDistinguishedName | string | | +action_result.data.\*.onPremisesDomainName | string | | +action_result.data.\*.onPremisesExtensionAttributes.extensionAttribute1 | string | | +action_result.data.\*.onPremisesExtensionAttributes.extensionAttribute10 | string | | +action_result.data.\*.onPremisesExtensionAttributes.extensionAttribute11 | string | | +action_result.data.\*.onPremisesExtensionAttributes.extensionAttribute12 | string | | +action_result.data.\*.onPremisesExtensionAttributes.extensionAttribute13 | string | | +action_result.data.\*.onPremisesExtensionAttributes.extensionAttribute14 | string | | +action_result.data.\*.onPremisesExtensionAttributes.extensionAttribute15 | string | | +action_result.data.\*.onPremisesExtensionAttributes.extensionAttribute2 | string | | +action_result.data.\*.onPremisesExtensionAttributes.extensionAttribute3 | string | | +action_result.data.\*.onPremisesExtensionAttributes.extensionAttribute4 | string | | +action_result.data.\*.onPremisesExtensionAttributes.extensionAttribute5 | string | | +action_result.data.\*.onPremisesExtensionAttributes.extensionAttribute6 | string | | +action_result.data.\*.onPremisesExtensionAttributes.extensionAttribute7 | string | | +action_result.data.\*.onPremisesExtensionAttributes.extensionAttribute8 | string | | +action_result.data.\*.onPremisesExtensionAttributes.extensionAttribute9 | string | | +action_result.data.\*.onPremisesImmutableId | string | | +action_result.data.\*.onPremisesLastSyncDateTime | string | | +action_result.data.\*.onPremisesSamAccountName | string | | +action_result.data.\*.onPremisesSecurityIdentifier | string | | +action_result.data.\*.onPremisesSyncEnabled | string | | +action_result.data.\*.onPremisesUserPrincipalName | string | | +action_result.data.\*.passwordPolicies | string | | +action_result.data.\*.passwordProfile | string | | +action_result.data.\*.postalCode | string | | 94303 +action_result.data.\*.preferredDataLocation | string | | +action_result.data.\*.preferredLanguage | string | | +action_result.data.\*.provisionedPlans.\*.capabilityStatus | string | | Enabled +action_result.data.\*.provisionedPlans.\*.provisioningStatus | string | | Success +action_result.data.\*.provisionedPlans.\*.service | string | | testCommunicationsOnline +action_result.data.\*.refreshTokensValidFromDateTime | string | | 2022-08-08T13:00:58Z +action_result.data.\*.showInAddressList | string | | +action_result.data.\*.signInSessionsValidFromDateTime | string | | 2022-08-08T13:00:58Z +action_result.data.\*.state | string | | CA +action_result.data.\*.streetAddress | string | | 2479 E. Bayshore Rd. +action_result.data.\*.surname | string | | +action_result.data.\*.usageLocation | string | | US +action_result.data.\*.userPrincipalName | string | | ews_retest@test.com +action_result.data.\*.userType | string | | Member +action_result.summary.num_members | numeric | `user id` | 3 +action_result.summary.num_users | numeric | | 3 +action_result.message | string | | Num members: 3 +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'validate group' +Returns true if a user is in a group; otherwise, false + +Type: **investigate** +Read only: **True** + +#### Action Parameters +PARAMETER | REQUIRED | DESCRIPTION | TYPE | CONTAINS +--------- | -------- | ----------- | ---- | -------- +**group_object_id** | required | Object ID of group | string | `group object id` +**user_id** | required | User ID to validate | string | `user id` + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.parameter.group_object_id | string | `group object id` | ebcd3130-55a1-4cbf-81b2-86408ff21203 +action_result.parameter.user_id | string | `user id` | user@test.com +action_result.data.\*.@odata.context | string | | https://graph.test.com/v1.0/$metadata#directoryObjects +action_result.data.\*.user_in_group | string | | +action_result.data.\*.value.\*.@odata.type | string | | #test.graph.group +action_result.data.\*.value.\*.classification | string | | +action_result.data.\*.value.\*.createdDateTime | string | | 2022-02-25T12:05:22Z +action_result.data.\*.value.\*.deletedDateTime | string | | +action_result.data.\*.value.\*.description | string | | Test group for MSGraph +action_result.data.\*.value.\*.displayName | string | | Test group for MSGraph +action_result.data.\*.value.\*.expirationDateTime | string | | +action_result.data.\*.value.\*.id | string | `user id` | 49233413-24c6-4516-a9e1-4d5f87fe34fd +action_result.data.\*.value.\*.isAssignableToRole | string | | +action_result.data.\*.value.\*.mail | string | | test@user.test.com +action_result.data.\*.value.\*.mailEnabled | boolean | | True +action_result.data.\*.value.\*.mailNickname | string | | TestgroupforMSGraph +action_result.data.\*.value.\*.membershipRule | string | | +action_result.data.\*.value.\*.membershipRuleProcessingState | string | | +action_result.data.\*.value.\*.onPremisesDomainName | string | | +action_result.data.\*.value.\*.onPremisesLastSyncDateTime | string | | +action_result.data.\*.value.\*.onPremisesNetBiosName | string | | +action_result.data.\*.value.\*.onPremisesSamAccountName | string | | +action_result.data.\*.value.\*.onPremisesSecurityIdentifier | string | | +action_result.data.\*.value.\*.onPremisesSyncEnabled | string | | +action_result.data.\*.value.\*.preferredDataLocation | string | | +action_result.data.\*.value.\*.preferredLanguage | string | | +action_result.data.\*.value.\*.renewedDateTime | string | | 2022-02-25T12:05:22Z +action_result.data.\*.value.\*.securityEnabled | boolean | | True +action_result.data.\*.value.\*.securityIdentifier | string | | S-1-12-1-1227043859-1159079110-1598939561-4248108679 +action_result.data.\*.value.\*.theme | string | | +action_result.data.\*.value.\*.visibility | string | | Private +action_result.summary.message | string | | User is member of group +action_result.summary.user_in_group | string | | +action_result.message | string | | User in group: True +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'list directory roles' +List the directory roles that are activated in the tenant + +Type: **investigate** +Read only: **True** + +

Pagination is not implemented for this action as this endpoint does not support pagination. Here is the Documentation for the same.

+ +#### Action Parameters +No parameters are required for this action + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.data.\*.deletedDateTime | string | | +action_result.data.\*.deletionTimestamp | string | | +action_result.data.\*.description | string | | Can read basic directory information. For granting access to applications, not intended for users. +action_result.data.\*.displayName | string | | Directory Readers +action_result.data.\*.id | string | `directory object id` | 02b238cb-0d15-454b-aae6-0e94993a3207 +action_result.data.\*.isSystem | boolean | | True False +action_result.data.\*.objectType | string | | Role +action_result.data.\*.odata.type | string | | test.DirectoryServices.DirectoryRole +action_result.data.\*.roleTemplateId | string | `role template id` | 88d8e3e3-8f55-4a1e-953a-9b9898b8876b +action_result.summary.num_directory_roles | numeric | | 9 +action_result.message | string | | Num directory roles: 9 +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 + +## action: 'generate token' +Generate a token + +Type: **generic** +Read only: **False** + +#### Action Parameters +No parameters are required for this action + +#### Action Output +DATA PATH | TYPE | CONTAINS | EXAMPLE VALUES +--------- | ---- | -------- | -------------- +action_result.status | string | | success failed +action_result.data | string | | +action_result.summary | string | | +action_result.message | string | | Token generated +summary.total_objects | numeric | | 1 +summary.total_objects_successful | numeric | | 1 \ No newline at end of file diff --git a/deployment-apps/msadgraph/__init__.py b/deployment-apps/msadgraph/__init__.py new file mode 100644 index 00000000..1cad73cc --- /dev/null +++ b/deployment-apps/msadgraph/__init__.py @@ -0,0 +1,14 @@ +# File: __init__.py +# +# Copyright (c) 2022-2023 Splunk Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed under +# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +# either express or implied. See the License for the specific language governing permissions +# and limitations under the License. diff --git a/deployment-apps/msadgraph/logo_msadgraph.svg b/deployment-apps/msadgraph/logo_msadgraph.svg new file mode 100644 index 00000000..e21db8b7 --- /dev/null +++ b/deployment-apps/msadgraph/logo_msadgraph.svg @@ -0,0 +1 @@ +Microsoft Logo diff --git a/deployment-apps/msadgraph/logo_msadgraph_dark.svg b/deployment-apps/msadgraph/logo_msadgraph_dark.svg new file mode 100644 index 00000000..9c2c2dbf --- /dev/null +++ b/deployment-apps/msadgraph/logo_msadgraph_dark.svg @@ -0,0 +1 @@ +Artboard 1 diff --git a/deployment-apps/msadgraph/manual_readme_content.md b/deployment-apps/msadgraph/manual_readme_content.md new file mode 100644 index 00000000..2bf5e8b6 --- /dev/null +++ b/deployment-apps/msadgraph/manual_readme_content.md @@ -0,0 +1,145 @@ +[comment]: # " File: README.md" +[comment]: # " Copyright (c) 2022-2023 Splunk Inc." +[comment]: # "" +[comment]: # "Licensed under the Apache License, Version 2.0 (the 'License');" +[comment]: # "you may not use this file except in compliance with the License." +[comment]: # "You may obtain a copy of the License at" +[comment]: # "" +[comment]: # " http://www.apache.org/licenses/LICENSE-2.0" +[comment]: # "" +[comment]: # "Unless required by applicable law or agreed to in writing, software distributed under" +[comment]: # "the License is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND," +[comment]: # "either express or implied. See the License for the specific language governing permissions" +[comment]: # "and limitations under the License." +[comment]: # "" +## Authentication + +### Microsoft Azure Application creation + +This app requires creating a Microsoft Azure Application. To do so, navigate to + in a browser and log in with a Microsoft account, then select **Azure +Active Directory** . + +1. Go to **App Registrations** and click on **+ New registration** . +2. Give the app an appropriate name. +3. Select a supported account type (configure the application to be multitenant). +4. Click on the **Register** . + - Under **Certificates & secrets** , add **New client secret** . Note this key somewhere + secure, as it cannot be retrieved after closing the window. + - Under **Redirect URIs** we will be updating the entry of https://phantom.local to reflect + the actual redirect URI. We will get this from the SOAR asset we create below in the section + titled "Configure the MS Graph for Active Directory SOAR app Asset" + +### Delegated Permissions configuration + +Use this procedure to provide non-admin permissions to the app. To do so, navigate to + in a browser and log in with a Microsoft account, then navigate to the +previously created app configuration. + +1. Under **API Permissions** , click on **Add a permission** . +2. Go to **Microsoft Graph Permissions** , the following **Delegated Permissions** need to be + added: + - User.ReadWrite.All + - Directory.ReadWrite.All + - Directory.AccessAsUser.All + - User.ManageIdentities.All + - Group.ReadWrite.All + - GroupMember.ReadWrite.All + - RoleManagement.ReadWrite.Directory + - offline_access +3. Click on the **Add permissions** . +4. After making these changes, click on **Grant admin consent** . + +### Application Permissions configuration + +Use this procedure to provide admin permissions to the app. To do so, navigate to + in a browser and log in with a Microsoft account, then navigate to the +previously created app configuration. + +1. Under **API Permissions** , click on **Add a permission** . +2. Go to **Microsoft Graph Permissions** , the following **Application Permissions** need to be + added: + - User.ReadWrite.All + - Directory.ReadWrite.All + - User.ManageIdentities.All + - Group.ReadWrite.All + - GroupMember.ReadWrite.All + - RoleManagement.ReadWrite.Directory +3. Click on the **Add permissions** . +4. After making these changes, click on **Grant admin consent** . + +#### Note: **reset password** action is not supported with Application permissions + +## Configure the MS Graph for Active Directory SOAR app Asset + +When creating an asset for the **MS Graph for Active Directory** app, place the **Application ID** +of the app created during the previous step in the **Client ID** field and place the password +generated during the app creation process in the **Client Secret** field. Then, after filling out +the **Tenant** field, click **SAVE** . + +After saving, a new field will appear in the **Asset Settings** tab. Take the URL found in the +**POST incoming for MS Graph to this location** field and place it in the **Redirect URIs** field of +the Azure Application configuration page. To this URL, add **/result** . After doing so the URL +should look something like: + +https://\/rest/handler/msgraphforactivedirectory_f2a239df-acb2-47d6-861c-726a435cfe76/\/result + + +Once again, click on Save. + +## Enable Application Permissions + +If you have received admin consent to use application permissions, make sure to check the **Admin +Access Required** and **Admin Consent Already Provided** checkboxes on the asset. + +## User Permissions + +To complete the authorization process, this app needs permission to view assets, which is not +granted by default. First, under **asset settings** , check which user is listed under **Select a +user on behalf of which automated actions can be executed** . By default, the user will be +**automation** , but this user can be changed by clicking **EDIT** at the bottom of the window. To +give this user permission to view assets, follow these steps: + +- In the main drop-down menu, select **Administration** , then select the **User Management** , + and under that tab, select **Roles** . Finally, click **+ ROLE** . +- In the **Add Role** wizard, give the role a name (e.g **Asset Viewer** ), and provide a + description. Subsequently, under **Available Users** , add the user assigned to the asset viewed + earlier. Then click the **Permissions** tab. +- On the permission tab, under **Available Privileges** , give the role the **View Assets** + privilege. Then click **SAVE** . + +## Method to Run Test Connectivity (for delegated permissions) + +After setting up the asset and user, click the **TEST CONNECTIVITY** button. A window should pop up +and display a URL. Navigate to this URL in a separate browser tab. This new tab will redirect to a +Microsoft login page. Log in to a Microsoft account with administrator privileges to the Microsoft +AD environment. After logging in, review the requested permissions listed, then click **Accept** . +Finally, close that tab. The test connectivity window should show success. + +The app should now be ready to use. + +## State File Permissions + +Please check the permissions for the state file as mentioned below. + +#### State Filepath + +- For Root Install Instance: + /opt/phantom/local_data/app_states/f2a239df-acb2-47d6-861c-726a435cfe76/{asset_id}\_state.json +- For Non-Root Install Instance: + /\/local_data/app_states/f2a239df-acb2-47d6-861c-726a435cfe76/{asset_id}\_state.json + +#### State File Permissions + +- File Rights: rw-rw-r-- (664) (The SOAR user should have read and write access for the state + file) +- File Owner: appropriate SOAR user + +## Port Details + +The app uses HTTP/ HTTPS protocol for communicating with the Microsoft Graph server. Below are the +default ports used by the Splunk SOAR Connector. + +| Service Name | Transport Protocol | Port | +|--------------|--------------------|------| +| https | tcp | 443 | diff --git a/deployment-apps/msadgraph/msadgraph.json b/deployment-apps/msadgraph/msadgraph.json new file mode 100644 index 00000000..2acb359d --- /dev/null +++ b/deployment-apps/msadgraph/msadgraph.json @@ -0,0 +1,3871 @@ +{ + "appid": "f2a239df-acb2-47d6-861c-726a435cfe76", + "name": "MS Graph for Active Directory", + "description": "Connects to Microsoft Active Directory using MS Graph REST API services to support various generic and investigative actions", + "type": "identity management", + "product_vendor": "Microsoft", + "logo": "logo_msadgraph.svg", + "logo_dark": "logo_msadgraph_dark.svg", + "product_name": "MS Graph for Active Directory", + "product_version_regex": ".*", + "publisher": "Splunk", + "contributors": [ + { + "name": "Mathieu A. Cormier" + } + ], + "license": "Copyright (c) 2022-2023 Splunk Inc.", + "app_version": "1.4.0", + "python_version": "3", + "utctime_updated": "2022-04-18T12:59:04.000000Z", + "package_name": "phantom_msadgraph", + "main_module": "msadgraph_connector.py", + "min_phantom_version": "6.1.0", + "fips_compliant": true, + "latest_tested_versions": [ + "Cloud 2023-9-20, API Version: 1.0" + ], + "app_wizard_version": "1.0.0", + "rest_handler": "msadgraph_connector._handle_rest_request", + "configuration": { + "tenant_id": { + "description": "Tenant (Tenant ID or Tenant Name)", + "data_type": "string", + "required": true, + "order": 0 + }, + "client_id": { + "description": "Application ID", + "data_type": "string", + "required": true, + "order": 2 + }, + "client_secret": { + "description": "Client Secret", + "data_type": "password", + "required": true, + "order": 3 + }, + "region": { + "data_type": "string", + "description": "Microsoft AD Region", + "default": "Global", + "order": 1, + "value_list": [ + "Global", + "US Gov L4", + "US Gov L5 (DOD)", + "Germany", + "China (21Vianet)" + ] + }, + "admin_access_required": { + "description": "Admin Access Required", + "data_type": "boolean", + "default": false, + "order": 4 + }, + "admin_access_granted": { + "description": "Admin Consent Already Provided", + "data_type": "boolean", + "default": false, + "order": 5 + } + }, + "actions": [ + { + "action": "test connectivity", + "description": "Use supplied credentials to generate a token with MS Graph", + "type": "test", + "identifier": "test_connectivity", + "read_only": true, + "parameters": {}, + "output": [], + "versions": "EQ(*)" + }, + { + "action": "list users", + "description": "Get a list of users", + "verbose": "For more information on using the filter_string, select_string and expand_string parameters, refer to https://docs.microsoft.com/en-us/graph/query-parameters. By default, only a limited set of properties are returned, to return an alternative property set use $select query parameter.", + "type": "investigate", + "identifier": "list_users", + "read_only": true, + "parameters": { + "filter_string": { + "description": "Filter string to apply to user listing", + "data_type": "string", + "order": 0 + }, + "select_string": { + "description": "Select string to get additional user properties. Separate multiple values with commas", + "data_type": "string", + "order": 1 + }, + "expand_string": { + "description": "Expand string to get a resource or collection referenced by a single relationship", + "data_type": "string", + "order": 2 + }, + "use_advanced_query": { + "description": "Use advanced query capabilities", + "data_type": "boolean", + "default": false, + "order": 3 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] + }, + { + "data_path": "action_result.parameter.expand_string", + "data_type": "string", + "example_values": [ + "manager" + ] + }, + { + "data_path": "action_result.parameter.filter_string", + "data_type": "string", + "example_values": [ + "startswith(displayName,'User')" + ] + }, + { + "data_path": "action_result.parameter.select_string", + "data_type": "string", + "example_values": [ + "displayName" + ] + }, + { + "data_path": "action_result.parameter.use_advanced_query", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.accountEnabled", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.ageGroup", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.assignedLicenses.*.skuId", + "data_type": "string", + "example_values": [ + "189a915c-fe4f-4ffa-bde4-85b9628d07a0" + ] + }, + { + "data_path": "action_result.data.*.assignedPlans.*.assignedTimestamp", + "data_type": "string", + "example_values": [ + "2017-08-29T02:31:40Z" + ] + }, + { + "data_path": "action_result.data.*.assignedPlans.*.capabilityStatus", + "data_type": "string", + "example_values": [ + "Enabled" + ] + }, + { + "data_path": "action_result.data.*.assignedPlans.*.service", + "data_type": "string", + "example_values": [ + "OfficeForms" + ] + }, + { + "data_path": "action_result.data.*.assignedPlans.*.servicePlanId", + "data_type": "string", + "example_values": [ + "e212cbc7-0961-4c40-9825-01117710dcb1" + ] + }, + { + "data_path": "action_result.data.*.city", + "data_type": "string", + "example_values": [ + "Palo Alto" + ] + }, + { + "data_path": "action_result.data.*.companyName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.consentProvidedForMinor", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.country", + "data_type": "string", + "example_values": [ + "US" + ] + }, + { + "data_path": "action_result.data.*.createdDateTime", + "data_type": "string", + "example_values": [ + "2019-05-21T22:27:20Z" + ] + }, + { + "data_path": "action_result.data.*.creationType", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.deletionTimestamp", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.department", + "data_type": "string", + "example_values": [ + "Sales" + ] + }, + { + "data_path": "action_result.data.*.dirSyncEnabled", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.displayName", + "data_type": "string", + "column_name": "Display Name", + "column_order": 0, + "example_values": [ + "User" + ] + }, + { + "data_path": "action_result.data.*.employeeId", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.facsimileTelephoneNumber", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.givenName", + "data_type": "string", + "example_values": [ + "testuser" + ] + }, + { + "data_path": "action_result.data.*.id", + "data_type": "string", + "column_name": "Object ID", + "column_order": 1, + "example_values": [ + "e4c722ac-3b83-478d-8f52-c388885dc30f" + ], + "contains": [ + "user id" + ] + }, + { + "data_path": "action_result.data.*.immutableId", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.isCompromised", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.jobTitle", + "data_type": "string", + "example_values": [ + "Sales Manager" + ] + }, + { + "data_path": "action_result.data.*.lastDirSyncTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.legalAgeGroupClassification", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.mail", + "data_type": "string", + "example_values": [ + "user@test.com" + ], + "contains": [ + "email" + ] + }, + { + "data_path": "action_result.data.*.mailNickname", + "data_type": "string", + "example_values": [ + "testmail" + ] + }, + { + "data_path": "action_result.data.*.mobile", + "data_type": "string", + "example_values": [ + "+1 5556378688" + ] + }, + { + "data_path": "action_result.data.*.mobilePhone", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.objectType", + "data_type": "string", + "example_values": [ + "User" + ] + }, + { + "data_path": "action_result.data.*.odata.type", + "data_type": "string", + "example_values": [ + "test.DirectoryServices.User" + ] + }, + { + "data_path": "action_result.data.*.officeLocation", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesDistinguishedName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesSecurityIdentifier", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.otherMails", + "data_type": "string", + "example_values": [ + "user.test@outlook.com" + ], + "contains": [ + "email" + ] + }, + { + "data_path": "action_result.data.*.passwordPolicies", + "data_type": "string", + "example_values": [ + "None" + ] + }, + { + "data_path": "action_result.data.*.passwordProfile", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.passwordProfile.enforceChangePasswordPolicy", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.passwordProfile.forceChangePasswordNextLogin", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.passwordProfile.password", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.physicalDeliveryOfficeName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.postalCode", + "data_type": "string", + "example_values": [ + "94303" + ] + }, + { + "data_path": "action_result.data.*.preferredLanguage", + "data_type": "string", + "example_values": [ + "en-US" + ] + }, + { + "data_path": "action_result.data.*.provisionedPlans.*.capabilityStatus", + "data_type": "string", + "example_values": [ + "Enabled" + ] + }, + { + "data_path": "action_result.data.*.provisionedPlans.*.provisioningStatus", + "data_type": "string", + "example_values": [ + "Success" + ] + }, + { + "data_path": "action_result.data.*.provisionedPlans.*.service", + "data_type": "string", + "example_values": [ + "exchange" + ] + }, + { + "data_path": "action_result.data.*.proxyAddresses", + "data_type": "string", + "example_values": [ + "SMTP:user1@test.com" + ] + }, + { + "data_path": "action_result.data.*.refreshTokensValidFromDateTime", + "data_type": "string", + "example_values": [ + "2017-09-27T22:54:59Z" + ] + }, + { + "data_path": "action_result.data.*.showInAddressList", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.sipProxyAddress", + "data_type": "string", + "example_values": [ + "user@test.com" + ], + "contains": [ + "email" + ] + }, + { + "data_path": "action_result.data.*.state", + "data_type": "string", + "example_values": [ + "CA" + ] + }, + { + "data_path": "action_result.data.*.streetAddress", + "data_type": "string", + "example_values": [ + "2479 E. Bayshore Rd." + ] + }, + { + "data_path": "action_result.data.*.surname", + "data_type": "string", + "example_values": [ + "Test_surname" + ] + }, + { + "data_path": "action_result.data.*.telephoneNumber", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.thumbnailPhoto@odata.mediaEditLink", + "data_type": "string", + "example_values": [ + "directoryObjects/6132ca31-7a09-434f-a269-abe836d0c01e/test.DirectoryServices.User/thumbnailPhoto" + ] + }, + { + "data_path": "action_result.data.*.usageLocation", + "data_type": "string", + "example_values": [ + "US" + ] + }, + { + "data_path": "action_result.data.*.userPrincipalName", + "data_type": "string", + "column_name": "User Principal Name", + "column_order": 2, + "example_values": [ + "user@test.com" + ], + "contains": [ + "user id" + ] + }, + { + "data_path": "action_result.data.*.userState", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.userStateChangedOn", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.userType", + "data_type": "string", + "example_values": [ + "Member" + ] + }, + { + "data_path": "action_result.summary.num_users", + "data_type": "numeric", + "example_values": [ + 8 + ] + }, + { + "data_path": "action_result.summary.result_found", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.summary.total_results", + "data_type": "numeric", + "example_values": [ + 7 + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Successfully listed users" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "custom", + "title": "List Users", + "view": "msadgraph_view.display_view" + }, + "versions": "EQ(*)" + }, + { + "action": "reset password", + "description": "Reset or set a user's password in a Microsoft AD environment", + "type": "contain", + "identifier": "reset_password", + "read_only": false, + "parameters": { + "user_id": { + "description": "User ID to change password - can be user principal name or object ID", + "data_type": "string", + "required": true, + "primary": true, + "order": 0, + "contains": [ + "user id" + ] + }, + "force_change": { + "description": "Force user to change password on next login", + "data_type": "boolean", + "default": true, + "order": 1 + }, + "temp_password": { + "description": "Temporary password for user", + "data_type": "string", + "required": true, + "order": 2 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ], + "column_name": "Status", + "column_order": 1 + }, + { + "data_path": "action_result.parameter.force_change", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.parameter.temp_password", + "data_type": "string", + "example_values": [ + "Temp_PA$$w0rd" + ] + }, + { + "data_path": "action_result.parameter.user_id", + "data_type": "string", + "example_values": [ + "ee3dc4f2-70f9-446f-a19e-6b4e95ba030d", + "user@test.com" + ], + "contains": [ + "user id" + ], + "column_name": "User ID", + "column_order": 0 + }, + { + "data_path": "action_result.data", + "data_type": "string" + }, + { + "data_path": "action_result.summary.status", + "data_type": "string", + "example_values": [ + "Successfully reset user password" + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Status: Successfully reset user password" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "width": 12, + "title": "User Password Reset", + "type": "table", + "height": 5 + }, + "versions": "EQ(*)" + }, + { + "action": "disable tokens", + "description": "Invalidate all active refresh tokens for a user in a Microsoft AD environment", + "type": "contain", + "identifier": "invalidate_tokens", + "read_only": false, + "parameters": { + "user_id": { + "description": "User ID to disable tokens of - can be user principal name or object ID", + "data_type": "string", + "required": true, + "primary": true, + "order": 0, + "contains": [ + "user id" + ] + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ], + "column_name": "Status", + "column_order": 1 + }, + { + "data_path": "action_result.parameter.user_id", + "data_type": "string", + "example_values": [ + "ee3dc4f2-70f9-446f-a19e-6b4e95ba030d", + "user@test.com" + ], + "contains": [ + "user id" + ], + "column_name": "User ID", + "column_order": 0 + }, + { + "data_path": "action_result.data", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.@odata.context", + "data_type": "string", + "example_values": [ + "https://graph.test.com/v1.0/$metadata#Edm.Boolean" + ] + }, + { + "data_path": "action_result.data.*.odata.metadata", + "data_type": "string", + "example_values": [ + "https://graph.windows.net/1t309est-db6c-4tes-t1d2-12bf3456d78d/$metadata#Edm.Null" + ], + "contains": [ + "url" + ] + }, + { + "data_path": "action_result.data.*.odata.null", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.value", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.summary.status", + "data_type": "string", + "example_values": [ + "Successfully disabled tokens" + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Successfully invalidated tokens", + "Status: Successfully disabled tokens" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "width": 12, + "title": "Invalidate Tokens", + "type": "table", + "height": 5 + }, + "versions": "EQ(*)" + }, + { + "action": "enable user", + "description": "Enable a user", + "type": "generic", + "identifier": "enable_user", + "read_only": false, + "undo": "disable user", + "parameters": { + "user_id": { + "description": "User ID to enable - can be user principal name or object ID", + "data_type": "string", + "required": true, + "primary": true, + "order": 0, + "contains": [ + "user id" + ] + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ], + "column_name": "Status", + "column_order": 1 + }, + { + "data_path": "action_result.parameter.user_id", + "data_type": "string", + "example_values": [ + "user@test.com" + ], + "contains": [ + "user id" + ], + "column_name": "User ID", + "column_order": 0 + }, + { + "data_path": "action_result.data", + "data_type": "string" + }, + { + "data_path": "action_result.summary.status", + "data_type": "string", + "example_values": [ + "Successfully enabled user user@test.com" + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Status: Successfully enabled user user@test.com" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" + }, + { + "action": "disable user", + "description": "Disable a user", + "type": "generic", + "identifier": "disable_user", + "read_only": false, + "undo": "enable user", + "parameters": { + "user_id": { + "description": "User ID to disable - can be user principal name or object ID", + "data_type": "string", + "required": true, + "primary": true, + "order": 0, + "contains": [ + "user id" + ] + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ], + "column_name": "Status", + "column_order": 1 + }, + { + "data_path": "action_result.parameter.user_id", + "data_type": "string", + "example_values": [ + "user@test.com" + ], + "contains": [ + "user id" + ], + "column_name": "User ID", + "column_order": 0 + }, + { + "data_path": "action_result.data", + "data_type": "string" + }, + { + "data_path": "action_result.summary.status", + "data_type": "string", + "example_values": [ + "Successfully disabled user user@test.com" + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Status: Successfully disabled user user@test.com" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" + }, + { + "action": "list user devices", + "description": "List devices for a specified user", + "verbose": "By default, only a limited set of properties are returned, to return an alternative property set use $select query parameter. For more information on using the select_string parameter, refer to this documentation.", + "type": "investigate", + "identifier": "list_user_devices", + "read_only": true, + "parameters": { + "user_id": { + "description": "User ID - can be user principal name or object ID", + "data_type": "string", + "primary": true, + "required": true, + "order": 0, + "contains": [ + "user id" + ] + }, + "select_string": { + "description": "Select string to get additional user properties. Separate multiple values with commas", + "data_type": "string", + "order": 1 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] + }, + { + "data_path": "action_result.parameter.select_string", + "data_type": "string", + "example_values": [ + "displayName" + ] + }, + { + "data_path": "action_result.parameter.user_id", + "data_type": "string", + "example_values": [ + "user@test.com" + ], + "contains": [ + "user id" + ] + }, + { + "data_path": "action_result.data.*.@odata.type", + "data_type": "string", + "example_values": [ + "#test.graph.device" + ] + }, + { + "data_path": "action_result.data.*.accountEnabled", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.alternativeSecurityIds.*.identityProvider", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.alternativeSecurityIds.*.key", + "data_type": "string", + "example_values": [ + "WAA1ADAAOQA6ADwAUwBIAEEAMQAtAFQAUAAtAFAAVQBCAEsARQBZAD4AOQA5AEEARQAwADgAOABDAEUANAA1ADgAMABCADcAQgBGAEEARQA2ADEAQQBCADYANAA3ADYANgA5ADUAOAAzAEQANABFAEYARQA5ADYAOAAyAHkAcQBSAEIANwBrAGEAMQA4AEoATAByACsAegB4AE8AYwB6AE8AYgBNAFEANQBZAEgAbgB0AFQAdgBOAG0AbgA5AEQAZQA2AFgAVQBUAGgAcwBFAD0A" + ] + }, + { + "data_path": "action_result.data.*.alternativeSecurityIds.*.type", + "data_type": "numeric", + "example_values": [ + 2 + ] + }, + { + "data_path": "action_result.data.*.approximateLastSignInDateTime", + "data_type": "string", + "example_values": [ + "2019-09-26T03:42:15Z" + ] + }, + { + "data_path": "action_result.data.*.complianceExpirationDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.createdDateTime", + "data_type": "string", + "example_values": [ + "2019-09-26T03:42:15Z" + ] + }, + { + "data_path": "action_result.data.*.deletedDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.deviceCategory", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.deviceId", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.deviceMetadata", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.deviceOwnership", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.deviceVersion", + "data_type": "numeric" + }, + { + "data_path": "action_result.data.*.displayName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.domainName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.enrollmentProfileName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.enrollmentType", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.extensionAttributes.extensionAttribute1", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.extensionAttributes.extensionAttribute10", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.extensionAttributes.extensionAttribute11", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.extensionAttributes.extensionAttribute12", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.extensionAttributes.extensionAttribute13", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.extensionAttributes.extensionAttribute14", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.extensionAttributes.extensionAttribute15", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.extensionAttributes.extensionAttribute2", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.extensionAttributes.extensionAttribute3", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.extensionAttributes.extensionAttribute4", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.extensionAttributes.extensionAttribute5", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.extensionAttributes.extensionAttribute6", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.extensionAttributes.extensionAttribute7", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.extensionAttributes.extensionAttribute8", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.extensionAttributes.extensionAttribute9", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.externalSourceName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.id", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.isCompliant", + "data_type": "boolean" + }, + { + "data_path": "action_result.data.*.isManaged", + "data_type": "boolean" + }, + { + "data_path": "action_result.data.*.isRooted", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.managementType", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.manufacturer", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.mdmAppId", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.model", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesLastSyncDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesSyncEnabled", + "data_type": "boolean" + }, + { + "data_path": "action_result.data.*.operatingSystem", + "data_type": "string", + "example_values": [ + "Windows" + ] + }, + { + "data_path": "action_result.data.*.operatingSystemVersion", + "data_type": "string", + "example_values": [ + "10.0.18362.0" + ] + }, + { + "data_path": "action_result.data.*.profileType", + "data_type": "string", + "example_values": [ + "RegisteredDevice" + ] + }, + { + "data_path": "action_result.data.*.registrationDateTime", + "data_type": "string", + "example_values": [ + "2019-09-26T03:42:15Z" + ] + }, + { + "data_path": "action_result.data.*.sourceType", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.trustType", + "data_type": "string", + "example_values": [ + "Workplace" + ] + }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, + { + "data_path": "action_result.summary.status", + "data_type": "string", + "example_values": [ + "Successfully retrieved owned devices for user test@user.test.com" + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Status: Successfully retrieved owned devices for user test@user.test.com" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "custom", + "title": "Owned Devices", + "view": "msadgraph_view.display_view" + }, + "versions": "EQ(*)" + }, + { + "action": "list user attributes", + "description": "List attributes for all or a specified user", + "verbose": "By default, only a limited set of properties are returned, to return an alternative property set use $select query parameter. For more information on using the select_string and expand_string parameters, refer to https://docs.microsoft.com/en-us/graph/query-parameters.", + "type": "investigate", + "identifier": "list_user_attributes", + "read_only": true, + "parameters": { + "user_id": { + "description": "User ID - can be user principal name or object ID", + "data_type": "string", + "primary": true, + "order": 0, + "contains": [ + "user id" + ] + }, + "select_string": { + "description": "Select string to get additional user properties. Separate multiple values with commas", + "data_type": "string", + "order": 1 + }, + "expand_string": { + "description": "Expand string to get a resource or collection referenced by a single relationship", + "data_type": "string", + "order": 2 + }, + "use_advanced_query": { + "description": "Use advanced query capabilities", + "data_type": "boolean", + "default": false, + "order": 3 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] + }, + { + "data_path": "action_result.parameter.expand_string", + "data_type": "string", + "example_values": [ + "manager" + ] + }, + { + "data_path": "action_result.parameter.select_string", + "data_type": "string", + "example_values": [ + "displayName" + ] + }, + { + "data_path": "action_result.parameter.use_advanced_query", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.parameter.user_id", + "data_type": "string", + "example_values": [ + "user@test.com" + ], + "contains": [ + "user id" + ] + }, + { + "data_path": "action_result.data.*.@odata.context", + "data_type": "string", + "example_values": [ + "https://graph.test.com/v1.0/$metadata#users/$entity" + ] + }, + { + "data_path": "action_result.data.*.accountEnabled", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.ageGroup", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.assignedLicenses.*.skuId", + "data_type": "string", + "example_values": [ + "f30db892-07e9-47e9-837c-80727f46fd3d" + ] + }, + { + "data_path": "action_result.data.*.assignedPlans.*.assignedTimestamp", + "data_type": "string", + "example_values": [ + "2019-04-26T07:21:18Z" + ] + }, + { + "data_path": "action_result.data.*.assignedPlans.*.capabilityStatus", + "data_type": "string", + "example_values": [ + "Enabled" + ] + }, + { + "data_path": "action_result.data.*.assignedPlans.*.service", + "data_type": "string", + "example_values": [ + "exchange" + ] + }, + { + "data_path": "action_result.data.*.assignedPlans.*.servicePlanId", + "data_type": "string", + "example_values": [ + "33c4f319-9bdd-48d6-9c4d-410b750a4a5a" + ] + }, + { + "data_path": "action_result.data.*.city", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.companyName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.consentProvidedForMinor", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.country", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.createdDateTime", + "data_type": "string", + "example_values": [ + "2019-05-02T20:27:59Z" + ] + }, + { + "data_path": "action_result.data.*.creationType", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.deletionTimestamp", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.department", + "data_type": "string", + "example_values": [ + "Sales" + ] + }, + { + "data_path": "action_result.data.*.dirSyncEnabled", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.displayName", + "data_type": "string", + "example_values": [ + "Test User" + ] + }, + { + "data_path": "action_result.data.*.employeeId", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.facsimileTelephoneNumber", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.givenName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.id", + "data_type": "string", + "example_values": [ + "7d55d7e6-cf5a-4dd2-a176-57a3c33b7fa9" + ], + "contains": [ + "user id" + ] + }, + { + "data_path": "action_result.data.*.identities.*.issuer", + "data_type": "string", + "example_values": [ + "test.com" + ] + }, + { + "data_path": "action_result.data.*.identities.*.issuerAssignedId", + "data_type": "string", + "example_values": [ + "test2@user.test.com" + ] + }, + { + "data_path": "action_result.data.*.identities.*.signInType", + "data_type": "string", + "example_values": [ + "userPrincipalName" + ] + }, + { + "data_path": "action_result.data.*.immutableId", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.isCompromised", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.jobTitle", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.lastDirSyncTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.legalAgeGroupClassification", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.mail", + "data_type": "string", + "contains": [ + "email" + ] + }, + { + "data_path": "action_result.data.*.mailNickname", + "data_type": "string", + "example_values": [ + "test" + ] + }, + { + "data_path": "action_result.data.*.mobile", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.mobilePhone", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.objectId", + "data_type": "string", + "example_values": [ + "59f51194-1998-4932-a8ac-468e59374edc" + ] + }, + { + "data_path": "action_result.data.*.objectType", + "data_type": "string", + "example_values": [ + "User" + ] + }, + { + "data_path": "action_result.data.*.odata.metadata", + "data_type": "string", + "example_values": [ + "https://graph.windows.net/1t309est-db6c-4tes-t1d2-12bf3456d78d/$metadata#directoryObjects/@Element" + ] + }, + { + "data_path": "action_result.data.*.odata.type", + "data_type": "string", + "example_values": [ + "test.DirectoryServices.User" + ] + }, + { + "data_path": "action_result.data.*.officeLocation", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesDistinguishedName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesSecurityIdentifier", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.otherMails", + "data_type": "string", + "example_values": [ + "user@test.com" + ], + "contains": [ + "email" + ] + }, + { + "data_path": "action_result.data.*.passwordPolicies", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.passwordProfile", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.passwordProfile.enforceChangePasswordPolicy", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.passwordProfile.forceChangePasswordNextLogin", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.passwordProfile.password", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.physicalDeliveryOfficeName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.postalCode", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.preferredLanguage", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.provisionedPlans.*.capabilityStatus", + "data_type": "string", + "example_values": [ + "Enabled" + ] + }, + { + "data_path": "action_result.data.*.provisionedPlans.*.provisioningStatus", + "data_type": "string", + "example_values": [ + "Success" + ] + }, + { + "data_path": "action_result.data.*.provisionedPlans.*.service", + "data_type": "string", + "example_values": [ + "exchange" + ] + }, + { + "data_path": "action_result.data.*.proxyAddresses", + "data_type": "string", + "example_values": [ + "SMTP:test_shared_mailbox@test.com" + ] + }, + { + "data_path": "action_result.data.*.refreshTokensValidFromDateTime", + "data_type": "string", + "example_values": [ + "2019-05-16T19:54:18Z" + ] + }, + { + "data_path": "action_result.data.*.showInAddressList", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.sipProxyAddress", + "data_type": "string", + "contains": [ + "email" + ] + }, + { + "data_path": "action_result.data.*.state", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.streetAddress", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.surname", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.telephoneNumber", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.thumbnailPhoto@odata.mediaEditLink", + "data_type": "string", + "example_values": [ + "directoryObjects/59f12345-1998-4932-a8ac-468e59374edc/test.DirectoryServices.User/thumbnailPhoto" + ] + }, + { + "data_path": "action_result.data.*.usageLocation", + "data_type": "string", + "example_values": [ + "US" + ] + }, + { + "data_path": "action_result.data.*.userPrincipalName", + "data_type": "string", + "example_values": [ + "user@test.com" + ], + "contains": [ + "user id" + ] + }, + { + "data_path": "action_result.data.*.userState", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.userStateChangedOn", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.userType", + "data_type": "string", + "example_values": [ + "Member" + ] + }, + { + "data_path": "action_result.summary.status", + "data_type": "string", + "example_values": [ + "Successfully retrieved user attributes", + "Successfully retrieved attributes for user user@test.com" + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Status: Successfully retrieved user attributes", + "Status: Successfully retrieved attributes for user user@test.com, User enabled: False" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "custom", + "title": "list user attributes", + "view": "msadgraph_view.display_view" + }, + "versions": "EQ(*)" + }, + { + "action": "set user attribute", + "description": "Set an attribute for a user", + "type": "generic", + "identifier": "set_user_attribute", + "read_only": false, + "parameters": { + "user_id": { + "description": "User ID - can be user principal name or object ID", + "data_type": "string", + "required": true, + "primary": true, + "order": 0, + "contains": [ + "user id" + ] + }, + "ph_0": { + "description": "Placeholder", + "data_type": "ph", + "order": 1 + }, + "attribute": { + "description": "Attribute to set", + "data_type": "string", + "required": true, + "order": 2 + }, + "attribute_value": { + "description": "Value of attribute to set", + "data_type": "string", + "required": true, + "order": 3 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ], + "column_name": "Status", + "column_order": 3 + }, + { + "data_path": "action_result.parameter.attribute", + "data_type": "string", + "example_values": [ + "department" + ], + "column_name": "Attribute Name", + "column_order": 1 + }, + { + "data_path": "action_result.parameter.attribute_value", + "data_type": "string", + "example_values": [ + "Sales" + ], + "column_name": "Attribute Value", + "column_order": 2 + }, + { + "data_path": "action_result.parameter.user_id", + "data_type": "string", + "example_values": [ + "user@test.com" + ], + "contains": [ + "user id" + ], + "column_name": "User ID", + "column_order": 0 + }, + { + "data_path": "action_result.data", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.classification", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.createdDateTime", + "data_type": "string", + "example_values": [ + "2021-03-25T18:40:53Z" + ] + }, + { + "data_path": "action_result.data.*.deletedDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.deletionTimestamp", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.description", + "data_type": "string", + "example_values": [ + "This is for testing purpose" + ] + }, + { + "data_path": "action_result.data.*.dirSyncEnabled", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.displayName", + "data_type": "string", + "example_values": [ + "Test-site" + ] + }, + { + "data_path": "action_result.data.*.expirationDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.id", + "data_type": "string", + "example_values": [ + "2a201c95-101b-42d9-a7af-9a2fdf8193f1" + ], + "contains": [ + "user id" + ] + }, + { + "data_path": "action_result.data.*.isAssignableToRole", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.lastDirSyncTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.mail", + "data_type": "string", + "example_values": [ + "Test-site@test.com" + ], + "contains": [ + "email" + ] + }, + { + "data_path": "action_result.data.*.mailEnabled", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.mailNickname", + "data_type": "string", + "example_values": [ + "Test-site" + ] + }, + { + "data_path": "action_result.data.*.membershipRule", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.membershipRuleProcessingState", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.objectType", + "data_type": "string", + "example_values": [ + "Group" + ] + }, + { + "data_path": "action_result.data.*.odata.type", + "data_type": "string", + "example_values": [ + "test.DirectoryServices.Group" + ] + }, + { + "data_path": "action_result.data.*.onPremisesDomainName", + "data_type": "string", + "contains": [ + "domain" + ] + }, + { + "data_path": "action_result.data.*.onPremisesLastSyncDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesNetBiosName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesSamAccountName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesSecurityIdentifier", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesSyncEnabled", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.preferredDataLocation", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.preferredLanguage", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.proxyAddresses", + "data_type": "string", + "example_values": [ + "SMTP:test-h@test.com" + ] + }, + { + "data_path": "action_result.data.*.renewedDateTime", + "data_type": "string", + "example_values": [ + "2021-03-25T18:40:53Z" + ] + }, + { + "data_path": "action_result.data.*.securityEnabled", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.securityIdentifier", + "data_type": "string", + "example_values": [ + "S-1-12-1-294681889-1319597617-672379543-28952017" + ] + }, + { + "data_path": "action_result.data.*.theme", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.visibility", + "data_type": "string", + "example_values": [ + "Private" + ] + }, + { + "data_path": "action_result.summary.status", + "data_type": "string", + "example_values": [ + "Successfully enabled user user@test.com" + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Status: Successfully enabled user user@test.com" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" + }, + { + "action": "remove user", + "description": "Remove a user from a specified group", + "type": "generic", + "identifier": "remove_user", + "read_only": false, + "undo": "add user", + "parameters": { + "group_object_id": { + "description": "Object ID of group", + "data_type": "string", + "required": true, + "primary": true, + "order": 0, + "contains": [ + "group object id" + ] + }, + "user_id": { + "description": "User ID to remove from group", + "data_type": "string", + "required": true, + "primary": true, + "order": 1, + "contains": [ + "user id" + ] + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ], + "column_name": "Status", + "column_order": 2 + }, + { + "data_path": "action_result.parameter.group_object_id", + "data_type": "string", + "example_values": [ + "ddb876b3-603a-437b-9814-2d46a2219a1e" + ], + "contains": [ + "group object id" + ], + "column_name": "Group Object ID", + "column_order": 0 + }, + { + "data_path": "action_result.parameter.user_id", + "data_type": "string", + "example_values": [ + "17be76d0-35ed-4881-ab62-d2eb73c2ebe3" + ], + "contains": [ + "user id" + ], + "column_name": "User ID", + "column_order": 1 + }, + { + "data_path": "action_result.data", + "data_type": "string" + }, + { + "data_path": "action_result.summary.status", + "data_type": "string", + "example_values": [ + "Successfully removed user from group", + "User not in group" + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Status: Successfully removed user from group", + "Status: User not in group" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" + }, + { + "action": "add user", + "description": "Add a user to a specified group", + "type": "generic", + "identifier": "add_user", + "read_only": false, + "undo": "remove user", + "parameters": { + "group_object_id": { + "description": "Object ID of group", + "data_type": "string", + "required": true, + "primary": true, + "order": 0, + "contains": [ + "group object id" + ] + }, + "user_id": { + "description": "User ID to add to group", + "data_type": "string", + "required": true, + "primary": true, + "order": 1, + "contains": [ + "user id" + ] + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ], + "column_name": "Status", + "column_order": 2 + }, + { + "data_path": "action_result.parameter.group_object_id", + "data_type": "string", + "example_values": [ + "ddb876b3-603a-437b-9814-2d46a2219a1e" + ], + "contains": [ + "group object id" + ], + "column_name": "Group Object ID", + "column_order": 0 + }, + { + "data_path": "action_result.parameter.user_id", + "data_type": "string", + "example_values": [ + "17be76d0-35ed-4881-ab62-d2eb73c2ebe3" + ], + "contains": [ + "user id" + ], + "column_name": "User ID", + "column_order": 1 + }, + { + "data_path": "action_result.data", + "data_type": "string" + }, + { + "data_path": "action_result.summary.status", + "data_type": "string", + "example_values": [ + "Successfully added user to group", + "User already in group" + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Status: Successfully added user to group", + "Status: User already in group" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" + }, + { + "action": "list groups", + "description": "List groups in the organization", + "verbose": "By default, only a limited set of properties are returned, to return an alternative property set use $select query parameter. For more information on using the select_string and expand_string parameters, refer to https://docs.microsoft.com/en-us/graph/query-parameters.", + "type": "investigate", + "identifier": "list_groups", + "read_only": true, + "parameters": { + "filter_string": { + "description": "Filter string to apply to group listing", + "data_type": "string", + "order": 0 + }, + "select_string": { + "description": "Select string to get additional group properties. Separate multiple values with commas", + "data_type": "string", + "order": 1 + }, + "expand_string": { + "description": "Expand string to get a resource or collection referenced by a single relationship", + "data_type": "string", + "order": 2 + }, + "use_advanced_query": { + "description": "Use advanced query capabilities", + "data_type": "boolean", + "default": false, + "order": 3 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] + }, + { + "data_path": "action_result.parameter.expand_string", + "data_type": "string", + "example_values": [ + "members" + ] + }, + { + "data_path": "action_result.parameter.filter_string", + "data_type": "string", + "example_values": [ + "createdDateTime ge '2014-01-01T00:00:00Z'" + ] + }, + { + "data_path": "action_result.parameter.select_string", + "data_type": "string", + "example_values": [ + "displayName" + ] + }, + { + "data_path": "action_result.parameter.use_advanced_query", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.classification", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.createdDateTime", + "data_type": "string", + "example_values": [ + "2021-03-25T18:40:53Z" + ] + }, + { + "data_path": "action_result.data.*.deletedDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.deletionTimestamp", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.description", + "data_type": "string", + "example_values": [ + "This is for testing purpose" + ], + "column_name": "Description", + "column_order": 1 + }, + { + "data_path": "action_result.data.*.dirSyncEnabled", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.displayName", + "data_type": "string", + "example_values": [ + "Test-site" + ], + "column_name": "Display Name", + "column_order": 0 + }, + { + "data_path": "action_result.data.*.expirationDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.id", + "data_type": "string", + "example_values": [ + "2a201c95-101b-42d9-a7af-9a2fdf8193f1" + ], + "contains": [ + "group object id" + ] + }, + { + "data_path": "action_result.data.*.isAssignableToRole", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.lastDirSyncTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.mail", + "data_type": "string", + "example_values": [ + "Test-site@test.com" + ], + "contains": [ + "email" + ] + }, + { + "data_path": "action_result.data.*.mailEnabled", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.mailNickname", + "data_type": "string", + "example_values": [ + "Test-site" + ] + }, + { + "data_path": "action_result.data.*.membershipRule", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.membershipRuleProcessingState", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.objectType", + "data_type": "string", + "example_values": [ + "Group" + ] + }, + { + "data_path": "action_result.data.*.odata.type", + "data_type": "string", + "example_values": [ + "test.DirectoryServices.Group" + ] + }, + { + "data_path": "action_result.data.*.onPremisesDomainName", + "data_type": "string", + "contains": [ + "domain" + ] + }, + { + "data_path": "action_result.data.*.onPremisesLastSyncDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesNetBiosName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesSamAccountName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesSecurityIdentifier", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesSyncEnabled", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.preferredDataLocation", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.preferredLanguage", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.proxyAddresses", + "data_type": "string", + "example_values": [ + "SMTP:test-h@test.com" + ] + }, + { + "data_path": "action_result.data.*.renewedDateTime", + "data_type": "string", + "example_values": [ + "2021-03-25T18:40:53Z" + ] + }, + { + "data_path": "action_result.data.*.securityEnabled", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.securityIdentifier", + "data_type": "string", + "example_values": [ + "S-1-12-1-294681889-1319597617-672379543-28952017" + ] + }, + { + "data_path": "action_result.data.*.theme", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.visibility", + "data_type": "string", + "example_values": [ + "Private" + ] + }, + { + "data_path": "action_result.summary.num_groups", + "data_type": "numeric", + "example_values": [ + 7 + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Num groups: 7" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "custom", + "title": "List Groups", + "view": "msadgraph_view.display_view" + }, + "versions": "EQ(*)" + }, + { + "action": "get group", + "description": "Get information about a group", + "verbose": "By default, only a limited set of properties are returned, to return an alternative property set use $select query parameter. For more information on using the select_string and expand_string parameters, refer to https://docs.microsoft.com/en-us/graph/query-parameters.", + "type": "investigate", + "identifier": "get_group", + "read_only": true, + "parameters": { + "object_id": { + "description": "Object ID of group", + "data_type": "string", + "required": true, + "primary": true, + "order": 0, + "contains": [ + "group object id" + ] + }, + "select_string": { + "description": "Select string to get additional group properties. Separate multiple values with commas", + "data_type": "string", + "order": 1 + }, + "expand_string": { + "description": "Expand string to get a resource or collection referenced by a single relationship", + "data_type": "string", + "order": 2 + }, + "use_advanced_query": { + "description": "Use advanced query capabilities", + "data_type": "boolean", + "default": false, + "order": 3 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] + }, + { + "data_path": "action_result.parameter.expand_string", + "data_type": "string", + "example_values": [ + "members" + ] + }, + { + "data_path": "action_result.parameter.object_id", + "data_type": "string", + "example_values": [ + "ddb876b3-603a-437b-9814-2d46a2219a1e" + ], + "contains": [ + "group object id" + ] + }, + { + "data_path": "action_result.parameter.select_string", + "data_type": "string", + "example_values": [ + "displayName" + ] + }, + { + "data_path": "action_result.parameter.use_advanced_query", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.@odata.context", + "data_type": "string", + "example_values": [ + "https://graph.test.com/v1.0/$metadata#groups(id,displayName)/$entity" + ] + }, + { + "data_path": "action_result.data.*.classification", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.createdDateTime", + "data_type": "string", + "example_values": [ + "2020-08-05T11:59:49Z" + ] + }, + { + "data_path": "action_result.data.*.deletedDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.deletionTimestamp", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.description", + "data_type": "string", + "example_values": [ + "This is the office 365 group" + ] + }, + { + "data_path": "action_result.data.*.dirSyncEnabled", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.displayName", + "data_type": "string", + "example_values": [ + "o365group" + ], + "column_name": "Display Name", + "column_order": 0 + }, + { + "data_path": "action_result.data.*.expirationDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.id", + "data_type": "string", + "example_values": [ + "ddb876b3-603a-437b-9814-2d46a2219a1e" + ], + "contains": [ + "group object id" + ], + "column_name": "Object ID", + "column_order": 1 + }, + { + "data_path": "action_result.data.*.isAssignableToRole", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.lastDirSyncTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.mail", + "data_type": "string", + "example_values": [ + "bc7f9cabe@test.com" + ], + "contains": [ + "email" + ] + }, + { + "data_path": "action_result.data.*.mailEnabled", + "data_type": "boolean", + "example_values": [ + true, + false + ], + "column_name": "Mail Enabled", + "column_order": 3 + }, + { + "data_path": "action_result.data.*.mailNickname", + "data_type": "string", + "example_values": [ + "bc7f9cabe" + ] + }, + { + "data_path": "action_result.data.*.membershipRule", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.membershipRuleProcessingState", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.objectType", + "data_type": "string", + "example_values": [ + "Group" + ] + }, + { + "data_path": "action_result.data.*.odata.metadata", + "data_type": "string", + "example_values": [ + "https://graph.windows.net/1t309est-db6c-4tes-t1d2-12bf3456d78d/$metadata#directoryObjects/@Element" + ] + }, + { + "data_path": "action_result.data.*.odata.type", + "data_type": "string", + "example_values": [ + "test.DirectoryServices.Group" + ] + }, + { + "data_path": "action_result.data.*.onPremisesDomainName", + "data_type": "string", + "contains": [ + "domain" + ] + }, + { + "data_path": "action_result.data.*.onPremisesLastSyncDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesNetBiosName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesSamAccountName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesSecurityIdentifier", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesSyncEnabled", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.preferredDataLocation", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.preferredLanguage", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.proxyAddresses", + "data_type": "string", + "example_values": [ + "SMTP:bc7f9cabe@test.com" + ] + }, + { + "data_path": "action_result.data.*.renewedDateTime", + "data_type": "string", + "example_values": [ + "2020-08-05T11:59:49Z" + ] + }, + { + "data_path": "action_result.data.*.securityEnabled", + "data_type": "boolean", + "example_values": [ + true, + false + ], + "column_name": "Security Enabled", + "column_order": 2 + }, + { + "data_path": "action_result.data.*.securityIdentifier", + "data_type": "string", + "example_values": [ + "S-1-12-1-909260723-1083662375-1952945031-2402852259" + ] + }, + { + "data_path": "action_result.data.*.theme", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.visibility", + "data_type": "string" + }, + { + "data_path": "action_result.summary.display_name", + "data_type": "string", + "example_values": [ + "o365group" + ] + }, + { + "data_path": "action_result.summary.status", + "data_type": "string", + "example_values": [ + "Successfully retrieved group 104d4576-1544-48b5-bb7e-9f8f871aa824" + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Display name: o365group" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "custom", + "title": "List Groups", + "view": "msadgraph_view.display_view" + }, + "versions": "EQ(*)" + }, + { + "action": "list group members", + "description": "List the members in a group", + "verbose": "By default, only a limited set of properties are returned, to return an alternative property set use $select query parameter. For more information on using the select_string and expand_string parameters, refer to https://docs.microsoft.com/en-us/graph/query-parameters.", + "type": "investigate", + "identifier": "list_group_members", + "read_only": true, + "parameters": { + "group_object_id": { + "description": "Object ID of group", + "data_type": "string", + "required": true, + "primary": true, + "order": 0, + "contains": [ + "group object id" + ] + }, + "select_string": { + "description": "Select string to get additional properties. Separate multiple values with commas", + "data_type": "string", + "order": 1 + }, + "expand_string": { + "description": "Expand string to get a resource or collection referenced by a single relationship", + "data_type": "string", + "order": 2 + }, + "use_advanced_query": { + "description": "Use advanced query capabilities", + "data_type": "boolean", + "default": false, + "order": 3 + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] + }, + { + "data_path": "action_result.parameter.expand_string", + "data_type": "string", + "example_values": [ + "manager" + ] + }, + { + "data_path": "action_result.parameter.group_object_id", + "data_type": "string", + "example_values": [ + "ebcd3130-55a1-4cbf-81b2-86408ff21203" + ], + "contains": [ + "group object id" + ] + }, + { + "data_path": "action_result.parameter.select_string", + "data_type": "string", + "example_values": [ + "displayName" + ] + }, + { + "data_path": "action_result.parameter.use_advanced_query", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.@odata.type", + "data_type": "string", + "example_values": [ + "#test.graph.user" + ] + }, + { + "data_path": "action_result.data.*.accountEnabled", + "data_type": "boolean", + "example_values": [ + true + ] + }, + { + "data_path": "action_result.data.*.ageGroup", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.assignedLicenses.*.skuId", + "data_type": "string", + "example_values": [ + "189a915c-fe4f-4ffa-bde4-85b9628d07a0" + ] + }, + { + "data_path": "action_result.data.*.assignedPlans.*.assignedDateTime", + "data_type": "string", + "example_values": [ + "2022-11-03T15:12:28Z" + ] + }, + { + "data_path": "action_result.data.*.assignedPlans.*.capabilityStatus", + "data_type": "string", + "example_values": [ + "Deleted" + ] + }, + { + "data_path": "action_result.data.*.assignedPlans.*.service", + "data_type": "string", + "example_values": [ + "AADPremiumService" + ] + }, + { + "data_path": "action_result.data.*.assignedPlans.*.servicePlanId", + "data_type": "string", + "example_values": [ + "eec0eb4f-6444-4f95-aba0-50c24d67f998" + ] + }, + { + "data_path": "action_result.data.*.city", + "data_type": "string", + "example_values": [ + "Palo Alto" + ] + }, + { + "data_path": "action_result.data.*.companyName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.consentProvidedForMinor", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.country", + "data_type": "string", + "example_values": [ + "US" + ] + }, + { + "data_path": "action_result.data.*.createdDateTime", + "data_type": "string", + "example_values": [ + "2016-06-09T18:33:27Z" + ] + }, + { + "data_path": "action_result.data.*.creationType", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.deletedDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.department", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.displayName", + "data_type": "string", + "example_values": [ + "Firstname Lastname" + ], + "column_name": "Display Name", + "column_order": 0 + }, + { + "data_path": "action_result.data.*.employeeHireDate", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.employeeId", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.employeeOrgData", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.employeeType", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.externalUserState", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.externalUserStateChangeDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.faxNumber", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.givenName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.id", + "data_type": "string", + "example_values": [ + "17be76d0-35ed-4881-ab62-d2eb73c2ebe3" + ], + "contains": [ + "user id" + ] + }, + { + "data_path": "action_result.data.*.identities.*.issuer", + "data_type": "string", + "example_values": [ + "test.com" + ] + }, + { + "data_path": "action_result.data.*.identities.*.issuerAssignedId", + "data_type": "string", + "example_values": [ + "test@user.test.com" + ] + }, + { + "data_path": "action_result.data.*.identities.*.signInType", + "data_type": "string", + "example_values": [ + "userPrincipalName" + ] + }, + { + "data_path": "action_result.data.*.isResourceAccount", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.jobTitle", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.legalAgeGroupClassification", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.mail", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.mailNickname", + "data_type": "string", + "example_values": [ + "User" + ] + }, + { + "data_path": "action_result.data.*.mobilePhone", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.officeLocation", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesDistinguishedName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesDomainName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesExtensionAttributes.extensionAttribute1", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesExtensionAttributes.extensionAttribute10", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesExtensionAttributes.extensionAttribute11", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesExtensionAttributes.extensionAttribute12", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesExtensionAttributes.extensionAttribute13", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesExtensionAttributes.extensionAttribute14", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesExtensionAttributes.extensionAttribute15", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesExtensionAttributes.extensionAttribute2", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesExtensionAttributes.extensionAttribute3", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesExtensionAttributes.extensionAttribute4", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesExtensionAttributes.extensionAttribute5", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesExtensionAttributes.extensionAttribute6", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesExtensionAttributes.extensionAttribute7", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesExtensionAttributes.extensionAttribute8", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesExtensionAttributes.extensionAttribute9", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesImmutableId", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesLastSyncDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesSamAccountName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesSecurityIdentifier", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesSyncEnabled", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.onPremisesUserPrincipalName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.passwordPolicies", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.passwordProfile", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.postalCode", + "data_type": "string", + "example_values": [ + "94303" + ] + }, + { + "data_path": "action_result.data.*.preferredDataLocation", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.preferredLanguage", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.provisionedPlans.*.capabilityStatus", + "data_type": "string", + "example_values": [ + "Enabled" + ] + }, + { + "data_path": "action_result.data.*.provisionedPlans.*.provisioningStatus", + "data_type": "string", + "example_values": [ + "Success" + ] + }, + { + "data_path": "action_result.data.*.provisionedPlans.*.service", + "data_type": "string", + "example_values": [ + "testCommunicationsOnline" + ] + }, + { + "data_path": "action_result.data.*.refreshTokensValidFromDateTime", + "data_type": "string", + "example_values": [ + "2022-08-08T13:00:58Z" + ] + }, + { + "data_path": "action_result.data.*.showInAddressList", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.signInSessionsValidFromDateTime", + "data_type": "string", + "example_values": [ + "2022-08-08T13:00:58Z" + ] + }, + { + "data_path": "action_result.data.*.state", + "data_type": "string", + "example_values": [ + "CA" + ] + }, + { + "data_path": "action_result.data.*.streetAddress", + "data_type": "string", + "example_values": [ + "2479 E. Bayshore Rd." + ] + }, + { + "data_path": "action_result.data.*.surname", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.usageLocation", + "data_type": "string", + "example_values": [ + "US" + ] + }, + { + "data_path": "action_result.data.*.userPrincipalName", + "data_type": "string", + "example_values": [ + "ews_retest@test.com" + ] + }, + { + "data_path": "action_result.data.*.userType", + "data_type": "string", + "example_values": [ + "Member" + ] + }, + { + "data_path": "action_result.summary.num_members", + "data_type": "numeric", + "example_values": [ + 3 + ], + "contains": [ + "user id" + ] + }, + { + "data_path": "action_result.summary.num_users", + "data_type": "numeric", + "example_values": [ + 3 + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Num members: 3" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "custom", + "title": "list group members", + "view": "msadgraph_view.display_view" + }, + "versions": "EQ(*)" + }, + { + "action": "validate group", + "description": "Returns true if a user is in a group; otherwise, false", + "type": "investigate", + "identifier": "validate_group", + "read_only": true, + "parameters": { + "group_object_id": { + "description": "Object ID of group", + "data_type": "string", + "required": true, + "primary": true, + "order": 0, + "contains": [ + "group object id" + ] + }, + "user_id": { + "description": "User ID to validate", + "data_type": "string", + "required": true, + "primary": true, + "order": 1, + "contains": [ + "user id" + ] + } + }, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ], + "column_name": "Status", + "column_order": 2 + }, + { + "data_path": "action_result.parameter.group_object_id", + "data_type": "string", + "example_values": [ + "ebcd3130-55a1-4cbf-81b2-86408ff21203" + ], + "contains": [ + "group object id" + ], + "column_name": "Group Object ID", + "column_order": 0 + }, + { + "data_path": "action_result.parameter.user_id", + "data_type": "string", + "example_values": [ + "user@test.com" + ], + "contains": [ + "user id" + ], + "column_name": "User ID", + "column_order": 1 + }, + { + "data_path": "action_result.data.*.@odata.context", + "data_type": "string", + "example_values": [ + "https://graph.test.com/v1.0/$metadata#directoryObjects" + ] + }, + { + "data_path": "action_result.data.*.user_in_group", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.value.*.@odata.type", + "data_type": "string", + "example_values": [ + "#test.graph.group" + ] + }, + { + "data_path": "action_result.data.*.value.*.classification", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.value.*.createdDateTime", + "data_type": "string", + "example_values": [ + "2022-02-25T12:05:22Z" + ] + }, + { + "data_path": "action_result.data.*.value.*.deletedDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.value.*.description", + "data_type": "string", + "example_values": [ + "Test group for MSGraph" + ] + }, + { + "data_path": "action_result.data.*.value.*.displayName", + "data_type": "string", + "example_values": [ + "Test group for MSGraph" + ] + }, + { + "data_path": "action_result.data.*.value.*.expirationDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.value.*.id", + "data_type": "string", + "example_values": [ + "49233413-24c6-4516-a9e1-4d5f87fe34fd" + ], + "contains": [ + "user id" + ] + }, + { + "data_path": "action_result.data.*.value.*.isAssignableToRole", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.value.*.mail", + "data_type": "string", + "example_values": [ + "test@user.test.com" + ] + }, + { + "data_path": "action_result.data.*.value.*.mailEnabled", + "data_type": "boolean", + "example_values": [ + true + ] + }, + { + "data_path": "action_result.data.*.value.*.mailNickname", + "data_type": "string", + "example_values": [ + "TestgroupforMSGraph" + ] + }, + { + "data_path": "action_result.data.*.value.*.membershipRule", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.value.*.membershipRuleProcessingState", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.value.*.onPremisesDomainName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.value.*.onPremisesLastSyncDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.value.*.onPremisesNetBiosName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.value.*.onPremisesSamAccountName", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.value.*.onPremisesSecurityIdentifier", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.value.*.onPremisesSyncEnabled", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.value.*.preferredDataLocation", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.value.*.preferredLanguage", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.value.*.renewedDateTime", + "data_type": "string", + "example_values": [ + "2022-02-25T12:05:22Z" + ] + }, + { + "data_path": "action_result.data.*.value.*.securityEnabled", + "data_type": "boolean", + "example_values": [ + true + ] + }, + { + "data_path": "action_result.data.*.value.*.securityIdentifier", + "data_type": "string", + "example_values": [ + "S-1-12-1-1227043859-1159079110-1598939561-4248108679" + ] + }, + { + "data_path": "action_result.data.*.value.*.theme", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.value.*.visibility", + "data_type": "string", + "example_values": [ + "Private" + ] + }, + { + "data_path": "action_result.summary.message", + "data_type": "string", + "example_values": [ + "User is member of group" + ] + }, + { + "data_path": "action_result.summary.user_in_group", + "data_type": "string" + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "User in group: True" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" + }, + { + "action": "list directory roles", + "description": "List the directory roles that are activated in the tenant", + "verbose": "

Pagination is not implemented for this action as this endpoint does not support pagination. Here is the Documentation for the same.

", + "type": "investigate", + "identifier": "list_directory_roles", + "read_only": true, + "parameters": {}, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ] + }, + { + "data_path": "action_result.data.*.deletedDateTime", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.deletionTimestamp", + "data_type": "string" + }, + { + "data_path": "action_result.data.*.description", + "data_type": "string", + "example_values": [ + "Can read basic directory information. For granting access to applications, not intended for users." + ] + }, + { + "data_path": "action_result.data.*.displayName", + "data_type": "string", + "example_values": [ + "Directory Readers" + ], + "column_name": "Display Name", + "column_order": 0 + }, + { + "data_path": "action_result.data.*.id", + "data_type": "string", + "example_values": [ + "02b238cb-0d15-454b-aae6-0e94993a3207" + ], + "contains": [ + "directory object id" + ], + "column_name": "Object ID", + "column_order": 1 + }, + { + "data_path": "action_result.data.*.isSystem", + "data_type": "boolean", + "example_values": [ + true, + false + ] + }, + { + "data_path": "action_result.data.*.objectType", + "data_type": "string", + "example_values": [ + "Role" + ] + }, + { + "data_path": "action_result.data.*.odata.type", + "data_type": "string", + "example_values": [ + "test.DirectoryServices.DirectoryRole" + ] + }, + { + "data_path": "action_result.data.*.roleTemplateId", + "data_type": "string", + "example_values": [ + "88d8e3e3-8f55-4a1e-953a-9b9898b8876b" + ], + "contains": [ + "role template id" + ] + }, + { + "data_path": "action_result.summary.num_directory_roles", + "data_type": "numeric", + "example_values": [ + 9 + ] + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Num directory roles: 9" + ] + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" + }, + { + "action": "generate token", + "identifier": "generate_token", + "description": "Generate a token", + "type": "generic", + "read_only": false, + "parameters": {}, + "output": [ + { + "data_path": "action_result.status", + "data_type": "string", + "example_values": [ + "success", + "failed" + ], + "column_name": "Status", + "column_order": 0 + }, + { + "data_path": "action_result.data", + "data_type": "string" + }, + { + "data_path": "action_result.summary", + "data_type": "string" + }, + { + "data_path": "action_result.message", + "data_type": "string", + "example_values": [ + "Token generated" + ], + "column_name": "Message", + "column_order": 1 + }, + { + "data_path": "summary.total_objects", + "data_type": "numeric", + "example_values": [ + 1 + ] + }, + { + "data_path": "summary.total_objects_successful", + "data_type": "numeric", + "example_values": [ + 1 + ] + } + ], + "render": { + "type": "table" + }, + "versions": "EQ(*)" + } + ], + "pip_dependencies": { + "wheel": [ + { + "module": "beautifulsoup4", + "input_file": "wheels/py3/beautifulsoup4-4.9.1-py3-none-any.whl" + }, + { + "module": "soupsieve", + "input_file": "wheels/py3/soupsieve-2.3.2.post1-py3-none-any.whl" + } + ] + }, + "pip39_dependencies": { + "wheel": [ + { + "module": "beautifulsoup4", + "input_file": "wheels/py3/beautifulsoup4-4.9.1-py3-none-any.whl" + }, + { + "module": "soupsieve", + "input_file": "wheels/py3/soupsieve-2.4.1-py3-none-any.whl" + } + ] + } +} diff --git a/deployment-apps/msadgraph/msadgraph_connector.py b/deployment-apps/msadgraph/msadgraph_connector.py new file mode 100644 index 00000000..5dea0e42 --- /dev/null +++ b/deployment-apps/msadgraph/msadgraph_connector.py @@ -0,0 +1,1541 @@ +# File: msadgraph_connector.py +# +# Copyright (c) 2022-2023 Splunk Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed under +# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +# either express or implied. See the License for the specific language governing permissions +# and limitations under the License. +# +# +# Phantom App imports +import grp +import json +import os +import pathlib +import pwd +import sys +import time +import urllib.parse as urlparse + +import encryption_helper +import phantom.app as phantom +import requests +from bs4 import BeautifulSoup +from django.http import HttpResponse +from phantom.action_result import ActionResult +from phantom.base_connector import BaseConnector + +from msadgraph_consts import * + +MAX_END_OFFSET_VAL = 2147483646 + + +def _handle_login_redirect(request, key): + """ This function is used to redirect login request to microsoft login page. + + :param request: Data given to REST endpoint + :param key: Key to search in state file + :return: response authorization_url/admin_consent_url + """ + + asset_id = request.GET.get('asset_id') + if not asset_id: + return HttpResponse('ERROR: Asset ID not found in URL', content_type="text/plain", status=MS_AZURE_BAD_REQUEST_CODE) + state = _load_app_state(asset_id) + if not state: + return HttpResponse('ERROR: Invalid asset_id', content_type="text/plain", status=MS_AZURE_BAD_REQUEST_CODE) + url = state.get(key) + if not url: + return HttpResponse(f'App state is invalid, {key} not found.', content_type="text/plain", status=MS_AZURE_BAD_REQUEST_CODE) + response = HttpResponse(status=302) + response['Location'] = url + return response + + +def _is_valid_asset_id(asset_id): + """ This function validates an asset id. + Must be an alphanumeric string of less than 128 characters. + + :param asset_id: asset_id + :return: is_valid: Boolean True if valid, False if not. + """ + if not isinstance(asset_id, str): + return False + if not asset_id.isalnum(): + return False + if len(asset_id) > 128: + return False + return True + + +def _get_file_path(asset_id, is_state_file=True): + """ This function gets the path of the auth status file of an asset id. + + :param asset_id: asset_id + :param app_connector: Object of app_connector class + :param is_state_file: boolean parameter for state file + :return: file_path: Path object of the file + """ + current_file_path = pathlib.Path(__file__).resolve() + if is_state_file: + input_file = f'{asset_id}_state.json' + else: + input_file = f'{asset_id}_oauth_task.out' + output_file_path = current_file_path.with_name(input_file) + return output_file_path + + +def _decrypt_state(state, salt): + """ + Decrypts the state. + :param state: state dictionary + :param salt: salt used for decryption + :return: decrypted state + """ + + if not state.get("is_encrypted"): + return state + + access_token = state.get("token", {}).get("access_token") + if access_token: + state["token"]["access_token"] = encryption_helper.decrypt(access_token, salt) + + refresh_token = state.get("token", {}).get("refresh_token") + if refresh_token: + state["token"]["refresh_token"] = encryption_helper.decrypt(refresh_token, salt) + + code = state.get("code") + if code: + state["code"] = encryption_helper.decrypt(code, salt) + + return state + + +def _encrypt_state(state, salt): + """ + Encrypts the state. + :param state: state dictionary + :param salt: salt used for encryption + :return: encrypted state + """ + + access_token = state.get("token", {}).get("access_token") + if access_token: + state["token"]["access_token"] = encryption_helper.encrypt(access_token, salt) + + refresh_token = state.get("token", {}).get("refresh_token") + if refresh_token: + state["token"]["refresh_token"] = encryption_helper.encrypt(refresh_token, salt) + + code = state.get("code") + if code: + state["code"] = encryption_helper.encrypt(code, salt) + + state["is_encrypted"] = True + + return state + + +def _load_app_state(asset_id, app_connector=None): + """ This function is used to load the current state file. + + :param asset_id: asset_id + :param app_connector: Object of app_connector class + :return: state: Current state file as a dictionary + """ + + asset_id = str(asset_id) + if not _is_valid_asset_id(asset_id): + if app_connector: + app_connector.debug_print('In _load_app_state: Invalid asset_id') + return {} + + state_file_path = _get_file_path(asset_id) + + state = {} + try: + with open(state_file_path, 'r') as state_file: + state = json.load(state_file) + except Exception as e: + if app_connector: + app_connector.error_print(f'In _load_app_state: Exception: {str(e)}') + + if app_connector: + app_connector.debug_print('Loaded state: ', state) + + try: + state = _decrypt_state(state, asset_id) + except Exception as e: + if app_connector: + app_connector.error_print("{}: {}".format(MS_AZURE_DECRYPTION_ERROR, str(e))) + state = {} + + return state + + +def _save_app_state(state, asset_id, app_connector): + """ This function is used to save current state in file. + + :param state: Dictionary which contains data to write in state file + :param asset_id: asset_id + :param app_connector: Object of app_connector class + :return: status: phantom.APP_SUCCESS + """ + asset_id = str(asset_id) + if not _is_valid_asset_id(asset_id): + if app_connector: + app_connector.debug_print('In _save_app_state: Invalid asset_id') + return {} + + state_file_path = _get_file_path(asset_id) + + try: + state = _encrypt_state(state, asset_id) + except Exception as e: + if app_connector: + app_connector.error_print("{}: {}".format(MS_AZURE_ENCRYPTION_ERROR, str(e))) + return phantom.APP_ERROR + + if app_connector: + app_connector.debug_print('Saving state: ', state) + + try: + with open(state_file_path, 'w+') as state_file: + json.dump(state, state_file) + except Exception as e: + if app_connector: + app_connector.error_print(f'Unable to save state file: {str(e)}') + + return phantom.APP_SUCCESS + + +def _handle_login_response(request): + """ This function is used to get the login response of authorization request from microsoft login page. + + :param request: Data given to REST endpoint + :return: HttpResponse. The response displayed on authorization URL page + """ + + asset_id = request.GET.get('state') + if not asset_id: + return HttpResponse(f'ERROR: Asset ID not found in URL\n{json.dumps(request.GET)}', + content_type="text/plain", status=MS_AZURE_BAD_REQUEST_CODE) + + # Check for error in URL + error = request.GET.get('error') + error_description = request.GET.get('error_description') + + # If there is an error in response + if error: + message = f'Error: {error}' + if error_description: + message = f'{message} Details: {error_description}' + return HttpResponse(f'Server returned {message}', content_type="text/plain", status=MS_AZURE_BAD_REQUEST_CODE) + + code = request.GET.get('code') + admin_consent = request.GET.get('admin_consent') + + # If none of the code or admin_consent is available + if not (code or admin_consent): + return HttpResponse(f'Error while authenticating\n{json.dumps(request.GET)}', + content_type="text/plain", status=MS_AZURE_BAD_REQUEST_CODE) + + state = _load_app_state(asset_id) + + # If value of admin_consent is available + if admin_consent: + if admin_consent == 'True': + admin_consent = True + else: + admin_consent = False + + state['admin_consent'] = admin_consent + _save_app_state(state, asset_id, None) + + # If admin_consent is True + if admin_consent: + return HttpResponse('Admin Consent received. Please close this window.', content_type="text/plain") + return HttpResponse('Admin Consent declined. Please close this window and try again later.', + content_type="text/plain", status=MS_AZURE_BAD_REQUEST_CODE) + + # If value of admin_consent is not available, value of code is available + state['code'] = code + _save_app_state(state, asset_id, None) + + return HttpResponse('Code received. Please close this window, the action will continue to get new token.', content_type="text/plain") + + +def _handle_rest_request(request, path_parts): + """ Handle requests for authorization. + + :param request: Data given to REST endpoint + :param path_parts: parts of the URL passed + :return: dictionary containing response parameters + """ + + if len(path_parts) < 2: + return HttpResponse('error: True, message: Invalid REST endpoint request', content_type="text/plain", status=MS_AZURE_BAD_REQUEST_CODE) + + call_type = path_parts[1] + + # To handle authorize request in test connectivity action + if call_type == 'start_oauth': + return _handle_login_redirect(request, 'admin_consent_url') + + # To handle response from microsoft login page + if call_type == 'result': + return_val = _handle_login_response(request) + asset_id = request.GET.get('state') + if asset_id: + if not _is_valid_asset_id(asset_id): + return HttpResponse("Error: Invalid asset_id", content_type="text/plain", status=MS_AZURE_BAD_REQUEST_CODE) + auth_status_file_path = _get_file_path(asset_id, is_state_file=False) + auth_status_file_path.touch(mode=664, exist_ok=True) + try: + uid = pwd.getpwnam('apache').pw_uid + gid = grp.getgrnam('phantom').gr_gid + os.chown(auth_status_file_path, uid, gid) # nosemgrep file traversal risk is handled by blocking non-alphanum strings + except Exception: + pass + + return return_val + return HttpResponse('error: Invalid endpoint', content_type="text/plain", status=MS_AZURE_NOT_FOUND_CODE) + + +def _get_dir_name_from_app_name(app_name): + """ Get name of the directory for the app. + + :param app_name: Name of the application for which directory name is required + :return: app_name: Name of the directory for the application + """ + + app_name = ''.join([x for x in app_name if x.isalnum()]) + app_name = app_name.lower() + if not app_name: + app_name = 'app_for_phantom' + return app_name + + +class RetVal(tuple): + + def __new__(cls, val1, val2): + + return tuple.__new__(RetVal, (val1, val2)) + + +class MSADGraphConnector(BaseConnector): + + def __init__(self): + + # Call the BaseConnectors init first + super(MSADGraphConnector, self).__init__() + + self._state = None + self._tenant = None + self._client_id = None + self._client_secret = None + self._access_token = None + self._refresh_token = None + self._base_url = None + self._admin_access_required = None + self._admin_access_granted = None + + def load_state(self): + """ + Load the contents of the state file to the state dictionary and decrypt it. + :return: loaded state + """ + state = super().load_state() + if not isinstance(state, dict): + self.debug_print("Reseting the state file with the default format") + state = { + "app_version": self.get_app_json().get('app_version') + } + return state + try: + state = _decrypt_state(state, self.get_asset_id()) + except Exception as e: + error_message = self._get_error_message_from_exception(e) + self.error_print("{}: {}".format(MS_AZURE_DECRYPTION_ERROR, error_message)) + self.debug_print("Reseting the state file with the default format") + state = { + "app_version": self.get_app_json().get('app_version') + } + + return state + + def save_state(self, state): + """ + Encrypt and save the current state dictionary to the the state file. + :param state: state dictionary + :return: status + """ + try: + state = _encrypt_state(state, self.get_asset_id()) + except Exception as e: + error_message = self._get_error_message_from_exception(e) + self.error_print("{}: {}".format(MS_AZURE_ENCRYPTION_ERROR, error_message)) + + return super().save_state(state) + + def _dump_error_log(self, error, message="Exception occurred."): + self.error_print(message, dump_object=error) + + def _get_error_message_from_exception(self, e): + """ + Get appropriate error message from the exception. + :param e: Exception object + :return: error message + """ + error_code = None + error_message = MS_AZURE_ERROR_MESSAGE_UNKNOWN + + self._dump_error_log(e) + + try: + if hasattr(e, "args"): + if len(e.args) > 1: + error_code = e.args[0] + error_message = e.args[1] + elif len(e.args) == 1: + error_message = e.args[0] + except Exception: + self.error_print("Exception occurred while getting error code and message") + + if not error_code: + error_text = "Error Message: {}".format(error_message) + else: + error_text = "Error Code: {}. Error Message: {}".format(error_code, error_message) + + return error_text + + def _process_empty_response(self, response, action_result): + """ This function is used to process empty response. + + :param response: response data + :param action_result: object of Action Result + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS(along with appropriate message) + """ + + if response.status_code == 200 or response.status_code == 202: + return RetVal(phantom.APP_SUCCESS, {}) + + return RetVal(action_result.set_status(phantom.APP_ERROR, "Empty response and no information in the header"), + None) + + def _process_html_response(self, response, action_result): + """ This function is used to process html response. + + :param response: response data + :param action_result: object of Action Result + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS(along with appropriate message) + """ + + # An html response, treat it like an error + status_code = response.status_code + + try: + soup = BeautifulSoup(response.text, "html.parser") + # Remove the script, style, footer and navigation part from the HTML message + for element in soup(["script", "style", "footer", "nav"]): + element.extract() + error_text = soup.text + split_lines = error_text.split('\n') + split_lines = [x.strip() for x in split_lines if x.strip()] + error_text = '\n'.join(split_lines) + except Exception: + error_text = "Cannot parse error details" + + message = MS_AZURE_RESPONSE_ERROR_MESSAGE.format(status_code=status_code, error_text=error_text) + + message = message.replace('{', '{{').replace('}', '}}') + + if status_code == MS_AZURE_BAD_REQUEST_CODE: + message = MS_AZURE_RESPONSE_ERROR_MESSAGE.format(status_code=status_code, error_text=MS_AZURE_HTML_ERROR) + + return RetVal(action_result.set_status(phantom.APP_ERROR, message), None) + + def _process_json_response(self, response, action_result): + """ This function is used to process json response. + + :param response: response data + :param action_result: object of Action Result + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS(along with appropriate message) + """ + + # Try a json parse + try: + resp_json = response.json() + except Exception as e: + error_message = self._get_error_message_from_exception(e) + return RetVal(action_result.set_status(phantom.APP_ERROR, "Unable to parse JSON response. Error: {0}". + format(error_message)), None) + + # Please specify the status codes here + if 200 <= response.status_code < 399: + return RetVal(phantom.APP_SUCCESS, resp_json) + + error_message = response.text.replace('{', '{{').replace('}', '}}') + message = MS_AZURE_RESPONSE_ERROR_MESSAGE.format(status_code=response.status_code, error_text=error_message) + + # Show only error message if available + if isinstance(resp_json.get('error', {}), dict): + if resp_json.get('error', {}).get('message'): + error_message = resp_json['error']['message'] + message = MS_AZURE_RESPONSE_ERROR_MESSAGE.format(status_code=response.status_code, error_text=error_message) + else: + error_message = resp_json['error'] + message = MS_AZURE_RESPONSE_ERROR_MESSAGE.format(status_code=response.status_code, error_text=error_message) + + return RetVal(action_result.set_status(phantom.APP_ERROR, message), None) + + def _process_response(self, response, action_result): + """ This function is used to process html response. + + :param response: response data + :param action_result: object of Action Result + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS(along with appropriate message) + """ + + # store the r_text in debug data, it will get dumped in the logs if the action fails + if hasattr(action_result, 'add_debug_data'): + action_result.add_debug_data({'r_status_code': response.status_code}) + action_result.add_debug_data({'r_text': response.text}) + action_result.add_debug_data({'r_headers': response.headers}) + + # Process each 'Content-Type' of response separately + + # Process a json response + if 'json' in response.headers.get('Content-Type', ''): + return self._process_json_response(response, action_result) + + if 'text/javascript' in response.headers.get('Content-Type', ''): + return self._process_json_response(response, action_result) + + # Process an HTML response, Do this no matter what the API talks. + # There is a high chance of a PROXY in between SOAR and the rest of + # world, in case of errors, PROXY's return HTML, this function parses + # the error and adds it to the action_result. + if 'html' in response.headers.get('Content-Type', ''): + return self._process_html_response(response, action_result) + + # Reset_password returns empty body + if not response.text and 200 <= response.status_code < 399: + return RetVal(phantom.APP_SUCCESS, {}) + + # it's not content-type that is to be parsed, handle an empty response + if not response.text: + return self._process_empty_response(response, action_result) + + # everything else is actually an error at this point + response_content = response.text.replace('{', '{{').replace('}', '}}') + message = MS_AZURE_PROCESS_RESPONSE_ERROR_MESSAGE.format(status_code=response.status_code, content=response_content) + + return RetVal(action_result.set_status(phantom.APP_ERROR, message), None) + + def _get_asset_name(self, action_result): + """ Get name of the asset using SOAR URL. + + :param action_result: object of ActionResult class + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS(along with appropriate message), asset name + """ + + url = urlparse.urljoin(self.get_phantom_base_url(), f'rest/asset/{self._asset_id}') + ret_val, resp_json = self._make_rest_call(action_result=action_result, endpoint=url, verify=False) # nosemgrep + + if phantom.is_fail(ret_val): + return ret_val, None + + asset_name = resp_json.get('name') + if not asset_name: + return action_result.set_status(phantom.APP_ERROR, f'Asset Name for id: {self._asset_id} not found.'), None + return phantom.APP_SUCCESS, asset_name + + def _get_external_phantom_base_url(self, action_result): + """ Get base url of SOAR. + + :param action_result: object of ActionResult class + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS(along with appropriate message), + base url of SOAR + """ + + url = urlparse.urljoin(self.get_phantom_base_url(), 'rest/system_info') + ret_val, resp_json = self._make_rest_call(action_result=action_result, endpoint=url, verify=False) # nosemgrep + if phantom.is_fail(ret_val): + return ret_val, None + + phantom_base_url = resp_json.get('base_url').rstrip("/") + if not phantom_base_url: + return action_result.set_status(phantom.APP_ERROR, MS_AZURE_BASE_URL_NOT_FOUND_MESSAGE), None + return phantom.APP_SUCCESS, phantom_base_url + + def _get_app_rest_url(self, action_result): + """ Get URL for making rest calls. + + :param action_result: object of ActionResult class + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS(along with appropriate message), + URL to make rest calls + """ + + ret_val, phantom_base_url = self._get_external_phantom_base_url(action_result) + if phantom.is_fail(ret_val): + return action_result.get_status(), None + + ret_val, asset_name = self._get_asset_name(action_result) + if phantom.is_fail(ret_val): + return action_result.get_status(), None + + self.save_progress(f'Using SOAR base URL: {phantom_base_url}') + app_json = self.get_app_json() + app_id = app_json['appid'] + app_name = app_json['name'] + + app_dir_name = _get_dir_name_from_app_name(app_name) + url_to_app_rest = f"{phantom_base_url}/rest/handler/{app_dir_name}_{app_id}/{asset_name}" + return phantom.APP_SUCCESS, url_to_app_rest + + def _make_rest_call(self, endpoint, action_result, verify=True, headers=None, params=None, data=None, json=None, method="get"): + """ Function that makes the REST call to the app. + + :param endpoint: REST endpoint that needs to appended to the service address + :param action_result: object of ActionResult class + :param headers: request headers + :param params: request parameters + :param data: request body + :param json: JSON object + :param method: GET/POST/PUT/DELETE/PATCH (Default will be GET) + :param verify: verify server certificate (Default True) + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS(along with appropriate message), + response obtained by making an API call + """ + + resp_json = None + + try: + request_func = getattr(requests, method) + except AttributeError: + return RetVal(action_result.set_status(phantom.APP_ERROR, f"Invalid method: {method}"), resp_json) + + try: + resp_json = request_func(endpoint, json=json, data=data, headers=headers, verify=verify, params=params, timeout=DEFAULT_TIMEOUT) + except Exception as e: + error_message = f"Error connecting to server. Details: {self._get_error_message_from_exception(e)}" + return RetVal(action_result.set_status(phantom.APP_ERROR, error_message), resp_json) + + return self._process_response(resp_json, action_result) + + def _make_rest_call_helper(self, action_result, endpoint, verify=True, headers=None, params=None, data=None, json=None, method="get"): + """ Function that helps setting REST call to the app. + + :param endpoint: REST endpoint that needs to appended to the service address + :param action_result: object of ActionResult class + :param headers: request headers + :param params: request parameters + :param data: request body + :param json: JSON object + :param method: GET/POST/PUT/DELETE/PATCH (Default will be GET) + :param verify: verify server certificate (Default True) + :return: status phantom.APP_ERROR/phantom.APP_SUCCESS(along with appropriate message), + response obtained by making an API call + """ + + url = f"{self._base_url}/{self._tenant}{endpoint}" + if headers is None: + headers = {} + + token = self._state.get(MS_AZURE_TOKEN_STRING, {}) + if not token.get(MS_AZURE_ACCESS_TOKEN_STRING): + ret_val = self._get_token(action_result) + + if phantom.is_fail(ret_val): + return RetVal(action_result.get_status(), None) + headers.update({ + 'Authorization': f'Bearer {self._access_token}', + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }) + ret_val, resp_json = self._make_rest_call(url, action_result, verify, headers, params, data, json, method) + + # If token is expired, generate a new token + message = action_result.get_message() + self.debug_print(f"message: {message}") + if message and ('token' in message and 'expired' in message): + self.save_progress("Token is invalid/expired. Hence, generating a new token.") + ret_val = self._get_token(action_result) + if phantom.is_fail(ret_val): + return RetVal(ret_val, None) + + headers.update({'Authorization': f'Bearer {self._access_token}'}) + + ret_val, resp_json = self._make_rest_call(url, action_result, verify, headers, params, data, json, method) + + if phantom.is_fail(ret_val): + return RetVal(ret_val, resp_json) + + return RetVal(phantom.APP_SUCCESS, resp_json) + + def _handle_generate_token(self, param): + + self.save_progress(f"In action handler for: {self.get_action_identifier()}") + action_result = self.add_action_result(ActionResult(dict(param))) + ret_val = self._get_token(action_result) + if phantom.is_fail(ret_val): + return action_result.get_status() + + self._state['admin_consent'] = True + + self.save_progress(f"Completed action handler for: {self.get_action_identifier()}") + return action_result.set_status(phantom.APP_SUCCESS, "Token generated") + + def _handle_test_connectivity(self, param): + """ Function that handles the test connectivity action, it is much simpler than other action handlers.""" + + # Progress + # self.save_progress("Generating Authentication URL") + app_state = {} + action_result = self.add_action_result(ActionResult(param)) + + if not (self._admin_access_required and self._admin_access_granted): + + self.save_progress("Getting App REST endpoint URL") + # Get the URL to the app's REST Endpoint, this is the url that the TC dialog + # box will ask the user to connect to + ret_val, app_rest_url = self._get_app_rest_url(action_result) + + if phantom.is_fail(ret_val): + self.save_progress(MS_REST_URL_NOT_AVAILABLE_MESSAGE.format(error=self.get_status())) + return self.set_status(phantom.APP_ERROR) + + # create the url that the oauth server should re-direct to after the auth is completed + # (success and failure), this is added to the state so that the request handler will access + # it later on + redirect_uri = f"{app_rest_url}/result" + app_state['redirect_uri'] = redirect_uri + + self.save_progress(MS_OAUTH_URL_MESSAGE) + self.save_progress(redirect_uri) + + self._client_id = urlparse.quote(self._client_id) + self._tenant = urlparse.quote(self._tenant) + + query_params = { + 'client_id': self._client_id, + 'redirect_uri': redirect_uri, + 'state': self._asset_id, + } + + if self._admin_access_required: + # Create the url for fetching administrator consent + admin_consent_url_base = MS_AZURE_ADMIN_CONSENT_URL.format(tenant_id=self._tenant) + else: + # Create the url authorization, this is the one pointing to the oauth server side + admin_consent_url_base = MS_AZURE_AUTHORIZE_URL.format(tenant_id=self._tenant) + query_params['scope'] = MS_AZURE_CODE_GENERATION_SCOPE + query_params['response_type'] = 'code' + + query_string = '&'.join(f'{key}={value}' for key, value in query_params.items()) + + admin_consent_url = f'{admin_consent_url_base}?{query_string}' + + app_state['admin_consent_url'] = admin_consent_url + + # The URL that the user should open in a different tab. + # This is pointing to a REST endpoint that points to the app + url_to_show = f"{app_rest_url}/start_oauth?asset_id={self._asset_id}&" + + # Save the state, will be used by the request handler + _save_app_state(app_state, self._asset_id, self) + + self.save_progress('Please connect to the following URL from a different tab to continue the connectivity process') + self.save_progress(url_to_show) + self.save_progress(MS_AZURE_AUTHORIZE_TROUBLESHOOT_MESSAGE) + + time.sleep(MS_AZURE_WAIT_FOR_URL_SLEEP) + + completed = False + + if not _is_valid_asset_id(self._asset_id): + return action_result.set_status(phantom.APP_ERROR, "Invalid asset id") + + auth_status_file_path = _get_file_path(self._asset_id, is_state_file=False) + + self.save_progress('Waiting for authorization to complete') + + for i in range(0, 40): + + self.send_progress('{0}'.format('.' * (i % 10))) + + if auth_status_file_path.is_file(): + completed = True + auth_status_file_path.unlink() + break + + time.sleep(MS_TC_STATUS_SLEEP) + + if not completed: + self.save_progress("Authentication process does not seem to be completed. Timing out") + self.save_progress(MS_AZURE_TEST_CONNECTIVITY_FAILURE_MESSAGE) + return self.set_status(phantom.APP_ERROR) + + self.send_progress("") + + # Load the state again, since the http request handlers would have saved the result of the admin consent + self._state = _load_app_state(self._asset_id, self) + + # Deleting the local state file because of it replicates with actual state file while installing the app + current_file_path = pathlib.Path(__file__).resolve() + input_file = f'{self._asset_id}_state.json' + state_file_path = current_file_path.with_name(input_file) + state_file_path.unlink() + + if not self._state: + self.save_progress(MS_STATE_FILE_ERROR_MESSAGE) + self.save_progress(MS_AZURE_TEST_CONNECTIVITY_FAILURE_MESSAGE) + return action_result.set_status(phantom.APP_ERROR) + + self._state.setdefault('admin_consent', False) + + if self._admin_access_required and not self._state.get('admin_consent'): + self.save_progress(MS_ADMIN_CONSENT_ERROR_MESSAGE) + self.save_progress(MS_AZURE_TEST_CONNECTIVITY_FAILURE_MESSAGE) + return action_result.set_status(phantom.APP_ERROR) + + if not self._admin_access_required and not self._state.get('code'): + self.save_progress(MS_AUTHORIZATION_ERROR_MESSAGE) + self.save_progress(MS_AZURE_TEST_CONNECTIVITY_FAILURE_MESSAGE) + return action_result.set_status(phantom.APP_ERROR) + + if self._admin_access_required: + self.save_progress("Admin consent received") + self.save_progress( + "Waiting for 30 seconds before generating token. If action fails with '403: AccessDenied' error, " + "please check permissions and re-run the 'test connectivity' after some time.") + self.save_progress( + "Admin consent is already received. You can mark 'Admin Consent Already Provided' to True, " + "unless you make changes in the permissions.") + time.sleep(30) + + self.save_progress(MS_GENERATING_ACCESS_TOKEN_MESSAGE) + ret_val = self._get_token(action_result) + if phantom.is_fail(ret_val): + return action_result.get_status() + + self.save_progress("Getting info about a single user to verify token") + params = {'$top': '1'} + ret_val, response = self._make_rest_call_helper(action_result, "/users", params=params) + + if phantom.is_fail(ret_val): + self.save_progress("API to get users failed") + self.save_progress(MS_AZURE_TEST_CONNECTIVITY_FAILURE_MESSAGE) + return self.set_status(phantom.APP_ERROR) + + value = response.get('value') + + if value: + self.save_progress("Got user info") + + self.save_progress(MS_AZURE_TEST_CONNECTIVITY_PASSED) + + return self.set_status(phantom.APP_SUCCESS) + + def _handle_list_users(self, param): + + self.save_progress(f"In action handler for: {self.get_action_identifier()}") + action_result = self.add_action_result(ActionResult(dict(param))) + + filter_string = param.get('filter_string') + select_string = param.get('select_string') + expand_string = param.get('expand_string') + use_advanced_query = param.get('use_advanced_query') + + headers = {} + parameters = {} + + if filter_string: + parameters['$filter'] = filter_string + if select_string: + select_string = [param_value.strip() for param_value in select_string.split(",")] + select_string = list(filter(None, select_string)) + parameters['$select'] = ','.join(param_value for param_value in select_string) + if expand_string: + parameters['$expand'] = expand_string + if use_advanced_query: + headers['ConsistencyLevel'] = 'eventual' + parameters['$count'] = 'true' + + ret_val = self._handle_pagination(action_result, '/users', headers=headers, params=parameters) + + if phantom.is_fail(ret_val): + return action_result.get_status() + + summary = action_result.update_summary({}) + resp_data = action_result.get_data() + if resp_data and resp_data[action_result.get_data_size() - 1] == 'Empty response': + summary['num_users'] = (action_result.get_data_size()) - 1 + else: + summary['num_users'] = action_result.get_data_size() + + self.save_progress(f"Completed action handler for: {self.get_action_identifier()}") + return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_reset_password(self, param): + + self.save_progress(f"In action handler for: {self.get_action_identifier()}") + action_result = self.add_action_result(ActionResult(dict(param))) + + user_id = param['user_id'] + temp_password = param.get('temp_password', '') + force_change = param.get('force_change', True) + + data = { + 'passwordProfile': { + 'forceChangePasswordNextSignIn': force_change, + 'password': temp_password + } + } + + endpoint = f'/users/{user_id}' + + ret_val, _ = self._make_rest_call_helper(action_result, endpoint, json=data, method='patch') + + if phantom.is_fail(ret_val): + return ret_val + + summary = action_result.update_summary({}) + summary['status'] = f"Successfully reset password for {user_id}" + + # An empty response indicates success. No response body is returned. + self.save_progress(f"Completed action handler for: {self.get_action_identifier()}") + return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_enable_user(self, param): + + self.save_progress(f"In action handler for: {self.get_action_identifier()}") + action_result = self.add_action_result(ActionResult(dict(param))) + + user_id = param['user_id'] + + data = { + "accountEnabled": True + } + + endpoint = f'/users/{user_id}' + ret_val, _ = self._make_rest_call_helper(action_result, endpoint, json=data, method='patch') + + if phantom.is_fail(ret_val): + return action_result.get_status() + + summary = action_result.update_summary({}) + summary['status'] = f"Successfully enabled user {user_id}" + + # An empty response indicates success. No response body is returned. + self.save_progress(f"Completed action handler for: {self.get_action_identifier()}") + return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_invalidate_tokens(self, param): + + self.save_progress(f"In action handler for: {self.get_action_identifier()}") + action_result = self.add_action_result(ActionResult(dict(param))) + + user_id = param['user_id'] + endpoint = f'/users/{user_id}/revokeSignInSessions' + + ret_val, _ = self._make_rest_call_helper(action_result, endpoint, method='post') + + if phantom.is_fail(ret_val): + return action_result.get_status() + + summary = action_result.update_summary({}) + summary['status'] = "Successfully disabled tokens" + + self.save_progress(f"Completed action handler for: {self.get_action_identifier()}") + return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_disable_user(self, param): + + self.save_progress(f"In action handler for: {self.get_action_identifier()}") + action_result = self.add_action_result(ActionResult(dict(param))) + + user_id = param['user_id'] + + data = { + "accountEnabled": False + } + + endpoint = f'/users/{user_id}' + ret_val, _ = self._make_rest_call_helper(action_result, endpoint, json=data, method='patch') + + if phantom.is_fail(ret_val): + return action_result.get_status() + + summary = action_result.update_summary({}) + summary['status'] = f"Successfully disabled user {user_id}" + + self.save_progress(f"Completed action handler for: {self.get_action_identifier()}") + return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_list_user_attributes(self, param): + + self.save_progress(f"In action handler for: {self.get_action_identifier()}") + action_result = self.add_action_result(ActionResult(dict(param))) + + user_id = param.get('user_id') + select_string = param.get('select_string') + expand_string = param.get('expand_string') + use_advanced_query = param.get('use_advanced_query') + + headers = {} + parameters = {} + + if select_string: + select_string = [param_value.strip() for param_value in select_string.split(",")] + select_string = list(filter(None, select_string)) + parameters['$select'] = ','.join(param_value for param_value in select_string) + if expand_string: + parameters['$expand'] = expand_string + if use_advanced_query: + headers['ConsistencyLevel'] = 'eventual' + parameters['$count'] = 'true' + + if user_id: + endpoint = f'/users/{user_id}' + else: + endpoint = '/users' + + ret_val = self._handle_pagination(action_result, endpoint, headers=headers, params=parameters) + + if phantom.is_fail(ret_val): + return action_result.get_status() + + summary = action_result.update_summary({}) + if user_id: + summary['status'] = f"Successfully retrieved attributes for user {user_id}" + else: + summary['status'] = "Successfully retrieved user attributes" + + self.save_progress(f"Completed action handler for: {self.get_action_identifier()}") + return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_list_user_devices(self, param): + + self.save_progress("In action handler for: {0}".format(self.get_action_identifier())) + action_result = self.add_action_result(ActionResult(dict(param))) + + user_id = param['user_id'] + + parameters = {} + select_string = param.get('select_string') + if select_string: + select_string = [param_value.strip() for param_value in select_string.split(",")] + select_string = list(filter(None, select_string)) + parameters['$select'] = ','.join(param_value for param_value in select_string) + + endpoint = f'/users/{user_id}/ownedDevices' + + ret_val = self._handle_pagination(action_result, endpoint, params=parameters) + + if phantom.is_fail(ret_val): + return action_result.get_status() + + summary = action_result.update_summary({}) + summary['status'] = "Successfully retrieved owned devices for user {}".format(user_id) + + return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_set_user_attribute(self, param): + + self.save_progress(f"In action handler for: {self.get_action_identifier()}") + action_result = self.add_action_result(ActionResult(dict(param))) + + user_id = param['user_id'] + attribute = param['attribute'] + attribute_value = param['attribute_value'] + + data = { + attribute: attribute_value + } + + endpoint = f'/users/{user_id}' + ret_val, _ = self._make_rest_call_helper(action_result, endpoint, json=data, method='patch') + + if phantom.is_fail(ret_val): + return action_result.get_status() + + summary = action_result.update_summary({}) + summary['status'] = "Successfully updated user attribute" + + self.save_progress(f"Completed action handler for: {self.get_action_identifier()}") + return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_add_user(self, param): + + config = self.get_config() + self.save_progress(f"In action handler for: {self.get_action_identifier()}") + action_result = self.add_action_result(ActionResult(dict(param))) + + object_id = param['group_object_id'] + user_id = param['user_id'] + + data = { + '@odata.id': "https://{}/directoryObjects/{}".format(MSADGRAPH_API_REGION[config.get(MS_AZURE_URL, "Global")], user_id) + } + + endpoint = f'/groups/{object_id}/members/$ref' + ret_val, _ = self._make_rest_call_helper(action_result, endpoint, json=data, method='post') + + summary = action_result.update_summary({}) + if phantom.is_fail(ret_val): + message = action_result.get_message() + if 'references already exist for the following modified properties: \'members\'.' in message: + summary['status'] = "User already in group" + return action_result.get_status() + else: + return ret_val + else: + summary['status'] = "Successfully added user to group" + + self.save_progress(f"Completed action handler for: {self.get_action_identifier()}") + return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_remove_user(self, param): + + self.save_progress(f"In action handler for: {self.get_action_identifier()}") + action_result = self.add_action_result(ActionResult(dict(param))) + + object_id = param['group_object_id'] + user_id = param['user_id'] + + endpoint = f'/groups/{object_id}/members/{user_id}/$ref' + ret_val, _ = self._make_rest_call_helper(action_result, endpoint, method='delete') + + summary = action_result.update_summary({}) + if phantom.is_fail(ret_val): + message = action_result.get_message() + if 'does not exist or one of its queried' in message: + summary['status'] = "User not in group" + return action_result.get_status() + else: + summary['status'] = "Successfully removed user from group" + + self.save_progress(f"Completed action handler for: {self.get_action_identifier()}") + return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_list_groups(self, param): + + self.save_progress(f"In action handler for: {self.get_action_identifier()}") + action_result = self.add_action_result(ActionResult(dict(param))) + + filter_string = param.get('filter_string') + select_string = param.get('select_string') + expand_string = param.get('expand_string') + use_advanced_query = param.get('use_advanced_query') + + headers = {} + parameters = {} + + if filter_string: + parameters['$filter'] = filter_string + if select_string: + select_string = [param_value.strip() for param_value in select_string.split(",")] + select_string = list(filter(None, select_string)) + parameters['$select'] = ','.join(param_value for param_value in select_string) + if expand_string: + parameters['$expand'] = expand_string + if use_advanced_query: + headers['ConsistencyLevel'] = 'eventual' + parameters['$count'] = 'true' + + ret_val = self._handle_pagination(action_result, '/groups', headers=headers, params=parameters) + + if phantom.is_fail(ret_val): + return action_result.get_status() + + summary = action_result.update_summary({}) + resp_data = action_result.get_data() + if resp_data and resp_data[action_result.get_data_size() - 1] == 'Empty response': + summary['num_groups'] = (action_result.get_data_size()) - 1 + else: + summary['num_groups'] = action_result.get_data_size() + + self.save_progress(f"Completed action handler for: {self.get_action_identifier()}") + return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_get_group(self, param): + + self.save_progress(f"In action handler for: {self.get_action_identifier()}") + action_result = self.add_action_result(ActionResult(dict(param))) + + select_string = param.get('select_string') + expand_string = param.get('expand_string') + use_advanced_query = param.get('use_advanced_query') + + headers = {} + parameters = {} + + if select_string: + select_string = [param_value.strip() for param_value in select_string.split(",")] + select_string = list(filter(None, select_string)) + parameters['$select'] = ','.join(param_value for param_value in select_string) + if expand_string: + parameters['$expand'] = expand_string + if use_advanced_query: + headers['ConsistencyLevel'] = 'eventual' + parameters['$count'] = 'true' + + object_id = param['object_id'] + + endpoint = f'/groups/{object_id}' + + ret_val, response = self._make_rest_call_helper(action_result, endpoint, method='get', headers=headers, params=parameters) + + if phantom.is_fail(ret_val): + return action_result.get_status() + + action_result.add_data(response) + + summary = action_result.update_summary({}) + summary['status'] = f"Successfully retrieved group {object_id}" + + self.save_progress(f"Completed action handler for: {self.get_action_identifier()}") + return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_list_group_members(self, param): + + self.save_progress(f"In action handler for: {self.get_action_identifier()}") + action_result = self.add_action_result(ActionResult(dict(param))) + + object_id = param['group_object_id'] + + select_string = param.get('select_string') + expand_string = param.get('expand_string') + use_advanced_query = param.get('use_advanced_query') + + headers = {} + parameters = {} + + if select_string: + select_string = [param_value.strip() for param_value in select_string.split(",")] + select_string = list(filter(None, select_string)) + parameters['$select'] = ','.join(param_value for param_value in select_string) + if expand_string: + parameters['$expand'] = expand_string + if use_advanced_query: + headers['ConsistencyLevel'] = 'eventual' + parameters['$count'] = 'true' + + endpoint = f'/groups/{object_id}/members' + + ret_val = self._handle_pagination(action_result, endpoint, headers=headers, params=parameters) + + if phantom.is_fail(ret_val): + return action_result.get_status() + + summary = action_result.update_summary({}) + summary['num_users'] = action_result.get_data_size() + + self.save_progress(f"Completed action handler for: {self.get_action_identifier()}") + return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_list_directory_roles(self, param): + + self.save_progress(f"In action handler for: {self.get_action_identifier()}") + action_result = self.add_action_result(ActionResult(dict(param))) + + endpoint = '/directoryRoles' + ret_val, response = self._make_rest_call_helper(action_result, endpoint, method='get') + + if phantom.is_fail(ret_val): + return action_result.get_status() + + value = response.get('value', []) + for item in value: + action_result.add_data(item) + + summary = action_result.update_summary({}) + summary['num_directory_roles'] = len(value) + + self.save_progress(f"Completed action handler for: {self.get_action_identifier()}") + return action_result.set_status(phantom.APP_SUCCESS) + + def _handle_validate_group(self, param): + + self.save_progress(f"In action handler for: {self.get_action_identifier()}") + action_result = self.add_action_result(ActionResult(dict(param))) + + object_id = param['group_object_id'] + user_id = param['user_id'] + + endpoint = f'/users/{user_id}/memberOf?$filter=id eq \'{object_id}\'' + ret_val, response = self._make_rest_call_helper(action_result, endpoint, method='get') + + if phantom.is_fail(ret_val): + return action_result.get_status() + + user_id_map = {} + + for user in response.get('value', []): + user_id_map[user['id']] = user['displayName'] + + self.save_progress(f"Completed action handler for: {self.get_action_identifier()}") + return action_result.set_status(phantom.APP_SUCCESS, f"User is member of group: {ret_val}") + + def _get_token(self, action_result): + """ This function is used to get a token via REST Call. + + :param action_result: Object of action result + :return: status(phantom.APP_SUCCESS/phantom.APP_ERROR) + """ + + data = { + 'client_id': self._client_id, + 'client_secret': self._client_secret, + } + + req_url = SERVER_TOKEN_URL.format(self._tenant) + headers = { + 'Content-Type': 'application/x-www-form-urlencoded' + } + + if not self._admin_access_required: + data['scope'] = MS_AZURE_CODE_GENERATION_SCOPE + data['redirect_uri'] = self._state.get('redirect_uri') + auth_code = self._state.get('code', None) + if self._state.get(MS_AZURE_TOKEN_STRING, {}).get(MS_AZURE_REFRESH_TOKEN_STRING, None): + data['refresh_token'] = self._refresh_token + data['grant_type'] = 'refresh_token' + elif auth_code: + data['code'] = auth_code + data['grant_type'] = 'authorization_code' + else: + return action_result.set_status(phantom.APP_ERROR, "Unexpected details retrieved from the state file.") + else: + data['scope'] = 'https://graph.microsoft.com/.default' + data['grant_type'] = 'client_credentials' + + ret_val, resp_json = self._make_rest_call(req_url, action_result, headers=headers, data=data, method='post') + + if phantom.is_fail(ret_val): + return action_result.get_status() + + if self._admin_access_required and self._admin_access_granted: + self._state['admin_consent'] = True + + self._state[MS_AZURE_TOKEN_STRING] = resp_json + self._access_token = resp_json.get(MS_AZURE_ACCESS_TOKEN_STRING, None) + self._refresh_token = resp_json.get(MS_AZURE_REFRESH_TOKEN_STRING, None) + + return phantom.APP_SUCCESS + + def _handle_pagination(self, action_result, endpoint, headers=None, params=None): + """ + This action is used to create an iterator that will paginate through responses from called methods. + + :param action_result: Object of ActionResult class + :param endpoint: REST endpoint that needs to appended to the service address + :param headers: Dictionary of headers for the rest API calls + :param params: Dictionary of params for the rest API calls + """ + # maximum page size + page_size = MS_AZURE_PAGE_SIZE + if isinstance(params, dict): + params.update({"$top": page_size}) + else: + params = {"$top": page_size} + + while True: + + # make rest call + ret_val, response = self._make_rest_call_helper(action_result, endpoint, headers=headers, params=params, method='get') + + if phantom.is_fail(ret_val): + return None + + if "value" in response: + for user in response.get('value', []): + action_result.add_data(user) + if len(response.get('value')) > 0 and response.get('value')[0] == {}: + action_result.add_data('Empty response') + else: + action_result.add_data(response) + + if response.get(MS_AZURE_NEXT_LINK_STRING): + parsed_url = urlparse.urlparse(response.get(MS_AZURE_NEXT_LINK_STRING)) + try: + params['$skiptoken'] = urlparse.parse_qs(parsed_url.query).get('$skiptoken')[0] + except Exception: + self.debug_print(f"odata.nextLink is {response.get(MS_AZURE_NEXT_LINK_STRING)}") + self.debug_print("Error occurred while extracting skiptoken from the odata.nextLink") + break + else: + break + + return phantom.APP_SUCCESS + + def handle_action(self, param): + + ret_val = phantom.APP_SUCCESS + + # Get the action that we are supposed to execute for this App Run + action_id = self.get_action_identifier() + + self.debug_print("action_id", self.get_action_identifier()) + + if action_id == 'test_connectivity': + ret_val = self._handle_test_connectivity(param) + + elif action_id == 'list_users': + ret_val = self._handle_list_users(param) + + elif action_id == 'reset_password': + ret_val = self._handle_reset_password(param) + + elif action_id == 'invalidate_tokens': + ret_val = self._handle_invalidate_tokens(param) + + elif action_id == 'enable_user': + ret_val = self._handle_enable_user(param) + + elif action_id == 'disable_user': + ret_val = self._handle_disable_user(param) + + elif action_id == 'list_user_attributes': + ret_val = self._handle_list_user_attributes(param) + + elif action_id == 'set_user_attribute': + ret_val = self._handle_set_user_attribute(param) + + elif action_id == 'remove_user': + ret_val = self._handle_remove_user(param) + + elif action_id == 'add_user': + ret_val = self._handle_add_user(param) + + elif action_id == 'list_groups': + ret_val = self._handle_list_groups(param) + + elif action_id == 'get_group': + ret_val = self._handle_get_group(param) + + elif action_id == 'list_group_members': + ret_val = self._handle_list_group_members(param) + + elif action_id == 'validate_group': + ret_val = self._handle_validate_group(param) + + elif action_id == 'list_directory_roles': + ret_val = self._handle_list_directory_roles(param) + + elif action_id == 'generate_token': + ret_val = self._handle_generate_token(param) + + elif action_id == 'list_user_devices': + ret_val = self._handle_list_user_devices(param) + + return ret_val + + def initialize(self): + """ This is an optional function that can be implemented by the AppConnector derived class. Since the + configuration dictionary is already validated by the time this function is called, it's a good place to do any + extra initialization of any internal modules. This function MUST return a value of either phantom.APP_SUCCESS or + phantom.APP_ERROR. If this function returns phantom.APP_ERROR, then AppConnector::handle_action will not get + called. + """ + + self._state = self.load_state() + + # get the asset config + config = self.get_config() + self._asset_id = self.get_asset_id() + + self._tenant = config[MS_AZURE_CONFIG_TENANT] + self._client_id = config[MS_AZURE_CONFIG_CLIENT_ID] + self._client_secret = config[MS_AZURE_CONFIG_CLIENT_SECRET] + self._admin_access_required = config.get(MS_AZURE_CONFIG_ADMIN_ACCESS_REQUIRED, False) + self._admin_access_granted = config.get(MS_AZURE_CONFIG_ADMIN_ACCESS_GRANTED, False) + self._access_token = self._state.get(MS_AZURE_TOKEN_STRING, {}).get(MS_AZURE_ACCESS_TOKEN_STRING) + self._refresh_token = self._state.get(MS_AZURE_TOKEN_STRING, {}).get(MS_AZURE_REFRESH_TOKEN_STRING) + self._base_url = MSADGRAPH_API_URLS[config.get(MS_AZURE_URL, "Global")] + + return phantom.APP_SUCCESS + + def finalize(self): + + # Save the state, this data is saved across actions and app upgrades + self.save_state(self._state) + return phantom.APP_SUCCESS + + +if __name__ == '__main__': + + import argparse + + import pudb + + pudb.set_trace() + + argparser = argparse.ArgumentParser() + + argparser.add_argument('input_test_json', help='Input Test JSON file') + argparser.add_argument('-u', '--username', help='username', required=False) + argparser.add_argument('-p', '--password', help='password', required=False) + argparser.add_argument('-v', '--verify', action='store_true', help='verify', required=False, default=False) + + args = argparser.parse_args() + session_id = None + + username = args.username + password = args.password + verify = args.verify + + if username is not None and password is None: + + # User specified a username but not a password, so ask + import getpass + password = getpass.getpass("Password: ") + + if username and password: + login_url = BaseConnector._get_phantom_base_url() + "login" + try: + print("Accessing the Login page") + r = requests.get(login_url, verify=verify, timeout=60) + csrftoken = r.cookies['csrftoken'] + + data = dict() + data['username'] = username + data['password'] = password + data['csrfmiddlewaretoken'] = csrftoken + + headers = dict() + headers['Cookie'] = 'csrftoken=' + csrftoken + headers['Referer'] = login_url + + print("Logging into Platform to get the session id") + r2 = requests.post(login_url, verify=verify, data=data, headers=headers, timeout=60) + session_id = r2.cookies['sessionid'] + except Exception as e: + print("Unable to get session id from the platform. Error: " + str(e)) + sys.exit(1) + + with open(args.input_test_json) as f: + in_json = f.read() + in_json = json.loads(in_json) + print(json.dumps(in_json, indent=4)) + + connector = MSADGraphConnector() + connector.print_progress_message = True + + if session_id is not None: + in_json['user_session_token'] = session_id + connector._set_csrf_info(csrftoken, headers['Referer']) + + ret_val = connector._handle_action(json.dumps(in_json), None) + print(json.dumps(json.loads(ret_val), indent=4)) + + sys.exit(0) diff --git a/deployment-apps/msadgraph/msadgraph_consts.py b/deployment-apps/msadgraph/msadgraph_consts.py new file mode 100644 index 00000000..1f05ba95 --- /dev/null +++ b/deployment-apps/msadgraph/msadgraph_consts.py @@ -0,0 +1,86 @@ +# File: msadgraph_consts.py +# +# Copyright (c) 2022-2023 Splunk Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed under +# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +# either express or implied. See the License for the specific language governing permissions +# and limitations under the License. + +PHANTOM_SYS_INFO_URL = "{base_url}rest/system_info" +PHANTOM_ASSET_INFO_URL = "{base_url}rest/asset/{asset_id}" + +MSADGRAPH_API_URLS = { + "Global": "https://graph.microsoft.com/v1.0", + "US Gov L4": "https://graph.microsoft.us", + "US Gov L5 (DOD)": "https://dod-graph.microsoft.us", + "Germany": "https://graph.microsoft.de", + "China (21Vianet)": "https://microsoftgraph.chinacloudapi.cn" +} +MSADGRAPH_API_REGION = { + "Global": "graph.microsoft.com/v1.0", + "US Gov L4": "graph.microsoft.us", + "US Gov L5 (DOD)": "dod-graph.microsoft.us", + "Germany": "graph.microsoft.de", + "China (21Vianet)": "microsoftgraph.chinacloudapi.cn" +} +MS_AZURE_CONFIG_TENANT = 'tenant_id' +MS_AZURE_CONFIG_SUBSCRIPTION = 'subscription_id' +MS_AZURE_CONFIG_CLIENT_ID = 'client_id' +MS_AZURE_CONFIG_CLIENT_SECRET = 'client_secret' # pragma: allowlist secret +MS_AZURE_CONFIG_ADMIN_ACCESS_REQUIRED = 'admin_access_required' +MS_AZURE_CONFIG_ADMIN_ACCESS_GRANTED = 'admin_access_granted' +MS_AZURE_URL = "region" +MS_AZURE_CONFIG_ADMIN_ACCESS = 'admin_access' +MS_AZURE_TOKEN_STRING = 'token' +MS_AZURE_ACCESS_TOKEN_STRING = 'access_token' +MS_AZURE_REFRESH_TOKEN_STRING = 'refresh_token' +MS_AZURE_PHANTOM_BASE_URL = '{phantom_base_url}rest' +MS_AZURE_PHANTOM_SYS_INFO_URL = '/system_info' +MS_AZURE_PHANTOM_ASSET_INFO_URL = '/asset/{asset_id}' +MS_AZURE_BASE_URL_NOT_FOUND_MESSAGE = 'SOAR Base URL not found in System Settings. ' \ + 'Please specify this value in System Settings.' +MS_AZURE_HTML_ERROR = 'Bad Request Bad Request - Invalid URL HTTP Error 400. The request URL is invalid.' +MS_AZURE_NEXT_LINK_STRING = 'odata.nextLink' +MS_AZURE_PAGE_SIZE = 999 +MS_AZURE_ERROR_MESSAGE_UNKNOWN = "Unknown error occurred. Please check the asset configuration and|or action parameters." + +# status codes +MS_AZURE_BAD_REQUEST_CODE = 400 +MS_AZURE_NOT_FOUND_CODE = 404 + +# For authorization code +SERVER_TOKEN_URL = "https://login.microsoftonline.com/{0}/oauth2/v2.0/token" +MS_AZURE_ADMIN_CONSENT_URL = "https://login.microsoftonline.com/{tenant_id}/adminconsent" +MS_AZURE_AUTHORIZE_URL = "https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/authorize" +MS_REST_URL_NOT_AVAILABLE_MESSAGE = 'Rest URL not available. Error: {error}' +MS_OAUTH_URL_MESSAGE = 'Using OAuth URL:\n' +MS_AUTHORIZE_USER_MESSAGE = 'Please authorize user in a separate tab using URL:' +MS_GENERATING_ACCESS_TOKEN_MESSAGE = 'Generating access token' +MS_TC_STATUS_SLEEP = 3 +MS_AZURE_WAIT_FOR_URL_SLEEP = 5 +MS_AZURE_CODE_GENERATION_SCOPE = 'offline_access Group.ReadWrite.All User.Read.All User.ReadWrite.All Directory.ReadWrite.All \ +Directory.AccessAsUser.All User.ManageIdentities.All GroupMember.ReadWrite.All RoleManagement.ReadWrite.Directory' +MS_AZURE_AUTHORIZE_TROUBLESHOOT_MESSAGE = 'If authorization URL fails to communicate with your SOAR instance, check whether you have: '\ + ' 1. Specified the Web Redirect URL of your App -- The Redirect URL should be /result . '\ + ' 2. Configured the base URL of your SOAR Instance at Administration -> Company Settings -> Info' + +MS_AZURE_TEST_CONNECTIVITY_FAILURE_MESSAGE = "Test Connectivity Failed" +MS_AZURE_TEST_CONNECTIVITY_PASSED = "Test Connectivity Passed" +MS_AZURE_ENCRYPTION_ERROR = "Error occurred while encrypting the state file" +MS_AZURE_DECRYPTION_ERROR = "Error occurred while decrypting the state file" +MS_AZURE_STATE_FILE_CORRUPT_ERROR = "Error occurred while loading the state file due to it's unexpected format. " \ + "Resetting the state file with the default format. Please test the connectivity." +MS_AZURE_RESPONSE_ERROR_MESSAGE = "Error from server. Status Code: {status_code}. Data from server: \n{error_text}\n" +MS_AZURE_PROCESS_RESPONSE_ERROR_MESSAGE = "Can't process response from server. Status Code: {status_code} Data from server: {content}" +MS_ADMIN_CONSENT_ERROR_MESSAGE = "Admin consent not received" +MS_AUTHORIZATION_ERROR_MESSAGE = "Authorization code not received or not given" +MS_STATE_FILE_ERROR_MESSAGE = "Unable to load state file" + +DEFAULT_TIMEOUT = 30 diff --git a/deployment-apps/msadgraph/msadgraph_get_group.html b/deployment-apps/msadgraph/msadgraph_get_group.html new file mode 100644 index 00000000..5f48c5e0 --- /dev/null +++ b/deployment-apps/msadgraph/msadgraph_get_group.html @@ -0,0 +1,170 @@ +{% extends 'widgets/widget_template.html' %} +{% load custom_template %} + +{% block custom_title_prop %}{% if title_logo %}style="background-size: auto 60%; background-position: 50%; +background-repeat: no-repeat; background-image: url('/app_resource/{{ title_logo }}');"{% endif %}{% endblock %} +{% block title1 %}{{ title1 }}{% endblock %} +{% block title2 %}{{ title2 }}{% endblock %} +{% block custom_tools %} +{% endblock %} + +{% block widget_content %} + + + + + +
+ + {% for result in results %} + + + {% if not result.data %} +

No data found

+ {% else %} + {% if result.param.select_string %} +

Group Details

+ {% for curr_data in result.data %} + + + + {% for key, value in curr_data.items %} + + {% endfor %} + + + + {% for key, value in curr_data.items %} + + {% endfor %} + +
{{ key }}
{{ value }}
+
+ {% endfor %} +
+ + {% else %} +

Group Details

+ + + + + + + + {% for curr_data in result.data %} + + + + + + {% endfor %} + +
Display NameGroup Object IdDescription
+ {{ curr_data.displayName }} + + + {{ curr_data.id }} +   + + + + {{ curr_data.description }} +
+
+ {% endif %} + {% endif %} +
+ {% endfor %} + + +
+ + + +{% endblock %} + diff --git a/deployment-apps/msadgraph/msadgraph_list_group_members.html b/deployment-apps/msadgraph/msadgraph_list_group_members.html new file mode 100644 index 00000000..092ae770 --- /dev/null +++ b/deployment-apps/msadgraph/msadgraph_list_group_members.html @@ -0,0 +1,174 @@ +{% extends 'widgets/widget_template.html' %} +{% load custom_template %} + +{% block custom_title_prop %}{% if title_logo %}style="background-size: auto 60%; background-position: 50%; +background-repeat: no-repeat; background-image: url('/app_resource/{{ title_logo }}');"{% endif %}{% endblock %} +{% block title1 %}{{ title1 }}{% endblock %} +{% block title2 %}{{ title2 }}{% endblock %} +{% block custom_tools %} +{% endblock %} + +{% block widget_content %} + + + + + +
+ + {% for result in results %} + + + {% if not result.data %} +

No data found

+ {% else %} + {% if result.param.select_string %} +

List of Group Members

+ {% for curr_data in result.data %} + + + + {% for key, value in curr_data.items %} + + {% endfor %} + + + + {% for key, value in curr_data.items %} + + {% endfor %} + +
{{ key }}
{{ value }}
+
+ {% endfor %} +
+ + {% else %} +

List of Group Members

+ + + + + + + + {% for curr_data in result.data %} + + + + + + {% endfor %} + +
Display NameUser Object IdUser Princicple Name
+ {{ curr_data.displayName }} + + + {{ curr_data.id }} +   + + + + + {{ curr_data.userPrincipalName }} +   + + +
+
+ {% endif %} + {% endif %} +
+ {% endfor %} + + +
+ + +{% endblock %} + diff --git a/deployment-apps/msadgraph/msadgraph_list_groups.html b/deployment-apps/msadgraph/msadgraph_list_groups.html new file mode 100644 index 00000000..ee345ef1 --- /dev/null +++ b/deployment-apps/msadgraph/msadgraph_list_groups.html @@ -0,0 +1,174 @@ +{% extends 'widgets/widget_template.html' %} +{% load custom_template %} + +{% block custom_title_prop %}{% if title_logo %}style="background-size: auto 60%; background-position: 50%; +background-repeat: no-repeat; background-image: url('/app_resource/{{ title_logo }}');"{% endif %}{% endblock %} +{% block title1 %}{{ title1 }}{% endblock %} +{% block title2 %}{{ title2 }}{% endblock %} +{% block custom_tools %} +{% endblock %} + +{% block widget_content %} + + + + + +
+ + {% for result in results %} + + + {% if not result.data %} +

No data found

+ {% else %} + {% if result.param.select_string %} + {% for curr_data in result.data %} + {% if curr_data == 'Empty response' %} +

Empty response. Please add valid property name

+ {% else %} +

Group

+ + + + {% for key, value in curr_data.items %} + + {% endfor %} + + + + {% for key, value in curr_data.items %} + + {% endfor %} + +
+
{{ key }}
{{ value }}
+ {% endif %} + {% endfor %} +
+ + {% else %} +

List of Groups

+ + + + + + + + {% for curr_data in result.data %} + + + + + + {% endfor %} + +
Group Object IdDisplay NameDescription
+ + {{ curr_data.id }} +   + + + + {{ curr_data.displayName }} + + {{ curr_data.description }} +
+
+ {% endif %} + {% endif %} +
+ {% endfor %} + + +
+ + + +{% endblock %} + diff --git a/deployment-apps/msadgraph/msadgraph_list_user_attributes.html b/deployment-apps/msadgraph/msadgraph_list_user_attributes.html new file mode 100644 index 00000000..c70548c4 --- /dev/null +++ b/deployment-apps/msadgraph/msadgraph_list_user_attributes.html @@ -0,0 +1,175 @@ +{% extends 'widgets/widget_template.html' %} +{% load custom_template %} + +{% block custom_title_prop %}{% if title_logo %}style="background-size: auto 60%; background-position: 50%; +background-repeat: no-repeat; background-image: url('/app_resource/{{ title_logo }}');"{% endif %}{% endblock %} +{% block title1 %}{{ title1 }}{% endblock %} +{% block title2 %}{{ title2 }}{% endblock %} +{% block custom_tools %} +{% endblock %} + +{% block widget_content %} + + + + + +
+ + {% for result in results %} + + + {% if not result.data %} +

No data found

+ {% else %} + {% if result.param.select_string %} +

User Attributes

+ {% for curr_data in result.data %} + + + + {% for key, value in curr_data.items %} + + {% endfor %} + + + + {% for key, value in curr_data.items %} + + {% endfor %} + +
{{ key }}
{{ value }}
+
+{% endfor %} +
+ + {% else %} +

User Attributes

+ + + + + + + + {% for curr_data in result.data %} + + + + + + {% endfor %} + +
Display NameUser Object IdUser Princicple Name
+ {{ curr_data.displayName }} + + + {{ curr_data.id }} +   + + + + + {{ curr_data.userPrincipalName }} +   + + +
+
+ {% endif %} + {% endif %} +
+ {% endfor %} + + +
+ + + +{% endblock %} + diff --git a/deployment-apps/msadgraph/msadgraph_list_user_devices.html b/deployment-apps/msadgraph/msadgraph_list_user_devices.html new file mode 100644 index 00000000..1f92afba --- /dev/null +++ b/deployment-apps/msadgraph/msadgraph_list_user_devices.html @@ -0,0 +1,163 @@ +{% extends 'widgets/widget_template.html' %} +{% load custom_template %} + +{% block custom_title_prop %}{% if title_logo %}style="background-size: auto 60%; background-position: 50%; +background-repeat: no-repeat; background-image: url('/app_resource/{{ title_logo }}');"{% endif %}{% endblock %} +{% block title1 %}{{ title1 }}{% endblock %} +{% block title2 %}{{ title2 }}{% endblock %} +{% block custom_tools %} +{% endblock %} + +{% block widget_content %} + + + + + +
+ + {% for result in results %} + + + {% if not result.data %} +

No data found

+ {% else %} + {% if result.param.select_string %} + {% for curr_data in result.data %} + {% if curr_data == 'Empty response' %} +

Empty response. Please add valid property name

+ {% else %} +

Device

+ + + + {% for key, value in curr_data.items %} + + {% endfor %} + + + + {% for key, value in curr_data.items %} + + {% endfor %} + +
+
{{ key }}
{{ value }}
+ {% endif %} + {% endfor %} +
+ + {% else %} +

List of User Devices

+ + + + + + + {% for curr_data in result.data %} + + + + + {% endfor %} + +
Display NameDevice ID
+ {{ curr_data.displayName }} + + {{ curr_data.deviceId }} +
+
+ {% endif %} + {% endif %} +
+ {% endfor %} + +
+ + + +{% endblock %} + diff --git a/deployment-apps/msadgraph/msadgraph_list_users.html b/deployment-apps/msadgraph/msadgraph_list_users.html new file mode 100644 index 00000000..a468d038 --- /dev/null +++ b/deployment-apps/msadgraph/msadgraph_list_users.html @@ -0,0 +1,177 @@ +{% extends 'widgets/widget_template.html' %} +{% load custom_template %} + +{% block custom_title_prop %}{% if title_logo %}style="background-size: auto 60%; background-position: 50%; +background-repeat: no-repeat; background-image: url('/app_resource/{{ title_logo }}');"{% endif %}{% endblock %} +{% block title1 %}{{ title1 }}{% endblock %} +{% block title2 %}{{ title2 }}{% endblock %} +{% block custom_tools %} +{% endblock %} + +{% block widget_content %} + + + + + +
+ + {% for result in results %} + + + {% if not result.data %} +

No data found

+ {% else %} + {% if result.param.select_string %} + {% for curr_data in result.data %} + {% if curr_data == 'Empty response' %} +

Empty response. Please add valid property name

+ {% else %} +

User

+ + + + {% for key, value in curr_data.items %} + + {% endfor %} + + + + {% for key, value in curr_data.items %} + + {% endfor %} + +
+
{{ key }}
{{ value }}
+ {% endif %} + {% endfor %} +
+ + {% else %} +

List of Users

+ + + + + + + + {% for curr_data in result.data %} + + + + + + {% endfor %} + +
Display NameUser Object IdUser Princicple Name
+ {{ curr_data.displayName }} + + + {{ curr_data.id }} +   + + + + + {{ curr_data.userPrincipalName }} +   + + +
+
+ {% endif %} + {% endif %} +
+ {% endfor %} + +
+ + + +{% endblock %} + diff --git a/deployment-apps/msadgraph/msadgraph_view.py b/deployment-apps/msadgraph/msadgraph_view.py new file mode 100644 index 00000000..83f9f9df --- /dev/null +++ b/deployment-apps/msadgraph/msadgraph_view.py @@ -0,0 +1,58 @@ +# File: msadgraph_view.py +# +# Copyright (c) 2022-2023 Splunk Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed under +# the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +# either express or implied. See the License for the specific language governing permissions +# and limitations under the License. +def get_ctx_result(provides, result): + + ctx_result = {} + param = result.get_param() + summary = result.get_summary() + data = result.get_data() + + ctx_result['param'] = param + ctx_result['action'] = provides + + if data: + ctx_result['data'] = data + + if summary: + ctx_result['summary'] = summary + + return ctx_result + + +def display_view(provides, all_app_runs, context): + + context['results'] = results = [] + for summary, action_results in all_app_runs: + for result in action_results: + + ctx_result = get_ctx_result(provides, result) + if (not ctx_result): + continue + results.append(ctx_result) + + if provides == "list users": + return_page = "msadgraph_list_users.html" + if provides == "list user attributes": + return_page = "msadgraph_list_user_attributes.html" + if provides == "list groups": + return_page = "msadgraph_list_groups.html" + if provides == "get group": + return_page = "msadgraph_get_group.html" + if provides == "list group members": + return_page = "msadgraph_list_group_members.html" + if provides == "list user devices": + return_page = "msadgraph_list_user_devices.html" + + return return_page diff --git a/deployment-apps/msadgraph/release_notes/1.0.5.md b/deployment-apps/msadgraph/release_notes/1.0.5.md new file mode 100644 index 00000000..f07690d4 --- /dev/null +++ b/deployment-apps/msadgraph/release_notes/1.0.5.md @@ -0,0 +1,2 @@ +* Initial release with Python3 support +* Note - This app is a replacement for the Azure AD app with Microsoft Graph API as Azure AD API is going to deprecate in near future \ No newline at end of file diff --git a/deployment-apps/msadgraph/release_notes/1.1.0.md b/deployment-apps/msadgraph/release_notes/1.1.0.md new file mode 100644 index 00000000..aa6dedd6 --- /dev/null +++ b/deployment-apps/msadgraph/release_notes/1.1.0.md @@ -0,0 +1 @@ +* Added 'list user devices' action \ No newline at end of file diff --git a/deployment-apps/msadgraph/release_notes/1.2.0.md b/deployment-apps/msadgraph/release_notes/1.2.0.md new file mode 100644 index 00000000..0a6c863b --- /dev/null +++ b/deployment-apps/msadgraph/release_notes/1.2.0.md @@ -0,0 +1,8 @@ +* Added option to use admin granted permissions +* Updated the 'test connectivity' action to allow non-interactive tests when admin consent is already provided +* Added 'expand string' and 'use advanced query' parameters in below five actions + * list users + * list groups + * list user attributes + * get group + * list group members \ No newline at end of file diff --git a/deployment-apps/msadgraph/release_notes/1.3.0.md b/deployment-apps/msadgraph/release_notes/1.3.0.md new file mode 100644 index 00000000..6a23a79b --- /dev/null +++ b/deployment-apps/msadgraph/release_notes/1.3.0.md @@ -0,0 +1,2 @@ +* Fixed the state file reseting logic [PAPP-30760] +* Removed django and requests dependencies in order to use platform packages [PAPP-31087, PAPP-31082, PAPP-31096, PAPP-30822] \ No newline at end of file diff --git a/deployment-apps/msadgraph/release_notes/1.4.0.md b/deployment-apps/msadgraph/release_notes/1.4.0.md new file mode 100644 index 00000000..88391987 --- /dev/null +++ b/deployment-apps/msadgraph/release_notes/1.4.0.md @@ -0,0 +1 @@ +* Fixed the token expiration issue [PAPP-31400] \ No newline at end of file diff --git a/deployment-apps/msadgraph/release_notes/unreleased.md b/deployment-apps/msadgraph/release_notes/unreleased.md new file mode 100644 index 00000000..fbcb2fd9 --- /dev/null +++ b/deployment-apps/msadgraph/release_notes/unreleased.md @@ -0,0 +1 @@ +**Unreleased** diff --git a/deployment-apps/msadgraph/wheels/py3/beautifulsoup4-4.9.1-py3-none-any.whl b/deployment-apps/msadgraph/wheels/py3/beautifulsoup4-4.9.1-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..080b2f8e9aa9d8260006d2d3af7032cb80b8fe55 GIT binary patch literal 115057 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�d8Z>VA$SSD`!IazspFSoo*7Y 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

&;-`LY;~ewDDVP@KoY2& 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≶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 xe@vCk(Ku)9~-IUbC^$OTQraK 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 literal 0 HcmV?d00001 diff --git a/deployment-apps/msadgraph/wheels/py3/soupsieve-2.4.1-py3-none-any.whl b/deployment-apps/msadgraph/wheels/py3/soupsieve-2.4.1-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..26a486cb50e317481f18b38a742b78eb8155d090 GIT binary patch literal 36379 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˟D^{nf) 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 E00(_>=l}o! literal 0 HcmV?d00001