diff --git a/.gitignore b/.gitignore index 868a217..1626df3 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,10 @@ output graph logs .vscode +docs/official-docs/ + +# Codex +.codex # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..c297b02 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "docs/og-docs-automation"] + path = docs/og-docs-automation + url = https://github.com/SpecterOps/og-docs-automation diff --git a/descriptions/edges/Okta_AddMember.md b/descriptions/edges/Okta_AddMember.md index 428a633..2006bb7 100644 --- a/descriptions/edges/Okta_AddMember.md +++ b/descriptions/edges/Okta_AddMember.md @@ -1,5 +1,13 @@ ## General Information -The traversable `Okta_AddMember` edges represent custom role permissions that allow a principal (user, group, or application) -to add or remove members in scoped Okta groups. These edges are created when a custom role includes -the `okta.groups.members.manage` or `okta.groups.manage` permissions. +The traversable Okta_AddMember edges represent custom role permissions that allow a principal (user, group, or application) to add or remove members in scoped Okta groups. These edges are created when a custom role includes the `okta.groups.members.manage` or `okta.groups.manage` permissions. + +```mermaid +graph LR + u1("Okta_User john\@contoso.com") + g1("Okta_Group Finance") + g2("Okta_Group Tier 0 Admins") + app1("Okta_Application Automation") + u1 -- Okta_AddMember --> g1 + app1 -- Okta_AddMember --> g2 +``` diff --git a/descriptions/edges/Okta_AgentMemberOf.md b/descriptions/edges/Okta_AgentMemberOf.md index 9568559..8bd612c 100644 --- a/descriptions/edges/Okta_AgentMemberOf.md +++ b/descriptions/edges/Okta_AgentMemberOf.md @@ -1,10 +1,20 @@ ## General Information -`Okta_AgentMemberOf` edges represent membership of an `Okta_Agent` in an `Okta_AgentPool`. +Okta_AgentMemberOf edges represent membership of an Okta_Agent in an Okta_AgentPool. Active Directory Agent Pools and their agents can be visualized in BloodHound as follows: +```mermaid +graph LR + ap1("Okta_AgentPool contoso.com") + ap2("Okta_AgentPool adatum.com") + a1("Okta_Agent CONTOSO-SRV1") + a2("Okta_Agent CONTOSO-SRV2") + a3("Okta_Agent ADATUM-SRV1") + a1 -- Okta_AgentMemberOf --> ap1 + a2 -- Okta_AgentMemberOf --> ap1 + a3 -- Okta_AgentMemberOf --> ap2 +``` -> [!WARNING] -> Traversable edges between the `Okta_AgentPool` and AD `Domain` nodes are not created in the current version of `OktaHound`. -> This functionality is planned for a future release. +> [!NOTE] +> Traversable edges between Okta_AgentPool and AD Domain nodes are not modeled in the current version of the Okta BloodHound extension. Support for this is planned for a future release. \ No newline at end of file diff --git a/descriptions/edges/Okta_AgentPoolFor.md b/descriptions/edges/Okta_AgentPoolFor.md index 3656bab..826930a 100644 --- a/descriptions/edges/Okta_AgentPoolFor.md +++ b/descriptions/edges/Okta_AgentPoolFor.md @@ -1,3 +1,26 @@ ## General Information -`Okta_AgentPoolFor` edges connect an AD `Okta_AgentPool` to the backing `Okta_Application` used for directory integration. +Okta_AgentPoolFor edges connect an AD Okta_AgentPool to the backing Okta_Application used for directory integration. +```mermaid +graph TB + subgraph Active Directory + d1("Domain contoso.com") + c1("Computer CONTOSO-SRV1$") + c2("Computer CONTOSO-SRV2$") + d1 -- Contains --> c1 + d1 -- Contains --> c2 + end + + subgraph Okta + ap1("Okta_AgentPool contoso.com") + a1("Okta_Agent CONTOSO-SRV1") + a2("Okta_Agent CONTOSO-SRV2") + app1("Okta_Application AD contoso.com") + a1 -- Okta_AgentMemberOf --> ap1 + a2 -- Okta_AgentMemberOf --> ap1 + ap1 -- Okta_AgentPoolFor --> app1 + end + + c1 -- Okta_HostsAgent --> a1 + c2 -- Okta_HostsAgent --> a2 +``` diff --git a/descriptions/edges/Okta_ApiTokenFor.md b/descriptions/edges/Okta_ApiTokenFor.md index 48b8e2a..ea7aecc 100644 --- a/descriptions/edges/Okta_ApiTokenFor.md +++ b/descriptions/edges/Okta_ApiTokenFor.md @@ -1,6 +1,6 @@ ## General Information -The traversable `Okta_ApiTokenFor` edges represent the API token assignments for users in Okta, represented by the [Okta_User](../Nodes/Okta_User.md) nodes: +The traversable Okta_ApiTokenFor edges represent the API token assignments for users in Okta, represented by the Okta_User nodes: ```mermaid graph LR diff --git a/descriptions/edges/Okta_AppAdmin.md b/descriptions/edges/Okta_AppAdmin.md index 12d25bf..a175958 100644 --- a/descriptions/edges/Okta_AppAdmin.md +++ b/descriptions/edges/Okta_AppAdmin.md @@ -1,7 +1,6 @@ ## General Information -The traversable `Okta_AppAdmin` edges represent Application Administrator role assignments. -Application Administrators can manage application configurations, user assignments, and provisioning settings for their assigned applications. +The traversable Okta_AppAdmin edges represent Application Administrator role assignments. Application Administrators can manage application configurations, user assignments, and provisioning settings for their assigned applications. ```mermaid graph LR diff --git a/descriptions/edges/Okta_AppAssignment.md b/descriptions/edges/Okta_AppAssignment.md index 1941504..45d520f 100644 --- a/descriptions/edges/Okta_AppAssignment.md +++ b/descriptions/edges/Okta_AppAssignment.md @@ -2,7 +2,7 @@ Only users that are assigned to applications can access them. Users can be assigned to applications directly or indirectly through group memberships. -The non-traversable `Okta_AppAssignment` edges represent the application assignments for users and groups in Okta: +The non-traversable Okta_AppAssignment edges represent the application assignments for users and groups in Okta: ```mermaid graph LR @@ -16,14 +16,14 @@ graph LR a1("Okta_Application SalesForce") a2("Okta_Application GitHub") a3("Okta_Application VPN") - e -- Okta_AppAssignment --> a1 + e -. Okta_AppAssignment .-> a1 u1 -- Okta_MemberOf --> e u2 -- Okta_MemberOf --> e u3 -- Okta_MemberOf --> e u4 -- Okta_MemberOf --> e u3 -- Okta_MemberOf --> g1 u4 -- Okta_MemberOf --> g1 - g1 -- Okta_AppAssignment --> a2 - u4 -- Okta_AppAssignment --> a3 - u5 -- Okta_AppAssignment --> a3 + g1 -. Okta_AppAssignment .-> a2 + u4 -. Okta_AppAssignment .-> a3 + u5 -. Okta_AppAssignment .-> a3 ``` diff --git a/descriptions/edges/Okta_Contains.md b/descriptions/edges/Okta_Contains.md index 79d0513..4d940de 100644 --- a/descriptions/edges/Okta_Contains.md +++ b/descriptions/edges/Okta_Contains.md @@ -1,6 +1,6 @@ ## General Information -The traversable `Okta_Contains` edges represent the containment relationships between the organization and other entities in Okta. The organization node will have `Okta_Contains` edges to all other nodes in the graph, with some exceptions. +The traversable Okta_Contains edges represent the containment relationships between the organization and other entities in Okta. The organization node will have Okta_Contains edges to all other nodes in the graph, with some exceptions. ```mermaid graph LR diff --git a/descriptions/edges/Okta_CreatorOf.md b/descriptions/edges/Okta_CreatorOf.md index accbe0b..ad8fd45 100644 --- a/descriptions/edges/Okta_CreatorOf.md +++ b/descriptions/edges/Okta_CreatorOf.md @@ -1,6 +1,6 @@ ## General Information -The non-traversable `Okta_CreatorOf` edges represent the creator relationships between API Service Integration instances and users in Okta: +The non-traversable Okta_CreatorOf edges represent the creator relationships between API Service Integration instances and users in Okta: ```mermaid graph LR diff --git a/descriptions/edges/Okta_DeviceOf.md b/descriptions/edges/Okta_DeviceOf.md index ae61f55..dc69cec 100644 --- a/descriptions/edges/Okta_DeviceOf.md +++ b/descriptions/edges/Okta_DeviceOf.md @@ -1,6 +1,6 @@ ## General Information -The non-traversable `Okta_DeviceOf` edges represent the ownership relationships between users and devices in Okta: +The non-traversable Okta_DeviceOf edges represent the ownership relationships between users and devices in Okta: ```mermaid graph LR diff --git a/descriptions/edges/Okta_GroupAdmin.md b/descriptions/edges/Okta_GroupAdmin.md index d59c085..29bc892 100644 --- a/descriptions/edges/Okta_GroupAdmin.md +++ b/descriptions/edges/Okta_GroupAdmin.md @@ -1,7 +1,6 @@ ## General Information -The traversable `Okta_GroupAdmin` edges represent Group Administrator (also known as User Administrator) role assignments. -Group Administrators can manage users and groups within their assigned scope. +The traversable Okta_GroupAdmin edges represent Group Administrator (also known as User Administrator) role assignments. Group Administrators can manage users and groups within their assigned scope. ```mermaid graph LR @@ -10,7 +9,7 @@ graph LR g1("Okta_Group Marketing") u1 -- Okta_GroupAdmin --> u2 u1 -- Okta_GroupAdmin --> g1 - u2-. Okta_MemberOf .-> g1 + u2 -- Okta_MemberOf --> g1 ``` Target group memberships are flattened when the assignment is evaluated. diff --git a/descriptions/edges/Okta_GroupMembershipAdmin.md b/descriptions/edges/Okta_GroupMembershipAdmin.md index f1ed923..6586dc7 100644 --- a/descriptions/edges/Okta_GroupMembershipAdmin.md +++ b/descriptions/edges/Okta_GroupMembershipAdmin.md @@ -1,7 +1,6 @@ ## General Information -The traversable `Okta_GroupMembershipAdmin` edges represent Group Membership Administrator role assignments. -Group Membership Administrators can add and remove members from groups within their assigned scope but cannot modify the groups themselves. +The traversable Okta_GroupMembershipAdmin edges represent Group Membership Administrator role assignments. Group Membership Administrators can add and remove members from groups within their assigned scope but cannot modify the groups themselves. ```mermaid graph LR diff --git a/descriptions/edges/Okta_GroupPull.md b/descriptions/edges/Okta_GroupPull.md index e3af785..ca6193a 100644 --- a/descriptions/edges/Okta_GroupPull.md +++ b/descriptions/edges/Okta_GroupPull.md @@ -1,6 +1,6 @@ ## General Information -The traversable `Okta_GroupPull` edges represent the group synchronization relationships from applications to Okta: +The traversable Okta_GroupPull edges represent the group synchronization relationships from applications to Okta: ```mermaid graph LR diff --git a/descriptions/edges/Okta_GroupPush.md b/descriptions/edges/Okta_GroupPush.md index c0ae5f8..e5b283b 100644 --- a/descriptions/edges/Okta_GroupPush.md +++ b/descriptions/edges/Okta_GroupPush.md @@ -1,11 +1,10 @@ ## General Information -The non-traversable `Okta_GroupPush` edges represent the group push assignments to applications. -This indicates group provisioning and membership synchronization from Okta to external applications. +The non-traversable Okta_GroupPush edges represent the group push assignments to applications. This indicates group provisioning and membership synchronization from Okta to external applications. ```mermaid graph LR g1("Okta_Group Engineering") app1("Okta_Application contoso.com") - g1 -- Okta_GroupPush --> app1 + g1 -. Okta_GroupPush .-> app1 ``` diff --git a/descriptions/edges/Okta_HasRole.md b/descriptions/edges/Okta_HasRole.md index b228c0e..837deb8 100644 --- a/descriptions/edges/Okta_HasRole.md +++ b/descriptions/edges/Okta_HasRole.md @@ -1,6 +1,6 @@ ## General Information -The non-traversable `Okta_HasRole` edges represent the role assignments for users in Okta: +The non-traversable Okta_HasRole edges represent the role assignments for users in Okta: ```mermaid graph LR @@ -14,5 +14,5 @@ graph LR g1 -. Okta_HasRole .-> r1 g1 -. Okta_HasRole .-> r2 a1 -. Okta_HasRole .-> r2 - u2 -. Okta_MemberOf .-> g1 + u2 -- Okta_MemberOf --> g1 ``` diff --git a/descriptions/edges/Okta_HasRoleAssignment.md b/descriptions/edges/Okta_HasRoleAssignment.md index 6d11d49..3274acb 100644 --- a/descriptions/edges/Okta_HasRoleAssignment.md +++ b/descriptions/edges/Okta_HasRoleAssignment.md @@ -1,7 +1,6 @@ ## General Information -The `Okta_HasRoleAssignment` edges connect users, groups, and applications to their respective `Okta_RoleAssignment` nodes. -The `Okta_ScopedTo` edges connect the `Okta_RoleAssignment` nodes to the resources they are scoped to, such as the organization or specific groups or applications. +The Okta_HasRoleAssignment edges connect users, groups, and applications to their respective Okta_RoleAssignment nodes. The Okta_ScopedTo edges connect the Okta_RoleAssignment nodes to the resources they are scoped to, such as the organization or specific groups or applications. ```mermaid graph TB @@ -21,7 +20,7 @@ graph TB g1 -. Okta_HasRole .-> r1 g1 -- Okta_HelpDeskAdmin --> u3 u3 -- Okta_MemberOf --> g2 - ra1 -- Okta_ScopedTo --> g2 + ra1 -. Okta_ScopedTo .-> g2 u2 -. Okta_HasRoleAssignment .-> ra2 ra2 -. Okta_ScopedTo .-> org u2 -- Okta_SuperAdmin --> org diff --git a/descriptions/edges/Okta_HelpDeskAdmin.md b/descriptions/edges/Okta_HelpDeskAdmin.md index 22ebb91..08d3859 100644 --- a/descriptions/edges/Okta_HelpDeskAdmin.md +++ b/descriptions/edges/Okta_HelpDeskAdmin.md @@ -1,7 +1,6 @@ ## General Information -The traversable `Okta_HelpDeskAdmin` edges represent Help Desk Administrator role assignments. -Help Desk Administrators can perform password resets, unlock accounts, and reset MFA factors for users within their assigned scope. +The traversable Okta_HelpDeskAdmin edges represent Help Desk Administrator role assignments. Help Desk Administrators can perform password resets, unlock accounts, and reset MFA factors for users within their assigned scope. ```mermaid graph LR diff --git a/descriptions/edges/Okta_HostsAgent.md b/descriptions/edges/Okta_HostsAgent.md index dfd9bc7..5a62cc5 100644 --- a/descriptions/edges/Okta_HostsAgent.md +++ b/descriptions/edges/Okta_HostsAgent.md @@ -1,6 +1,6 @@ ## General Information -Hybrid `Okta_HostsAgent` edges connect an AD `Computer` node to the `Okta_Agent` running on that host. +Hybrid Okta_HostsAgent edges connect an AD Computer node to the Okta_Agent running on that host. ```mermaid graph LR diff --git a/descriptions/edges/Okta_IdentityProviderFor.md b/descriptions/edges/Okta_IdentityProviderFor.md index b3836ae..80038dd 100644 --- a/descriptions/edges/Okta_IdentityProviderFor.md +++ b/descriptions/edges/Okta_IdentityProviderFor.md @@ -1,6 +1,6 @@ ## General Information -The traversable `Okta_IdentityProviderFor` edges represent the relationships between identity providers and the users who authenticate through them: +The traversable Okta_IdentityProviderFor edges represent the relationships between identity providers and the users who authenticate through them: ```mermaid graph LR diff --git a/descriptions/edges/Okta_IdpGroupAssignment.md b/descriptions/edges/Okta_IdpGroupAssignment.md index fbc9719..5b8bf78 100644 --- a/descriptions/edges/Okta_IdpGroupAssignment.md +++ b/descriptions/edges/Okta_IdpGroupAssignment.md @@ -1,6 +1,6 @@ ## General Information -The non-traversable `Okta_IdpGroupAssignment` edges represent groups automatically assigned to users based on identity provider attributes or user claims: +The non-traversable Okta_IdpGroupAssignment edges represent groups automatically assigned to users based on identity provider attributes or user claims: ```mermaid graph LR @@ -8,7 +8,7 @@ graph LR g1("Okta_Group Contractors") g2("Okta_Group Employees") g3("Okta_Group Entra ID Users") - idp1 -- Okta_IdpGroupAssignment --> g1 - idp1 -- Okta_IdpGroupAssignment --> g2 - idp1 -- Okta_IdpGroupAssignment --> g3 + idp1 -. Okta_IdpGroupAssignment .-> g1 + idp1 -. Okta_IdpGroupAssignment .-> g2 + idp1 -. Okta_IdpGroupAssignment .-> g3 ``` diff --git a/descriptions/edges/Okta_InboundOrgSSO.md b/descriptions/edges/Okta_InboundOrgSSO.md index 793a8a0..6f7b9fa 100644 --- a/descriptions/edges/Okta_InboundOrgSSO.md +++ b/descriptions/edges/Okta_InboundOrgSSO.md @@ -1,6 +1,6 @@ ## General Information -The `Okta_InboundOrgSSO` and `Okta_InboundSSO` hybrid edges connect external tenants and users to Okta entities: +The Okta_InboundOrgSSO and Okta_InboundSSO hybrid edges connect external tenants and users to Okta entities: ```mermaid graph LR diff --git a/descriptions/edges/Okta_InboundSSO.md b/descriptions/edges/Okta_InboundSSO.md index 793a8a0..6f7b9fa 100644 --- a/descriptions/edges/Okta_InboundSSO.md +++ b/descriptions/edges/Okta_InboundSSO.md @@ -1,6 +1,6 @@ ## General Information -The `Okta_InboundOrgSSO` and `Okta_InboundSSO` hybrid edges connect external tenants and users to Okta entities: +The Okta_InboundOrgSSO and Okta_InboundSSO hybrid edges connect external tenants and users to Okta entities: ```mermaid graph LR diff --git a/descriptions/edges/Okta_KerberosSSO.md b/descriptions/edges/Okta_KerberosSSO.md index 8b8ca08..25b9182 100644 --- a/descriptions/edges/Okta_KerberosSSO.md +++ b/descriptions/edges/Okta_KerberosSSO.md @@ -1,6 +1,6 @@ ## General Information -Hybrid traversable `Okta_KerberosSSO` edges represent [agentless desktop SSO](https://help.okta.com/en-us/content/topics/directory/ad-dsso-about-workflow.htm) trust from an on-prem AD `User` account to an AD-backed `Okta_Application`. +Hybrid traversable Okta_KerberosSSO edges represent [agentless desktop SSO](https://help.okta.com/en-us/content/topics/directory/ad-dsso-about-workflow.htm) trust from an on-prem AD User account to an AD-backed Okta_Application. ```mermaid graph LR diff --git a/descriptions/edges/Okta_KeyOf.md b/descriptions/edges/Okta_KeyOf.md index 3f6c110..973c9d4 100644 --- a/descriptions/edges/Okta_KeyOf.md +++ b/descriptions/edges/Okta_KeyOf.md @@ -1,10 +1,10 @@ ## General Information -The traversable `Okta_KeyOf` edges represent the relationships between applications ([Okta_Application](../Nodes/Okta_Application.md)) and their JWKs: +The traversable Okta_KeyOf edges represent the relationships between applications Okta_Application and their JWKs: ```mermaid graph LR - app1("Okta_Application OktaHound Collector") + app1("Okta_Application OpenHound Okta Collector") app2("Okta_Application Security Scanner") key1("Okta_JWK ABC123") key2("Okta_JWK DEF456") @@ -14,5 +14,4 @@ graph LR key3 -- Okta_KeyOf --> app2 ``` -Possession of the private key corresponding to a JWK allows an attacker to authenticate as the application. -The `Okta_KeyOf` edge can be used in BloodHound to understand which applications use JWK-based authentication and trace potential attack paths involving compromised private keys. +Possession of the private key corresponding to a JWK allows an attacker to authenticate as the application. The Okta_KeyOf edge can be used in BloodHound to understand which applications use JWK-based authentication and trace potential attack paths involving compromised private keys. diff --git a/descriptions/edges/Okta_ManageApp.md b/descriptions/edges/Okta_ManageApp.md index fec936f..bfc9659 100644 --- a/descriptions/edges/Okta_ManageApp.md +++ b/descriptions/edges/Okta_ManageApp.md @@ -1,7 +1,6 @@ ## General Information -The traversable `Okta_ManageApp` edges correspond to the `okta.apps.manage` custom role permissions -that allow a principal (user, group, or application) to fully manage Okta applications and their members. +The traversable Okta_ManageApp edges correspond to the `okta.apps.manage` custom role permissions that allow a principal (user, group, or application) to fully manage Okta applications and their members. ```mermaid graph LR diff --git a/descriptions/edges/Okta_ManagerOf.md b/descriptions/edges/Okta_ManagerOf.md index 91ec27c..f513883 100644 --- a/descriptions/edges/Okta_ManagerOf.md +++ b/descriptions/edges/Okta_ManagerOf.md @@ -2,10 +2,9 @@ Okta uses the `Manager` and `ManagerId` user profile attributes to represent managerial relationships. Unfortunately, these attributes can have any arbitrary value and their referential integrity is not enforced by Okta. They are not even synchronized from external directories by default. -Our recommendation is to map the `ManagerId` attribute to the login of the manager in Okta. When synchronizing users from Active Directory, -the `getManagerUser("active_directory").login` mapping expression can be used to achieve this. Such values are automatically recognized by `OktaHound`. +Our recommendation is to map the `ManagerId` attribute to the login of the manager in Okta. When synchronizing users from Active Directory, the `getManagerUser("active_directory").login` mapping expression can be used to achieve this. Such values are automatically recognized by the OpenHound Okta collector. -The **non-traversable** `Okta_ManagerOf` edges represent the organizational structure in BloodHound: +The **non-traversable** Okta_ManagerOf edges represent the organizational structure in BloodHound: ```mermaid graph LR diff --git a/descriptions/edges/Okta_MemberOf.md b/descriptions/edges/Okta_MemberOf.md index 6bf8471..765a9e8 100644 --- a/descriptions/edges/Okta_MemberOf.md +++ b/descriptions/edges/Okta_MemberOf.md @@ -1,6 +1,6 @@ ## General Information -The traversable `Okta_MemberOf` edges represent the membership relationships between users and groups in Okta: +The traversable Okta_MemberOf edges represent the membership relationships between users and groups in Okta: ```mermaid graph LR diff --git a/descriptions/edges/Okta_MembershipSync.md b/descriptions/edges/Okta_MembershipSync.md index a1a7eab..601ccdd 100644 --- a/descriptions/edges/Okta_MembershipSync.md +++ b/descriptions/edges/Okta_MembershipSync.md @@ -1,6 +1,6 @@ ## General Information -The traversable hybrid `Okta_MembershipSync` edges represent the synchronization relationships between groups in external directories and their corresponding groups in Okta: +The traversable hybrid Okta_MembershipSync edges represent the synchronization relationships between groups in external directories and their corresponding groups in Okta: ```mermaid graph TB diff --git a/descriptions/edges/Okta_MobileAdmin.md b/descriptions/edges/Okta_MobileAdmin.md index 7dba2cb..74981c5 100644 --- a/descriptions/edges/Okta_MobileAdmin.md +++ b/descriptions/edges/Okta_MobileAdmin.md @@ -1,7 +1,6 @@ ## General Information -The traversable `Okta_MobileAdmin` edges represent Mobile Administrator role assignments. -Mobile Administrators can manage mobile device settings and configurations within their assigned scope. +The traversable Okta_MobileAdmin edges represent Mobile Administrator role assignments. Mobile Administrators can manage mobile device settings and configurations within their assigned scope. ```mermaid graph LR diff --git a/descriptions/edges/Okta_OrgAdmin.md b/descriptions/edges/Okta_OrgAdmin.md index 4d8e3e4..8d44587 100644 --- a/descriptions/edges/Okta_OrgAdmin.md +++ b/descriptions/edges/Okta_OrgAdmin.md @@ -1,7 +1,6 @@ ## General Information -The traversable `Okta_OrgAdmin` edges represent Organization Administrator role assignments. -Organization Administrators can manage most organizational settings except for administrative role assignments and some security settings. +The traversable Okta_OrgAdmin edges represent Organization Administrator role assignments. Organization Administrators can manage most organizational settings except for administrative role assignments and some security settings. ```mermaid graph LR diff --git a/descriptions/edges/Okta_OrgSWA.md b/descriptions/edges/Okta_OrgSWA.md index 894206b..e736109 100644 --- a/descriptions/edges/Okta_OrgSWA.md +++ b/descriptions/edges/Okta_OrgSWA.md @@ -1,21 +1,20 @@ ## General Information -The non-traversable `Okta_OrgSWA` edges represent the Secure Web Authentication (SWA) relationships between Okta applications and supported external organizations or tenants. SWA stores user credentials in Okta and automatically fills them in when users access the application, which is less secure than federated SSO protocols. +The non-traversable Okta_OrgSWA edges represent the Secure Web Authentication (SWA) relationships between Okta applications and supported external organizations or tenants. SWA stores user credentials in Okta and automatically fills them in when users access the application, which is less secure than federated SSO protocols. ```mermaid graph LR - subgraph okta["OktaHound"] + subgraph okta["OpenHound Okta"] direction TB o("Okta_Organization contoso.okta.com") app1("Okta_Application Jamf Pro SWA") o -- Okta_Contains --> app1 end - subgraph "JamfHound" + subgraph "Jamf" direction TB jamf("jamf_SSOIntegration contoso.jamfcloud.com-SSO") app1 -. Okta_OrgSWA .-> jamf end ``` -The respective BloodHound collectors, e.g., `GitHound` for GitHub organizations and `JamfHound` for Jamf Pro tenants, -must be used to gather the external node information. +The respective BloodHound collectors, e.g., OpenHound Github for GitHub organizations and OpenHound Jamf for Jamf Pro tenants, must be used to gather the external node information. diff --git a/descriptions/edges/Okta_OutboundOrgSSO.md b/descriptions/edges/Okta_OutboundOrgSSO.md index 0e70d61..b8af108 100644 --- a/descriptions/edges/Okta_OutboundOrgSSO.md +++ b/descriptions/edges/Okta_OutboundOrgSSO.md @@ -1,10 +1,10 @@ ## General Information -The traversable `Okta_OutboundOrgSSO` edges represent the Single Sign-On (SSO) relationships between Okta applications and supported external organizations or tenants, such as GitHub Enterprise or Jamf Pro, using SAML 2.0 or OIDC protocols. +The traversable Okta_OutboundOrgSSO edges represent the Single Sign-On (SSO) relationships between Okta applications and supported external organizations or tenants, such as GitHub Enterprise or Jamf Pro, using SAML 2.0 or OIDC protocols. ```mermaid graph LR - subgraph okta["OktaHound"] + subgraph okta["OpenHound Okta"] direction TB o("Okta_Organization contoso.okta.com") app1("Okta_Application GitHub Enterprise Cloud") @@ -12,17 +12,16 @@ graph LR o -- Okta_Contains --> app1 o -- Okta_Contains --> app2 end - subgraph "GitHound" + subgraph "GitHub" direction TB ghorg("GH_Organization Contoso") app1 -- Okta_OutboundOrgSSO --> ghorg end - subgraph "JamfHound" + subgraph "Jamf" direction TB jamf("jamf_SSOIntegration contoso.jamfcloud.com-SSO") app2 -- Okta_OutboundOrgSSO --> jamf end ``` -The respective BloodHound collectors, e.g., `GitHound` for GitHub organizations and `JamfHound` for Jamf Pro tenants, -must be used to gather the external node information. +The respective BloodHound collectors, e.g., OpenHound Github for GitHub organizations and OpenHound Jamf for Jamf Pro tenants, must be used to gather the external node information. diff --git a/descriptions/edges/Okta_OutboundSSO.md b/descriptions/edges/Okta_OutboundSSO.md index 3c4696e..60698f8 100644 --- a/descriptions/edges/Okta_OutboundSSO.md +++ b/descriptions/edges/Okta_OutboundSSO.md @@ -1,6 +1,6 @@ ## General Information -The traversable hybrid `Okta_OutboundSSO` edges represent Single Sign-On relationships between Okta users and their linked accounts in external applications using federated authentication (SAML 2.0 or OIDC). +The traversable hybrid Okta_OutboundSSO edges represent Single Sign-On relationships between Okta users and their linked accounts in external applications using federated authentication (SAML 2.0 or OIDC). ```mermaid graph LR diff --git a/descriptions/edges/Okta_PasswordSync.md b/descriptions/edges/Okta_PasswordSync.md index cda202c..0a599ce 100644 --- a/descriptions/edges/Okta_PasswordSync.md +++ b/descriptions/edges/Okta_PasswordSync.md @@ -1,11 +1,28 @@ ## General Information -The traversable `Okta_PasswordSync` edge represents password synchronization between Okta users across organizations in Org2Org setups. -This indicates that credentials are synchronized from a source Okta user to a target Okta user. +The traversable Okta_PasswordSync edge represents password synchronization between user accounts. This indicates that credentials are synchronized from a source user to a target user. -> ![WARNING] +In **Active Directory** hybrid setups, this edge is created between User (AD) and Okta_User when delegated authentication or password push is enabled. In **Org2Org** setups, this edge is created between Okta_User nodes across organizations when password synchronization is configured. + +> [!WARNING] > The Okta API does not indicate if the actual password or a randomly generated value is pushed to the other organization. +### Active Directory Hybrid + +```mermaid +graph LR + subgraph ad["Active Directory"] + adu1("User john\@contoso.com") + end + subgraph okta["Okta"] + u1("Okta_User john\@contoso.com") + adu1 -->|Okta_PasswordSync| u1 + adu1 .->|Okta_UserSync| u1 + end +``` + +### Org2Org + ```mermaid graph LR subgraph source_org["Okta Org Contoso"] diff --git a/descriptions/edges/Okta_PolicyMapping.md b/descriptions/edges/Okta_PolicyMapping.md index f6b8a51..479fe95 100644 --- a/descriptions/edges/Okta_PolicyMapping.md +++ b/descriptions/edges/Okta_PolicyMapping.md @@ -1,9 +1,9 @@ ## General Information -The non-traversable `Okta_PolicyMapping` edges represent the association between a policy and the resources to which it is applied. +The non-traversable Okta_PolicyMapping edges represent the association between a policy and the resources to which it is applied. -> [!WARNING] -> Only application targets are currently supported by `OktaHound`. +> [!NOTE] +> Only application targets are supported in the current version of the Okta BloodHound extension. ```mermaid graph LR diff --git a/descriptions/edges/Okta_ReadClientSecret.md b/descriptions/edges/Okta_ReadClientSecret.md index fd05e26..c342a9f 100644 --- a/descriptions/edges/Okta_ReadClientSecret.md +++ b/descriptions/edges/Okta_ReadClientSecret.md @@ -1,9 +1,6 @@ ## General Information -The traversable `Okta_ReadClientSecret` edges represent permissions that allow a principal (user, group, or application) -to read OAuth client secrets for scoped Okta applications. -These edges are created for the **Application Administrator**, **API Access Management Administrator**, and **Read-only Administrator** built-in roles -and for custom roles with the `okta.apps.clientCredentials.read` permission. +The traversable Okta_ReadClientSecret edges represent permissions that allow a principal (user, group, or application) to read OAuth client secrets for scoped Okta applications. These edges are created for the **Application Administrator**, **API Access Management Administrator**, and **Read-only Administrator** built-in roles and for custom roles with the `okta.apps.clientCredentials.read` permission. ```mermaid graph TD @@ -22,5 +19,4 @@ graph TD ## Potential Attack Scenarios -An attacker with the ability to read client secrets for an application assigned the Super Administrator role -could potentially use the client secret to authenticate as that application and perform privileged actions in Okta. +An attacker with the ability to read client secrets for an application assigned the Super Administrator role could potentially use the client secret to authenticate as that application and perform privileged actions in Okta. diff --git a/descriptions/edges/Okta_ReadPasswordUpdates.md b/descriptions/edges/Okta_ReadPasswordUpdates.md index 79768cf..1b59954 100644 --- a/descriptions/edges/Okta_ReadPasswordUpdates.md +++ b/descriptions/edges/Okta_ReadPasswordUpdates.md @@ -1,6 +1,6 @@ ## General Information -The traversable `Okta_ReadPasswordUpdates` edges represent applications that can read password updates over SCIM. +The traversable Okta_ReadPasswordUpdates edges represent applications that can read password updates over SCIM. ```mermaid graph LR diff --git a/descriptions/edges/Okta_RealmContains.md b/descriptions/edges/Okta_RealmContains.md index 7ddf8f0..ced9746 100644 --- a/descriptions/edges/Okta_RealmContains.md +++ b/descriptions/edges/Okta_RealmContains.md @@ -1,6 +1,6 @@ ## General Information -The traversable `Okta_RealmContains` edges represent containment relationships between realms and the users assigned to those realms. +The traversable Okta_RealmContains edges represent containment relationships between realms and the users assigned to those realms. ```mermaid graph LR @@ -14,5 +14,5 @@ graph LR r2 -- Okta_RealmContains --> u3 ``` -> [!WARNING] -> Okta Realms are currently not supported by `OktaHound` due to licensing restrictions. +> [!NOTE] +> Okta Realms are currently not supported by BloodHound due to licensing restrictions. diff --git a/descriptions/edges/Okta_ResetFactors.md b/descriptions/edges/Okta_ResetFactors.md index 71932f9..177206f 100644 --- a/descriptions/edges/Okta_ResetFactors.md +++ b/descriptions/edges/Okta_ResetFactors.md @@ -1,7 +1,6 @@ ## General Information -The traversable `Okta_ResetFactors` edges represent custom role permissions that allow a principal to reset MFA authenticators -for scoped Okta users. These edges are created when a custom role includes the `okta.users.credentials.resetFactors` or `okta.users.credentials.manage` permissions. +The traversable Okta_ResetFactors edges represent custom role permissions that allow a principal to reset MFA authenticators for scoped Okta users. These edges are created when a custom role includes the `okta.users.credentials.resetFactors` or `okta.users.credentials.manage` permissions. ```mermaid graph LR diff --git a/descriptions/edges/Okta_ResetPassword.md b/descriptions/edges/Okta_ResetPassword.md index d0dc9ab..4d8933e 100644 --- a/descriptions/edges/Okta_ResetPassword.md +++ b/descriptions/edges/Okta_ResetPassword.md @@ -1,9 +1,6 @@ ## General Information -The traversable `Okta_ResetPassword` edges represent custom role permissions that allow a principal (user, group, or application) -to reset passwords or temporary credentials for scoped Okta users. -These edges are created when a custom role includes -password management permissions such as `okta.users.credentials.resetPassword`, `okta.users.credentials.manage`, `okta.users.credentials.manageTemporaryAccessCode`, or `okta.users.manage`. +The traversable Okta_ResetPassword edges represent custom role permissions that allow a principal (user, group, or application) to reset passwords or temporary credentials for scoped Okta users. These edges are created when a custom role includes password management permissions such as `okta.users.credentials.resetPassword`, `okta.users.credentials.manage`, `okta.users.credentials.manageTemporaryAccessCode`, or `okta.users.manage`. ```mermaid graph LR @@ -15,3 +12,22 @@ graph LR g1 -- Okta_ResetFactors --> u2 app1 -- Okta_ResetPassword --> u1 ``` + +The edge is calculated based on custom role scoping. + +```mermaid +graph TD + u1("Okta_User john\@contoso.com") + u2("Okta_User alice\@contoso.com") + g1("Okta_Group Help Desk") + rs("Okta_ResourceSet Frontline Workers") + a("Okta_RoleAssignment Authentication Admins") + r("Okta_CustomRole Authentication Admins") + g1 -. Okta_HasRole .-> r + a -. Okta_ScopedTo .-> rs + g1 -. Okta_HasRoleAssignment .-> a + rs -- Okta_ResourceSetContains --> u2 + u1 -- Okta_MemberOf --> g1 + g1 -- Okta_ResetPassword --> u2 + g1 -- Okta_ResetFactors --> u2 +``` diff --git a/descriptions/edges/Okta_ResourceSetContains.md b/descriptions/edges/Okta_ResourceSetContains.md index 434982a..5520494 100644 --- a/descriptions/edges/Okta_ResourceSetContains.md +++ b/descriptions/edges/Okta_ResourceSetContains.md @@ -1,6 +1,6 @@ ## General Information -The traversable `Okta_ResourceSetContains` edges represent the membership relationships between resource sets and their member entities in Okta: +The traversable Okta_ResourceSetContains edges represent the membership relationships between resource sets and their member entities in Okta: ```mermaid graph LR @@ -11,12 +11,11 @@ graph LR a1("Okta_Application GitHub") d1("Okta_Device John's MacBook") rs1 -- Okta_ResourceSetContains --> u1 - rs1 -. Okta_ResourceSetContains .-> g1 + rs1 -- Okta_ResourceSetContains --> g1 rs1 -- Okta_ResourceSetContains --> a1 rs1 -- Okta_ResourceSetContains --> d1 u2 -- Okta_MemberOf --> g1 rs1 -- Okta_ResourceSetContains --> u2 ``` -Note that users can also be members of resource sets indirectly through group memberships. -The intermediate group will not appear in the graph, but the user membership will be resolved by `OktaHound`. +Note that users can also be members of resource sets indirectly through group memberships. The intermediate group will not appear in the graph, but the user membership will be resolved by the collector. diff --git a/descriptions/edges/Okta_SWA.md b/descriptions/edges/Okta_SWA.md index 20d817a..965281f 100644 --- a/descriptions/edges/Okta_SWA.md +++ b/descriptions/edges/Okta_SWA.md @@ -1,6 +1,6 @@ ## General Information -The non-traversable hybrid `Okta_SWA` edges represent Secure Web Authentication relationships between Okta users and their linked accounts in external applications. SWA stores user credentials in Okta and automatically fills them in, which is less secure than federated SSO. +The non-traversable hybrid Okta_SWA edges represent Secure Web Authentication relationships between Okta users and their linked accounts in external applications. SWA stores user credentials in Okta and automatically fills them in, which is less secure than federated SSO. ```mermaid graph LR diff --git a/descriptions/edges/Okta_ScopedTo.md b/descriptions/edges/Okta_ScopedTo.md index 6d11d49..3274acb 100644 --- a/descriptions/edges/Okta_ScopedTo.md +++ b/descriptions/edges/Okta_ScopedTo.md @@ -1,7 +1,6 @@ ## General Information -The `Okta_HasRoleAssignment` edges connect users, groups, and applications to their respective `Okta_RoleAssignment` nodes. -The `Okta_ScopedTo` edges connect the `Okta_RoleAssignment` nodes to the resources they are scoped to, such as the organization or specific groups or applications. +The Okta_HasRoleAssignment edges connect users, groups, and applications to their respective Okta_RoleAssignment nodes. The Okta_ScopedTo edges connect the Okta_RoleAssignment nodes to the resources they are scoped to, such as the organization or specific groups or applications. ```mermaid graph TB @@ -21,7 +20,7 @@ graph TB g1 -. Okta_HasRole .-> r1 g1 -- Okta_HelpDeskAdmin --> u3 u3 -- Okta_MemberOf --> g2 - ra1 -- Okta_ScopedTo --> g2 + ra1 -. Okta_ScopedTo .-> g2 u2 -. Okta_HasRoleAssignment .-> ra2 ra2 -. Okta_ScopedTo .-> org u2 -- Okta_SuperAdmin --> org diff --git a/descriptions/edges/Okta_SecretOf.md b/descriptions/edges/Okta_SecretOf.md index 0232074..1e57807 100644 --- a/descriptions/edges/Okta_SecretOf.md +++ b/descriptions/edges/Okta_SecretOf.md @@ -1,6 +1,6 @@ ## General Information -The traversable `Okta_SecretOf` edges represent the relationship between service applications or API service integrations and their associated client secrets, represented by the [Okta_ClientSecret](../Nodes/Okta_ClientSecret.md) nodes. +The traversable Okta_SecretOf edges represent the relationship between service applications or API service integrations and their associated client secrets, represented by the Okta_ClientSecret nodes. ```mermaid graph LR diff --git a/descriptions/edges/Okta_SuperAdmin.md b/descriptions/edges/Okta_SuperAdmin.md index 4d85c59..0a602e9 100644 --- a/descriptions/edges/Okta_SuperAdmin.md +++ b/descriptions/edges/Okta_SuperAdmin.md @@ -1,7 +1,6 @@ ## General Information -The traversable `Okta_SuperAdmin` edges represent Super Administrator role assignments to the Okta organization. -Super Administrators have full access to all features and settings in the Okta organization. +The traversable Okta_SuperAdmin edges represent Super Administrator role assignments to the Okta organization. Super Administrators have full access to all features and settings in the Okta organization. ```mermaid graph LR diff --git a/descriptions/edges/Okta_UserPull.md b/descriptions/edges/Okta_UserPull.md index 861b681..7f6b10d 100644 --- a/descriptions/edges/Okta_UserPull.md +++ b/descriptions/edges/Okta_UserPull.md @@ -1,12 +1,12 @@ ## General Information -The `Okta_UserPull` edges represent user import relationships from external applications to Okta. +The Okta_UserPull edges represent user import relationships from external applications to Okta. ```mermaid graph LR app1("Okta_Application Workday") u1("Okta_User john\@contoso.com") u2("Okta_User alice\@contoso.com") - app1 -- Okta_UserPull --> u1 - app1 -- Okta_UserPull --> u2 + app1 -. Okta_UserPull .-> u1 + app1 -. Okta_UserPull .-> u2 ``` diff --git a/descriptions/edges/Okta_UserPush.md b/descriptions/edges/Okta_UserPush.md index 2483386..024455f 100644 --- a/descriptions/edges/Okta_UserPush.md +++ b/descriptions/edges/Okta_UserPush.md @@ -1,6 +1,6 @@ ## General Information -The non-traversable `Okta_UserPush` edges represent user provisioning relationships from Okta to external applications. When configured, Okta can automatically create, update, or deactivate user accounts in integrated applications using protocols like SCIM or LDAP. +The non-traversable Okta_UserPush edges represent user provisioning relationships from Okta to external applications. When configured, Okta can automatically create, update, or deactivate user accounts in integrated applications using protocols like SCIM or LDAP. ```mermaid graph LR diff --git a/descriptions/edges/Okta_UserSync.md b/descriptions/edges/Okta_UserSync.md index 55b8ecf..3ea406c 100644 --- a/descriptions/edges/Okta_UserSync.md +++ b/descriptions/edges/Okta_UserSync.md @@ -1,6 +1,6 @@ ## General Information -The non-traversable hybrid `Okta_UserSync` edges represent bidirectional user synchronization relationships between Okta and external directories or applications. These edges indicate that user accounts are linked and synchronized between systems. +The non-traversable hybrid Okta_UserSync edges represent bidirectional user synchronization relationships between Okta and external directories or applications. These edges indicate that user accounts are linked and synchronized between systems. ```mermaid graph LR diff --git a/descriptions/nodes/Okta_Agent.md b/descriptions/nodes/Okta_Agent.md index f8e0643..7018d4d 100644 --- a/descriptions/nodes/Okta_Agent.md +++ b/descriptions/nodes/Okta_Agent.md @@ -1,7 +1,6 @@ ## Overview -The `Okta_Agent` node represents an Okta Agent, which is a component used in Okta's integration with on-premises systems. -Okta Agents facilitate communication between the Okta cloud and on-premises applications or directories, enabling features such as single sign-on (SSO) and user provisioning. +The Okta_Agent node represents an Okta Agent, which is a component used in Okta's integration with on-premises systems. Okta Agents facilitate communication between the Okta cloud and on-premises applications or directories, enabling features such as single sign-on (SSO) and user provisioning. One or more agents are grouped into Agent Pools, represented by the [Okta_AgentPool](Okta_AgentPool.md) nodes, to provide redundancy and load balancing. diff --git a/descriptions/nodes/Okta_AgentPool.md b/descriptions/nodes/Okta_AgentPool.md index 7540e34..17016c8 100644 --- a/descriptions/nodes/Okta_AgentPool.md +++ b/descriptions/nodes/Okta_AgentPool.md @@ -1,6 +1,6 @@ ## Overview -The `Okta_AgentPool` nodes represent Okta Agent Pools, which are collections of Okta Agents (represented as [Okta_Agent](Okta_Agent.md) nodes) that work together to provide high availability and load balancing for on-premises integrations. +The Okta_AgentPool nodes represent Okta Agent Pools, which are collections of Okta Agents (represented as [Okta_Agent](Okta_Agent.md) nodes) that work together to provide high availability and load balancing for on-premises integrations. The following agent pool types are supported by Okta: diff --git a/descriptions/nodes/Okta_ApiServiceIntegration.md b/descriptions/nodes/Okta_ApiServiceIntegration.md index 9543632..b155b99 100644 --- a/descriptions/nodes/Okta_ApiServiceIntegration.md +++ b/descriptions/nodes/Okta_ApiServiceIntegration.md @@ -11,7 +11,7 @@ API service integrations in Okta represent OAuth 2.0 service (daemon) applicatio | Support authentication using private keys: | ✅ | ❌ | | Admins can read cleartext client secrets: | ✅ | ❌ | -In `OktaHound`, API service integrations are represented as `Okta_ApiServiceIntegration` nodes. +Okta API service integrations are represented as Okta_ApiServiceIntegration nodes. ## Integration OAuth 2.0 Scopes diff --git a/descriptions/nodes/Okta_ApiToken.md b/descriptions/nodes/Okta_ApiToken.md index ff940a7..284bacc 100644 --- a/descriptions/nodes/Okta_ApiToken.md +++ b/descriptions/nodes/Okta_ApiToken.md @@ -6,4 +6,4 @@ These tokens are always associated with a specific user in Okta, and the permiss The use of API tokens is generally discouraged in favor of OAuth 2.0 access tokens, as they provide better security and flexibility. However, API tokens are still widely used by Okta customers. -In `OktaHound`, API tokens are represented as `Okta_ApiToken` nodes. +Okta API tokens are represented as Okta_ApiToken nodes in BloodHound. diff --git a/descriptions/nodes/Okta_Application.md b/descriptions/nodes/Okta_Application.md index 0cba845..91ea5e3 100644 --- a/descriptions/nodes/Okta_Application.md +++ b/descriptions/nodes/Okta_Application.md @@ -4,7 +4,7 @@ Applications in Okta represent the various software applications and services th With the exception of API Service applications, Okta users and groups can be assigned to applications. Users can also be synchronized TO and FROM applications in Okta, typically using the SCIM protocol. For example, when integrating with GitHub Enterprise Cloud, Okta can be configured to automatically create user accounts in GitHub when users are assigned to the GitHub application in Okta. -In `OktaHound`, applications are represented as `Okta_Application` nodes. +Okta applications are represented as Okta_Application nodes. ## User Name Mapping @@ -32,8 +32,7 @@ This application type is the most interesting one from the security perspective, ## Hybrid Edges -For supported systems like Active Directory, GitHub Enterprise Cloud, or Jamf Pro, -OktaHound can create hybrid edges in BloodHound to represent the relationships between these external systems and Okta. +For supported systems like Active Directory, GitHub Enterprise Cloud, or Jamf Pro, OpenHound can create hybrid edges in BloodHound to represent the relationships between these external systems and Okta. ```mermaid graph TB @@ -61,8 +60,8 @@ graph TB org -- Okta_Contains --> g1 u1 -- Okta_MemberOf --> g1 u2 -- Okta_AppAdmin --> gha - g1 -- Okta_AppAssignment --> gha - u1 -- Okta_AppAssignment --> jmfa + g1 -. Okta_AppAssignment .-> gha + u1 -. Okta_AppAssignment .-> jmfa end subgraph gh["GitHub Enterprise Cloud"] direction LR @@ -75,11 +74,100 @@ graph TB jamft("jamf_SSOIntegration contoso.jamfcloud.com-SSO") jmfu1("jamf_Account john\@contoso.com") end - adu1 -- Okta_UserSync --> u1 - adu2 -- Okta_UserSync --> u2 + adu1 -. Okta_UserSync .-> u1 + adu2 -. Okta_UserSync .-> u2 adg1 -- Okta_MembershipSync --> g1 gha -- Okta_OutboundOrgSSO --> ghorg jmfa -- Okta_OutboundOrgSSO --> jamft u1 -- Okta_OutboundSSO --> ghu1 u1 -- Okta_OutboundSSO --> jmfu1 ``` + +### Active Directory Synchronization + +When Okta's Active Directory (AD) integration is configured for user and group synchronization, the connected AD domain is represented as an Okta_Application node in BloodHound. This allows you to visualize the AD-backed application alongside other applications in your Okta environment and understand its relationships with users, groups, and roles. + +The synchronization is performed by domain-joined servers with the Okta AD Agent installed. This agent typically has Domain Admin privileges in the connected AD domain to perform user and group enumeration and synchronization, making it a high-value target for attackers. + +![Okta AD agent settings](../Images/okta-ad-agent.png) + +Authentication can be delegated from Okta to AD in multiple ways: + +- [Agentless Desktop SSO](https://help.okta.com/oie/en-us/content/topics/directory/ad-dsso-about-workflow.htm) +- [Password Synchronization](https://help.okta.com/oie/en-us/content/topics/directory/installing_configuring_active_directory_password_sync_agent.htm) +- Active Directory Federation Services (ADFS) integration with Okta as a SAML IdP + +> [!NOTE] +> There is no documented API available to determine the authentication delegation method(s) configured for an AD-backed Okta application. The collector therefore performs some heuristics that might not be 100% accurate in all cases. + +### GitHub Enterprise Cloud Organizations + +When integrating Okta with GitHub Enterprise Cloud, each GitHub organization connected to Okta is represented as a separate Okta_Application node in BloodHound. + +![Properties of the GitHub Application node](../Images/bloodhound-github-properties.png) + +### Jamf Pro + +When integrating Okta with Jamf Pro using SAML 2.0, each Jamf Pro instance connected to Okta is represented as a separate Okta_Application node in BloodHound. The differentiator is the `domainFQDN` property: + +![Jamf Pro SAML application in BloodHound](../Images/bloodhound-jamf-saml-properties.png) + +It is also possible to integrate Jamf Pro with Okta using Secure Web Authentication (SWA), but this option is less secure. + +![Jamf Pro SWA settings](../Images/app-jamf-swa.png) + +## Google Workspace + +Similarly to the Jamf Pro SAML applications, each Google Workspace (formerly G Suite) instance connected to Okta using SAML 2.0 is represented as a separate Okta_Application node in BloodHound and is identified by the `domainFQDN` property: + +![Google Workspace SAML application in BloodHound](../Images/bloodhound-google-saml-properties.png) + +The SAML 2.0 protocol should always be preferred to SWA when integrating Okta with Google Workspace: + +![Google Workspace sign-in protocol settings](../Images/app-google-protocol-selector.png) + +## Generic SAML 2.0 Applications + +The assertion consumer service (ACS) URLs of generic (non-Catalog) Okta SAML 2.0 applications are exposed via the `url` attribute in BloodHound. + +![Okta SAML application in BloodHound](../Images/bloodhound-app-saml.png) + +## Generic Secure Web Authentication (SWA) Applications + +Secure Web Authentication (SWA) is an Okta technology that provides Single Sign-On (SSO) functionality to external web applications that don't support federated protocols. SWA applications store user credentials in Okta and automatically fill them in when users access the application through the Okta dashboard. + +The app's login page URL is exposed via the `url` attribute in BloodHound. + +![Okta SWA application in BloodHound](../Images/bloodhound-app-swa.png) + +## Generic OpenID Connect (OIDC) Applications + +Okta supports three types of OIDC applications: + +- Web Application +- Single-Page Application (SPA) +- Native Application + +The default redirect URI of generic (non-Catalog) Okta OIDC single-page applications (SPAs) starts with `http://localhost:8080/`, making it hard to identify the actual application address. The optional Okta-initiated sign-in flow URL is therefore exposed in the `url` attribute in BloodHound instead, if configured. + +OIDC applications can be granted OAuth 2.0 scopes to access Okta APIs on behalf of users: + +![Okta application OIDC grants](../Images/app-oidc-grants.png) + +## SCIM-Enabled Applications + +The `features` attribute of Okta_Application nodes may contain the following SCIM-related values, indicating if SCIM is enabled and which protocol capabilities are supported: + +| Feature | Description | +|------------------------------|--------------------------------------------------------------------------------| +| PUSH_NEW_USERS | Supports pushing new users from Okta to the application | +| PUSH_PASSWORD_UPDATES | Supports pushing password updates from Okta to the application | +| PUSH_PENDING_USERS | Supports pushing users from Okta to the application in pending state | +| PUSH_PROFILE_UPDATES | Supports pushing profile updates from Okta to the application | +| PUSH_USER_DEACTIVATION | Supports pushing user deactivation from Okta to the application | +| REACTIVATE_USERS | Supports reactivating users in the application from Okta | +| IMPORT_NEW_USERS | Supports importing new users into Okta from the application | +| OPP_SCIM_INCREMENTAL_IMPORTS | Supports incremental imports of users from the application into Okta | +| IMPORT_PROFILE_UPDATES | Updates a linked user's app profile in Okta during manual or scheduled imports | +| GROUP_PUSH | Supports pushing groups and group memberships from Okta to the application | +| PROFILE_MASTERING | Supports profile mastering in Okta, allowing the application to be the source of truth for user profiles | diff --git a/descriptions/nodes/Okta_AuthorizationServer.md b/descriptions/nodes/Okta_AuthorizationServer.md index 6241165..b43dd69 100644 --- a/descriptions/nodes/Okta_AuthorizationServer.md +++ b/descriptions/nodes/Okta_AuthorizationServer.md @@ -2,7 +2,7 @@ Authorization servers in Okta are used to issue OAuth 2.0 access tokens for API access. They define the scopes, claims, and access policies that control how tokens are issued and what permissions they grant. Each Okta organization has a default authorization server, and administrators can create additional custom authorization servers for specific use cases. -In `OktaHound`, authorization servers are represented as `Okta_AuthorizationServer` nodes. +Okta authorization servers are represented as Okta_AuthorizationServer nodes. -> [!WARNING] -> The relationships between authorization servers and applications are currently not evaluated by `OktaHound`. +> [!NOTE] +> The relationships between authorization servers and applications are currently not evaluated in BloodHound. diff --git a/descriptions/nodes/Okta_ClientSecret.md b/descriptions/nodes/Okta_ClientSecret.md index 86e60da..426d56f 100644 --- a/descriptions/nodes/Okta_ClientSecret.md +++ b/descriptions/nodes/Okta_ClientSecret.md @@ -8,8 +8,7 @@ An application can have up to two client secrets configured, to allow for secret ![Okta client secret rotation](../Images/app-client-secret-rotation.png) -Client secrets are represented as `Okta_ClientSecret` nodes in BloodHound. +Client secrets are represented as Okta_ClientSecret nodes in BloodHound. > [!NOTE] -> For security reasons, the OktaHound collector does not write cleartext client secrets -> to the OpenGraph JSON, only their hashed identifiers. +> For security reasons, the OpenHound and OktaHound collectors do not collect client secrets, only their hashed identifiers. diff --git a/descriptions/nodes/Okta_CustomRole.md b/descriptions/nodes/Okta_CustomRole.md index 3ac2b28..446b42e 100644 --- a/descriptions/nodes/Okta_CustomRole.md +++ b/descriptions/nodes/Okta_CustomRole.md @@ -1,19 +1,16 @@ ## Overview -Custom roles can be created with specific [permissions](https://developer.okta.com/docs/api/openapi/okta-management/guides/permissions/) -and then assigned to [users](Okta_User.md), [groups](Okta_Group.md), and [applications](Okta_Application.md) over [resource sets](Okta_ResourceSet.md). -[Complex conditions](https://help.okta.com/oie/en-us/content/topics/security/custom-admin-role/permission-conditions.htm) can be used if the custom admin role has one of the following permissions: +Custom roles can be created with specific [permissions](https://developer.okta.com/docs/api/openapi/okta-management/guides/permissions/) and then assigned to [users](Okta_User.md), [groups](Okta_Group.md), and [applications](Okta_Application.md) over [resource sets](Okta_ResourceSet.md). [Complex conditions](https://help.okta.com/oie/en-us/content/topics/security/custom-admin-role/permission-conditions.htm) can be used if the custom admin role has one of the following permissions: - okta.users.read - okta.users.manage - okta.users.create -Custom roles are represented as `Okta_CustomRole` and `Okta_RoleAssignment` nodes in `OktaHound`, similar to built-in roles. +Custom roles are represented as Okta_CustomRole and Okta_RoleAssignment nodes, similar to built-in roles. ## Abusable Permissions of Custom Roles in Okta -The following Okta permissions are particularly interesting from an offensive security perspective, -as they can be abused to escalate privileges in hybrid scenarios: +The following Okta permissions are particularly interesting from an offensive security perspective, as they can be abused to escalate privileges in hybrid scenarios: - okta.users.manage - okta.users.credentials.manage @@ -26,5 +23,5 @@ as they can be abused to escalate privileges in hybrid scenarios: - okta.apps.manage - okta.apps.clientCredentials.read -> [!WARNING] +> [!NOTE] > The research on abusable Okta permissions is still ongoing. diff --git a/descriptions/nodes/Okta_Device.md b/descriptions/nodes/Okta_Device.md index 274629f..cb1a0cf 100644 --- a/descriptions/nodes/Okta_Device.md +++ b/descriptions/nodes/Okta_Device.md @@ -2,4 +2,4 @@ Devices in Okta represent the physical or virtual devices that users use to authenticate and access the Okta organization. Devices can optionally be managed by 3rd party MDM solutions, which allow administrators to enforce security compliance policies. -In `OktaHound`, devices are represented as `Okta_Device` nodes. +Okta devices are represented as Okta_Device nodes. diff --git a/descriptions/nodes/Okta_Group.md b/descriptions/nodes/Okta_Group.md index c0b864f..408b9ed 100644 --- a/descriptions/nodes/Okta_Group.md +++ b/descriptions/nodes/Okta_Group.md @@ -1,13 +1,12 @@ ## Overview -Groups in Okta are collections of users that can be used to manage access to applications and resources. Groups can be created manually or synchronized from external directories such as Active Directory. -The built-in **Everyone** group always contains all users in the Okta organization. Only users can be members of groups and groups cannot be nested. +Groups in Okta are collections of users that can be used to manage access to applications and resources. Groups can be created manually or synchronized from external directories such as Active Directory. The built-in **Everyone** group always contains all users in the Okta organization. Only users can be members of groups and groups cannot be nested. -In `OktaHound`, groups are represented as `Okta_Group` nodes. +Okta groups are represented as Okta_Group nodes. ## Synchronization with External Directories -Similarly to users, groups can also be synchronized from external directories. The Okta API exposes the original Active Directory attributes, which are then collected by `OktaHound`: +Similarly to users, groups can also be synchronized from external directories. The Okta API exposes the original Active Directory attributes: ![Group synchronized from AD](../Images/bloodhound-ad-synced-group.png) diff --git a/descriptions/nodes/Okta_IdentityProvider.md b/descriptions/nodes/Okta_IdentityProvider.md index b26cb5d..10418d7 100644 --- a/descriptions/nodes/Okta_IdentityProvider.md +++ b/descriptions/nodes/Okta_IdentityProvider.md @@ -4,7 +4,7 @@ Identity Providers (IdPs) in Okta represent external authentication sources that When users authenticate through an external identity provider, Okta can optionally create or link user accounts, enabling federated authentication across multiple systems. -In `OktaHound`, identity providers are represented as `Okta_IdentityProvider` nodes. +Okta identity providers are represented as Okta_IdentityProvider nodes. -> [!WARNING] -> The inbound identity provider routing rules and JIT (Just-In-Time) provisioning settings are currently not evaluated by `OktaHound`. +> [!NOTE] +> The inbound identity provider routing rules and JIT (Just-In-Time) provisioning settings are currently not evaluated. diff --git a/descriptions/nodes/Okta_JWK.md b/descriptions/nodes/Okta_JWK.md index e9ec6bf..8aeea8a 100644 --- a/descriptions/nodes/Okta_JWK.md +++ b/descriptions/nodes/Okta_JWK.md @@ -1,7 +1,5 @@ ## Overview -JSON Web Keys (JWKs) are used by OAuth 2.0 client applications to authenticate with Okta using the `private_key_jwt` client authentication method. -This is an asymmetric authentication mechanism where the application possesses a private key and Okta stores the corresponding public key. -A service application can have multiple JWKs configured for key rotation purposes. +JSON Web Keys (JWKs) are used by OAuth 2.0 client applications to authenticate with Okta using the `private_key_jwt` client authentication method. This is an asymmetric authentication mechanism where the application possesses a private key and Okta stores the corresponding public key. A service application can have multiple JWKs configured for key rotation purposes. -JWKs are represented as `Okta_JWK` nodes in BloodHound. +JWKs are represented as Okta_JWK nodes in BloodHound. diff --git a/descriptions/nodes/Okta_Organization.md b/descriptions/nodes/Okta_Organization.md index a926067..2d18df8 100644 --- a/descriptions/nodes/Okta_Organization.md +++ b/descriptions/nodes/Okta_Organization.md @@ -2,4 +2,4 @@ The Organization entity represents the Okta tenant itself. It contains general information about the organization, such as its name, domain, and settings. -In `OktaHound`, the organization is represented as a single `Okta_Organization` node. +The Okta organization is represented as a single Okta_Organization node. diff --git a/descriptions/nodes/Okta_Policy.md b/descriptions/nodes/Okta_Policy.md index 666e966..5f39f67 100644 --- a/descriptions/nodes/Okta_Policy.md +++ b/descriptions/nodes/Okta_Policy.md @@ -2,7 +2,7 @@ Policies in Okta define the rules and conditions that govern authentication, authorization, and security behaviors within an organization. They control aspects such as password requirements, MFA enrollment, session management, and application access. -In `OktaHound`, policies are represented as `Okta_Policy` nodes. +Okta policies are represented as Okta_Policy nodes. ## Policy Types @@ -20,5 +20,4 @@ The following [policy types](https://developer.okta.com/docs/api/openapi/okta-ma | POST_AUTH_SESSION | [Identity Threat Protection policies](https://help.okta.com/oie/en-us/content/topics/itp/overview.htm) | | ENTITY_RISK | [Entity risk policies](https://help.okta.com/oie/en-us/content/topics/itp/entity-risk-policy.htm) | -The `OktaHound` collector specifically reads the `IDP_DISCOVERY` policies to check -if the [Agentless Desktop SSO](https://help.okta.com/en-us/content/topics/directory/configuring_agentless_sso.htm) feature is enabled in the organization through at least one such policy. +The OpenHound collector specifically reads the `IDP_DISCOVERY` policies to check if the [Agentless Desktop SSO](https://help.okta.com/en-us/content/topics/directory/configuring_agentless_sso.htm) feature is enabled in the organization through at least one such policy. diff --git a/descriptions/nodes/Okta_Realm.md b/descriptions/nodes/Okta_Realm.md index 197d274..a50068b 100644 --- a/descriptions/nodes/Okta_Realm.md +++ b/descriptions/nodes/Okta_Realm.md @@ -2,7 +2,7 @@ Okta Realms are used to define authentication boundaries within an Okta organization. They allow administrators to segment users and applications based on different criteria, such as geographic location, business unit, or security requirements. -In `OktaHound`, Okta Realms are represented as `Okta_Realm` nodes. +Okta Realms are represented as Okta_Realm nodes. -> [!WARNING] -> Okta Realms are currently not supported by `OktaHound` due to licensing restrictions. +> [!NOTE] +> Okta Realms are currently not supported due to licensing restrictions. diff --git a/descriptions/nodes/Okta_ResourceSet.md b/descriptions/nodes/Okta_ResourceSet.md index 4828469..e8e8a9f 100644 --- a/descriptions/nodes/Okta_ResourceSet.md +++ b/descriptions/nodes/Okta_ResourceSet.md @@ -1,7 +1,6 @@ ## Overview -Resource sets are collections of entities that can be used to scope custom role assignments in Okta. -A resource set can contain the following object types: +Resource sets are collections of entities that can be used to scope custom role assignments in Okta. A resource set can contain the following object types: - [x] [Users](Okta_User.md) - [x] [Groups](Okta_Group.md) @@ -23,9 +22,8 @@ A resource set can contain the following object types: - [ ] ~~Identity and Access Management Resources~~ (Gaps in the Okta API) > [!NOTE] -> Only the marked resource types are currently supported by `OktaHound` as resource set members. -> Some resource types, such as Workflows, are not accessible via the Okta API at all. +> Only the marked resource types are currently supported as resource set members. Some resource types, such as Workflows, are not accessible via the Okta API at all. ![Okta Resource Set displayed in BloodHound](../Images/bloodhound-resource-set.png) -In `OktaHound`, resource sets are represented as `Okta_ResourceSet` nodes. +Okta resource sets are represented as Okta_ResourceSet nodes. diff --git a/descriptions/nodes/Okta_Role.md b/descriptions/nodes/Okta_Role.md index 0c43f9f..6e425f9 100644 --- a/descriptions/nodes/Okta_Role.md +++ b/descriptions/nodes/Okta_Role.md @@ -24,7 +24,7 @@ The following roles can either be scoped to specific resources or assigned organ > [!NOTE] > Although the Workflows Administrator role is a built-in role, the Okta API treats it as a custom role that is scoped to the built-in `Workflows Resource Set`. -In `OktaHound`, built-in roles are represented as `Okta_Role` nodes. +Okta built-in roles are represented as Okta_Role nodes. ## Built-In Role Identifiers @@ -45,11 +45,8 @@ When working with roles using the Okta API, the built-in roles are referenced by | REPORT_ADMIN | Report Administrator | | READ_ONLY_ADMIN | Read-Only Administrator | -To make the role identifiers unique, the `OktaHound` collector adds the organization domain name as a suffix to each role's ID, e.g., `SUPER_ADMIN@contoso.okta.com`. +To make the role identifiers unique, the OpenHound collector adds the organization domain name as a suffix to each role's ID, e.g., `SUPER_ADMIN@contoso.okta.com`. ## Built-In Role Permissions -Unlike custom roles, built-in roles have fixed permissions that cannot be changed. -However, the exact OAuth 2.0 scopes granted to each built-in role are not publicly documented by Okta and cannot even be retrieved via the API. -We therefore did the mapping by ourselves based on the role descriptions in the Okta documentation. -Hence, the resulting permissions ingested to BloodHound are best-effort approximations and may not be 100% accurate. +Unlike custom roles, built-in roles have fixed permissions that cannot be changed. However, the exact OAuth 2.0 scopes granted to each built-in role are not publicly documented by Okta and cannot even be retrieved via the API. We therefore did the mapping by ourselves based on the role descriptions in the Okta documentation. Hence, the resulting permissions ingested to BloodHound are best-effort approximations and may not be 100% accurate. diff --git a/descriptions/nodes/Okta_RoleAssignment.md b/descriptions/nodes/Okta_RoleAssignment.md index af38863..fe0b489 100644 --- a/descriptions/nodes/Okta_RoleAssignment.md +++ b/descriptions/nodes/Okta_RoleAssignment.md @@ -1,3 +1,3 @@ ## Overview -To help visualize role assignments in BloodHound, `OktaHound` creates `Okta_RoleAssignment` nodes for each role assignment in Okta. These nodes represent the relationship between a [user](Okta_User.md), [group](Okta_Group.md), or [application](Okta_Application.md) and a role ([built-in](Okta_Role.md) or [custom](Okta_CustomRole.md)). +To help visualize role assignments in BloodHound, Okta_RoleAssignment nodes are created for each role assignment in Okta. These nodes represent the relationship between a [user](Okta_User.md), [group](Okta_Group.md), or [application](Okta_Application.md) and a role ([built-in](Okta_Role.md) or [custom](Okta_CustomRole.md)). diff --git a/descriptions/nodes/Okta_User.md b/descriptions/nodes/Okta_User.md index 055c804..5a0872a 100644 --- a/descriptions/nodes/Okta_User.md +++ b/descriptions/nodes/Okta_User.md @@ -2,7 +2,7 @@ User objects (AKA People) represent individuals who have access to the Okta organization. Each user has a unique identifier, username in the email address format, and various attributes such as email, first name, last name, and status. -In `OktaHound`, users are represented as `Okta_User` nodes. +Okta users are represented as Okta_User nodes. ## User Status @@ -10,7 +10,7 @@ User status can have [multiple values](https://developer.okta.com/docs/api/opena ![Okta user status](https://developer.okta.com/docs/api/images/users/okta-user-status.png) -To simplify analysis in BloodHound, the `OktaHound` collector maps the **Status** attribute to the virtual boolean **Enabled** attribute as follows: +To simplify analysis in BloodHound, the OpenHound collector maps the **Status** attribute to the virtual boolean **Enabled** attribute as follows: | Okta User Status | Enabled | Explanation | |------------------|---------|----------------------------------| @@ -24,16 +24,11 @@ To simplify analysis in BloodHound, the `OktaHound` collector maps the **Status* | DEPROVISIONED | ❌ | User is deprovisioned and cannot authenticate. | > [!WARNING] -> This mapping is a simplification and may not cover all edge cases. -> Always refer to the actual **Status** attribute for precise user state information. +> This mapping is a simplification and may not cover all edge cases. Always refer to the actual **Status** attribute for precise user state information. ## Authentication Factors -Okta supports various authentication factors for multi-factor authentication (MFA), -such as SMS, email, push notifications, and hardware tokens. -In case of mobile and desktop applications, these authentication factors are associated with the [Device](Okta_Device.md) entities. -Other authentication factors, such as YubiKeys and Google Authenticator, are not represented as separate nodes in BloodHound, -but the number of enrolled factors is stored in the `authenticationFactors` attribute of the `Okta_User` nodes. +Okta supports various authentication factors for multi-factor authentication (MFA), such as SMS, email, push notifications, and hardware tokens. In case of mobile and desktop applications, these authentication factors are associated with the [Device](Okta_Device.md) entities. Other authentication factors, such as YubiKeys and Google Authenticator, are not represented as separate nodes in BloodHound, but the number of enrolled factors is stored in the `authenticationFactors` attribute of the Okta_User nodes. ## Synchronization with External Directories diff --git a/docs/og-docs-automation b/docs/og-docs-automation new file mode 160000 index 0000000..400bd30 --- /dev/null +++ b/docs/og-docs-automation @@ -0,0 +1 @@ +Subproject commit 400bd3010e6b106b77991ad6eb2eb586cb627862 diff --git a/docs/og-docs.json b/docs/og-docs.json new file mode 100644 index 0000000..390b413 --- /dev/null +++ b/docs/og-docs.json @@ -0,0 +1,14 @@ +{ + "extensionSchemaPath": "extension/schema.json", + "extensionShortName": "Okta", + "gitHubBaseUrl": "https://github.com/SpecterOps/openhound-okta", + "stripTitlePrefix": "Okta: ", + "savedSearchesDir": "extension/saved_searches", + "zoneRulesDir": "extension/privilege_zone_rules", + "nodeDescriptionsDir": "descriptions/nodes", + "edgeDescriptionsDir": "descriptions/edges", + "openHoundStructure": true, + "imagesDir": "descriptions/images", + "iconSize": 32, + "iconScale": 0.55 +} diff --git a/extension/saved_searches/ad-agents.json b/extension/saved_searches/ad-agents.json index 05113fc..7ce321a 100644 --- a/extension/saved_searches/ad-agents.json +++ b/extension/saved_searches/ad-agents.json @@ -1,5 +1,5 @@ { "name": "Okta: Agents, Agent Pools, and Host Servers", "description": "Lists Okta agents, their associated agent pools, and the AD servers hosting each agent.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta_AgentPool)<-[:Okta_AgentMemberOf|Okta_HostsAgent*1..2]-(:Okta_Agent:Computer)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(:Okta_AgentPool)<-[:Okta_AgentMemberOf|Okta_HostsAgent*1..2]-(agent)\nWHERE agent:Okta_Agent OR agent:Computer\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/admin-console-access.json b/extension/saved_searches/admin-console-access.json index f8c4cb5..2d326ec 100644 --- a/extension/saved_searches/admin-console-access.json +++ b/extension/saved_searches/admin-console-access.json @@ -1,5 +1,5 @@ { "name": "Okta: Principals with Admin Console Access", "description": "Identifies principals with access to the Okta Admin Console.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta)-[:Okta_AppAssignment]->(c:Okta_Application)\nWHERE c.appType = \"saasure\"\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(:Okta)-[:Okta_AppAssignment]->(console:Okta_Application)\nWHERE console.appType = \"saasure\"\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/app-assignments.json b/extension/saved_searches/app-assignments.json index 854cc71..4bea94e 100644 --- a/extension/saved_searches/app-assignments.json +++ b/extension/saved_searches/app-assignments.json @@ -1,5 +1,5 @@ { "name": "Okta: Application Assignments", "description": "List all application assignments.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta)-[:Okta_AppAssignment]->(:Okta_Application)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(:Okta)-[:Okta_AppAssignment]->(:Okta_Application)\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/app-credentials.json b/extension/saved_searches/app-credentials.json index 721d626..278182c 100644 --- a/extension/saved_searches/app-credentials.json +++ b/extension/saved_searches/app-credentials.json @@ -1,5 +1,5 @@ { "name": "Okta: Application Credentials", "description": "Lists all service application secrets and JWTs.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta_Application)<-[:Okta_SecretOf|Okta_KeyOf]->(:Okta_ClientSecret:Okta_JWK)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(:Okta_Application)<-[:Okta_SecretOf|Okta_KeyOf]->(credential)\nWHERE credential:Okta_ClientSecret OR credential:Okta_JWK\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/devices.json b/extension/saved_searches/devices.json index 9bb8c39..ccf3f5b 100644 --- a/extension/saved_searches/devices.json +++ b/extension/saved_searches/devices.json @@ -1,5 +1,7 @@ { "name": "Okta: Devices", "description": "List all devices, their owners, and any mobile admins.", - "query": "MATCH p = (:Okta_Device)-[:Okta_DeviceOf]->(:Okta_User)\nOPTIONAL MATCH q = (:Okta_User:Okta_Group:Okta_Application)-[:Okta_MobileAdmin]->(:Okta_Device)\nRETURN p,q\nLIMIT 1000" + "query": "MATCH path = (:Okta_Device)-[:Okta_DeviceOf]->(:Okta_User)\nOPTIONAL MATCH adminPath = (admin)-[:Okta_MobileAdmin]->(:Okta_Device)\nWHERE admin:Okta_User OR admin:Okta_Group OR admin:Okta_Application\nRETURN path,adminPath\nLIMIT 1000" } + + diff --git a/extension/saved_searches/group-members.json b/extension/saved_searches/group-members.json index fa6eb94..cce39b4 100644 --- a/extension/saved_searches/group-members.json +++ b/extension/saved_searches/group-members.json @@ -1,5 +1,5 @@ { "name": "Okta: Group Membership", "description": "Retrieves all group membership relationships.", - "query": "MATCH p = (:Okta_User)-[:Okta_MemberOf]->(:Okta_Group)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_User)-[:Okta_MemberOf]->(:Okta_Group)\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/hybrid-inbound.json b/extension/saved_searches/hybrid-inbound.json index 18cf9c3..f7b3603 100644 --- a/extension/saved_searches/hybrid-inbound.json +++ b/extension/saved_searches/hybrid-inbound.json @@ -1,5 +1,5 @@ { "name": "Okta: Hybrid Relationships Inbound", "description": "Retrieves all hybrid relationships from external systems to Okta.", - "query": "MATCH p = (n)-[]->(:Okta)\nWHERE NOT n:Okta\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (source)-[]->(:Okta)\nWHERE NOT source:Okta\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/hybrid-outbound.json b/extension/saved_searches/hybrid-outbound.json index 6ed7911..f187c4f 100644 --- a/extension/saved_searches/hybrid-outbound.json +++ b/extension/saved_searches/hybrid-outbound.json @@ -1,5 +1,5 @@ { "name": "Okta: Hybrid Relationships Outbound", "description": "Retrieves all hybrid relationships from Okta to external systems.", - "query": "MATCH p = (:Okta)-[]->(n)\nWHERE NOT n:Okta\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta)-[]->(target)\nWHERE NOT target:Okta\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/hybrid-sync.json b/extension/saved_searches/hybrid-sync.json index fbc8b75..8e74034 100644 --- a/extension/saved_searches/hybrid-sync.json +++ b/extension/saved_searches/hybrid-sync.json @@ -1,5 +1,5 @@ { "name": "Okta: Security Principal Synchronization", "description": "Retrieves all users and groups that are synchronized TO or FROM Okta.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta)-[:Okta_UserPull|Okta_UserPush|Okta_GroupPull|Okta_GroupPush]->(:Okta)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(:Okta)-[:Okta_UserPull|Okta_UserPush|Okta_GroupPull|Okta_GroupPush]->(:Okta)\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/identity-providers-direct-privileged.json b/extension/saved_searches/identity-providers-direct-privileged.json index 15874d0..7a5be86 100644 --- a/extension/saved_searches/identity-providers-direct-privileged.json +++ b/extension/saved_searches/identity-providers-direct-privileged.json @@ -1,5 +1,5 @@ { "name": "Okta: Identity Provider Assignments - Direct Privileged Access", "description": "Identity providers associated with users or groups that hold direct privileged role assignments in Okta.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta_IdentityProvider)-[:Okta_IdentityProviderFor|Okta_IdpGroupAssignment]->(:Okta_User:Okta_Group)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(:Okta_IdentityProvider)-[:Okta_IdentityProviderFor|Okta_IdpGroupAssignment]->(assignee)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE assignee:Okta_User OR assignee:Okta_Group\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/identity-providers-indirect-privileged.json b/extension/saved_searches/identity-providers-indirect-privileged.json index 36e10a5..e625973 100644 --- a/extension/saved_searches/identity-providers-indirect-privileged.json +++ b/extension/saved_searches/identity-providers-indirect-privileged.json @@ -1,5 +1,5 @@ { "name": "Okta: Identity Provider Assignments - Indirect Privileged Access", "description": "Identity providers associated with users who hold privileged role assignments through group membership in Okta.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta_IdentityProvider)-[:Okta_IdentityProviderFor]->(:Okta_User)-[:Okta_MemberOf]->(:Okta_Group)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(:Okta_IdentityProvider)-[:Okta_IdentityProviderFor]->(:Okta_User)-[:Okta_MemberOf]->(:Okta_Group)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/identity-providers.json b/extension/saved_searches/identity-providers.json index 995f3a0..739f905 100644 --- a/extension/saved_searches/identity-providers.json +++ b/extension/saved_searches/identity-providers.json @@ -1,5 +1,5 @@ { "name": "Okta: Identity Provider Assignments", "description": "Lists all identity providers and the users and groups they are associated with, including per-user trust relationships and automatic group assignments.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta_IdentityProvider)-[:Okta_IdentityProviderFor|Okta_IdpGroupAssignment]->(:Okta_User:Okta_Group)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(:Okta_IdentityProvider)-[:Okta_IdentityProviderFor|Okta_IdpGroupAssignment]->(assignee)\nWHERE assignee:Okta_User OR assignee:Okta_Group\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/org-chart.json b/extension/saved_searches/org-chart.json index 15e118d..8fd5b8d 100644 --- a/extension/saved_searches/org-chart.json +++ b/extension/saved_searches/org-chart.json @@ -1,5 +1,5 @@ { "name": "Okta: Organizational Structure", "description": "Retrieves all manager relationships.", - "query": "MATCH p = (:Okta_User)-[:Okta_ManagerOf]->(:Okta_User)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_User)-[:Okta_ManagerOf]->(:Okta_User)\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/org-trust-relationships.json b/extension/saved_searches/org-trust-relationships.json index 380c059..14ae160 100644 --- a/extension/saved_searches/org-trust-relationships.json +++ b/extension/saved_searches/org-trust-relationships.json @@ -1,5 +1,5 @@ { "name": "Okta: Org Trust Relationships", "description": "Lists all org-to-org trust relationships including inbound and outbound SSO federation, Secure Web Authentication (SWA), and Kerberos SSO relationships between Okta applications and supported external organizations or tenants.", - "query": "MATCH p = (:Okta_Application:Okta_IdentityProvider)-[:Okta_InboundOrgSSO|Okta_OutboundOrgSSO|Okta_OrgSWA|Okta_KerberosSSO]-()\nRETURN p\nLIMIT 1000" -} + "query": "MATCH path = (source)-[:Okta_InboundOrgSSO|Okta_OutboundOrgSSO|Okta_OrgSWA|Okta_KerberosSSO]-()\nWHERE source:Okta_Application OR source:Okta_IdentityProvider\nRETURN path\nLIMIT 1000" +} \ No newline at end of file diff --git a/extension/saved_searches/password-and-mfa-permissions.json b/extension/saved_searches/password-and-mfa-permissions.json index d02fd5e..4f6b2dc 100644 --- a/extension/saved_searches/password-and-mfa-permissions.json +++ b/extension/saved_searches/password-and-mfa-permissions.json @@ -1,5 +1,5 @@ { "name": "Okta: Password and MFA Permissions", "description": "Lists permissions to reset passwords and MFA factors.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta_User:Okta_Group:Okta_Application)-[:Okta_ResetPassword|Okta_ResetFactors|Okta_HelpDeskAdmin|Okta_OrgAdmin|Okta_GroupAdmin]->(:Okta_User)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(actor)-[:Okta_ResetPassword|Okta_ResetFactors|Okta_HelpDeskAdmin|Okta_OrgAdmin|Okta_GroupAdmin]->(:Okta_User)\nWHERE actor:Okta_User OR actor:Okta_Group OR actor:Okta_Application\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/privileged-app-unrotated-access-keys.json b/extension/saved_searches/privileged-app-unrotated-access-keys.json index e9cf56b..cb2f813 100644 --- a/extension/saved_searches/privileged-app-unrotated-access-keys.json +++ b/extension/saved_searches/privileged-app-unrotated-access-keys.json @@ -1,5 +1,5 @@ { "name": "Okta: Unrotated Active Access Keys on Privileged Apps", "description": "Finds active JWKs or client secrets older than 365 days on applications that have role assignments.", - "query": "MATCH p = (s:Okta_JWK:Okta_ClientSecret)-[:Okta_KeyOf|Okta_SecretOf]->(:Okta_Application)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE s.status = \"ACTIVE\" AND datetime(s.created) <= datetime() - duration(\"P365D\")\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (credential)-[:Okta_KeyOf|Okta_SecretOf]->(:Okta_Application)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE (credential:Okta_JWK OR credential:Okta_ClientSecret) AND credential.status = \"ACTIVE\" AND datetime(credential.created) <= datetime() - duration(\"P365D\")\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/privileged-apps.json b/extension/saved_searches/privileged-apps.json index ea03c20..414fafd 100644 --- a/extension/saved_searches/privileged-apps.json +++ b/extension/saved_searches/privileged-apps.json @@ -1,5 +1,5 @@ { "name": "Okta: Applications with Role Assignments", "description": "Applications that have roles assigned.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta_Application)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(:Okta_Application)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/privileged-hybrid-inbound-direct.json b/extension/saved_searches/privileged-hybrid-inbound-direct.json index 3e25a1c..de3599a 100644 --- a/extension/saved_searches/privileged-hybrid-inbound-direct.json +++ b/extension/saved_searches/privileged-hybrid-inbound-direct.json @@ -1,5 +1,5 @@ { "name": "Okta: Synced Principals with Privileged Access (Direct) - Hybrid Edges", "description": "Users, groups, and applications with inbound hybrid relationships (sync, SSO, or AD agent) that hold privileged role assignments in Okta.", - "query": "MATCH p = ()-[:Okta_UserSync|Okta_MembershipSync|Okta_InboundSSO|Okta_HostsAgent]->(:Okta_User:Okta_Group:Okta_Application)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = ()-[:Okta_UserSync|Okta_MembershipSync|Okta_InboundSSO|Okta_HostsAgent]->(principal)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE principal:Okta_User OR principal:Okta_Group OR principal:Okta_Application\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/privileged-hybrid-inbound-indirect.json b/extension/saved_searches/privileged-hybrid-inbound-indirect.json index 9104170..4821d84 100644 --- a/extension/saved_searches/privileged-hybrid-inbound-indirect.json +++ b/extension/saved_searches/privileged-hybrid-inbound-indirect.json @@ -1,5 +1,5 @@ { "name": "Okta: Synced Principals with Privileged Access (Indirect) - Hybrid Edges", "description": "Users and applications with inbound hybrid relationships (sync, SSO, or AD agent) that hold privileged role assignments through group membership in Okta.", - "query": "MATCH p = ()-[:Okta_UserSync|Okta_InboundSSO|Okta_HostsAgent]->(:Okta_User:Okta_Application)-[:Okta_MemberOf]->(:Okta_Group)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nRETURN p\nLIMIT 1000" -} + "query": "MATCH path = ()-[:Okta_UserSync|Okta_InboundSSO|Okta_HostsAgent]->(principal)-[:Okta_MemberOf]->(:Okta_Group)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE principal:Okta_User OR principal:Okta_Application\nRETURN path\nLIMIT 1000" +} \ No newline at end of file diff --git a/extension/saved_searches/privileged-principals-hybrid-direct.json b/extension/saved_searches/privileged-principals-hybrid-direct.json index 0dd79c2..14ccbee 100644 --- a/extension/saved_searches/privileged-principals-hybrid-direct.json +++ b/extension/saved_searches/privileged-principals-hybrid-direct.json @@ -1,5 +1,5 @@ { "name": "Okta: Synced Principals with Privileged Access (Direct) - Okta Edges", "description": "Users and groups synchronized from external sources that have privileged role assignments.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta_Application:Okta_IdentityProvider)-[:Okta_UserPull|Okta_GroupPull|Okta_IdentityProviderFor|Okta_IdpGroupAssignment]->(:Okta)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(provider)-[:Okta_UserPull|Okta_GroupPull|Okta_IdentityProviderFor|Okta_IdpGroupAssignment]->(:Okta)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE provider:Okta_Application OR provider:Okta_IdentityProvider\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/privileged-principals-hybrid-indirect.json b/extension/saved_searches/privileged-principals-hybrid-indirect.json index 15a817e..e2e8bcf 100644 --- a/extension/saved_searches/privileged-principals-hybrid-indirect.json +++ b/extension/saved_searches/privileged-principals-hybrid-indirect.json @@ -1,5 +1,5 @@ { "name": "Okta: Synced Principals with Privileged Access (Indirect) - Okta Edges", "description": "Users synchronized from external sources that hold privileged role assignments through group membership in Okta.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta_Application:Okta_IdentityProvider)-[:Okta_UserPull|Okta_IdentityProviderFor]->(:Okta_User)-[:Okta_MemberOf]->(:Okta_Group)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(provider)-[:Okta_UserPull|Okta_IdentityProviderFor]->(:Okta_User)-[:Okta_MemberOf]->(:Okta_Group)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE provider:Okta_Application OR provider:Okta_IdentityProvider\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/privileged-users-no-mfa-direct.json b/extension/saved_searches/privileged-users-no-mfa-direct.json index 36b105e..a2a6540 100644 --- a/extension/saved_searches/privileged-users-no-mfa-direct.json +++ b/extension/saved_searches/privileged-users-no-mfa-direct.json @@ -1,5 +1,5 @@ { "name": "Okta: Privileged Users without MFA (Direct)", "description": "Users who do not have multi-factor authentication enabled and directly hold privileged role assignments.", - "query": "MATCH p = (u:Okta_User)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE u.authenticationFactors = 0\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (user:Okta_User)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE user.authenticationFactors = 0\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/privileged-users-no-mfa-indirect.json b/extension/saved_searches/privileged-users-no-mfa-indirect.json index 20dacf0..6126b9c 100644 --- a/extension/saved_searches/privileged-users-no-mfa-indirect.json +++ b/extension/saved_searches/privileged-users-no-mfa-indirect.json @@ -1,5 +1,5 @@ { "name": "Okta: Privileged Users without MFA (Indirect)", "description": "Users who do not have multi-factor authentication enabled and hold privileged role assignments through group membership.", - "query": "MATCH p = (u:Okta_User)-[:Okta_MemberOf]->(:Okta_Group)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE u.authenticationFactors = 0\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (user:Okta_User)-[:Okta_MemberOf]->(:Okta_Group)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE user.authenticationFactors = 0\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/privileged-users-old-passwords-direct.json b/extension/saved_searches/privileged-users-old-passwords-direct.json index 3435bd5..5edd2b2 100644 --- a/extension/saved_searches/privileged-users-old-passwords-direct.json +++ b/extension/saved_searches/privileged-users-old-passwords-direct.json @@ -1,5 +1,5 @@ { "name": "Okta: Privileged Users with Old Passwords (Direct)", "description": "Finds users whose last password change was more than a year ago and directly hold privileged role assignments.", - "query": "MATCH p = (u:Okta_User)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE u.passwordChanged IS NOT NULL AND datetime(u.passwordChanged) <= datetime() - duration(\"P365D\")\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (user:Okta_User)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE user.passwordChanged IS NOT NULL AND datetime(user.passwordChanged) <= datetime() - duration(\"P365D\")\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/privileged-users-old-passwords-indirect.json b/extension/saved_searches/privileged-users-old-passwords-indirect.json index cbd6114..d5b6436 100644 --- a/extension/saved_searches/privileged-users-old-passwords-indirect.json +++ b/extension/saved_searches/privileged-users-old-passwords-indirect.json @@ -1,5 +1,5 @@ { "name": "Okta: Privileged Users with Old Passwords (Indirect)", "description": "Finds users whose last password change was more than a year ago and hold privileged role assignments through group membership.", - "query": "MATCH p = (u:Okta_User)-[:Okta_MemberOf]->(:Okta_Group)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE u.passwordChanged IS NOT NULL AND datetime(u.passwordChanged) <= datetime() - duration(\"P365D\")\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (user:Okta_User)-[:Okta_MemberOf]->(:Okta_Group)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE user.passwordChanged IS NOT NULL AND datetime(user.passwordChanged) <= datetime() - duration(\"P365D\")\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/privileged-users-unexpected-status-direct.json b/extension/saved_searches/privileged-users-unexpected-status-direct.json index 67af0eb..c8c65d7 100644 --- a/extension/saved_searches/privileged-users-unexpected-status-direct.json +++ b/extension/saved_searches/privileged-users-unexpected-status-direct.json @@ -1,5 +1,5 @@ { "name": "Okta: Privileged Users with Non-Active Status (Direct)", "description": "Finds users whose status is not ACTIVE and directly hold privileged role assignments, including deactivated, suspended, or provisioning-incomplete accounts.", - "query": "MATCH p = (u:Okta_User)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE u.status <> \"ACTIVE\"\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (user:Okta_User)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE user.status <> \"ACTIVE\"\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/privileged-users-unexpected-status-indirect.json b/extension/saved_searches/privileged-users-unexpected-status-indirect.json index be2c15c..86a789e 100644 --- a/extension/saved_searches/privileged-users-unexpected-status-indirect.json +++ b/extension/saved_searches/privileged-users-unexpected-status-indirect.json @@ -1,5 +1,5 @@ { "name": "Okta: Privileged Users with Non-Active Status (Indirect)", "description": "Finds users whose status is not ACTIVE and hold privileged role assignments through group membership, including deactivated, suspended, or provisioning-incomplete accounts.", - "query": "MATCH p = (u:Okta_User)-[:Okta_MemberOf]->(:Okta_Group)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE u.status <> \"ACTIVE\"\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (user:Okta_User)-[:Okta_MemberOf]->(:Okta_Group)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE user.status <> \"ACTIVE\"\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/read-client-secrets.json b/extension/saved_searches/read-client-secrets.json index 990348e..4f04cff 100644 --- a/extension/saved_searches/read-client-secrets.json +++ b/extension/saved_searches/read-client-secrets.json @@ -1,5 +1,5 @@ { "name": "Okta: Read Client Secrets of Privileged Applications", "description": "Searches for client secrets associated with privileged applications that are readable to non-Super Admins.", - "query": "MATCH p = (:Okta)-[:Okta_ReadClientSecret|Okta_MemberOf*1..2]->(:Okta_ClientSecret)-[:Okta_SecretOf]->(:Okta_Application)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta)-[:Okta_ReadClientSecret|Okta_MemberOf*1..2]->(:Okta_ClientSecret)-[:Okta_SecretOf]->(:Okta_Application)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/realm-membership.json b/extension/saved_searches/realm-membership.json index 9ea6c40..3f6f40e 100644 --- a/extension/saved_searches/realm-membership.json +++ b/extension/saved_searches/realm-membership.json @@ -1,5 +1,5 @@ { "name": "Okta: Realm Membership", "description": "Lists all Okta realms and the users assigned to them.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta_Realm)-[:Okta_RealmContains]->(:Okta_User)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(:Okta_Realm)-[:Okta_RealmContains]->(:Okta_User)\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/resource-set-membership.json b/extension/saved_searches/resource-set-membership.json index 7a6befb..8683647 100644 --- a/extension/saved_searches/resource-set-membership.json +++ b/extension/saved_searches/resource-set-membership.json @@ -1,5 +1,5 @@ { "name": "Okta: Resource Set Membership", "description": "Lists all resource sets and their associated members.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta_ResourceSet)-[:Okta_ResourceSetContains]->(:Okta)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(:Okta_ResourceSet)-[:Okta_ResourceSetContains]->(:Okta)\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/role-app-admins.json b/extension/saved_searches/role-app-admins.json index 59f7fc0..335b0f7 100644 --- a/extension/saved_searches/role-app-admins.json +++ b/extension/saved_searches/role-app-admins.json @@ -1,5 +1,5 @@ { "name": "Okta: Application Administrators and Managers", "description": "List all Application Administrators and Managers.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta_User:Okta_Group:Okta_Application)-[:Okta_AppAdmin|Okta_ManageApp]->(:Okta_Application:Okta_ApiServiceIntegration)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(admin)-[:Okta_AppAdmin|Okta_ManageApp]->(app)\nWHERE (admin:Okta_User OR admin:Okta_Group OR admin:Okta_Application) AND (app:Okta_Application OR app:Okta_ApiServiceIntegration)\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/role-assignments.json b/extension/saved_searches/role-assignments.json index 2bc90ca..e94a235 100644 --- a/extension/saved_searches/role-assignments.json +++ b/extension/saved_searches/role-assignments.json @@ -1,5 +1,5 @@ { "name": "Okta: Role Assignments - Role Assignments and Scope", "description": "Lists all role assignments and scope, including transitive group membership.", - "query": "MATCH p = (:Okta)-[:Okta_HasRoleAssignment|Okta_MemberOf*1..2]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta)-[:Okta_HasRoleAssignment|Okta_MemberOf*1..2]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/role-custom-assignments.json b/extension/saved_searches/role-custom-assignments.json index 5b9c5e5..2095f27 100644 --- a/extension/saved_searches/role-custom-assignments.json +++ b/extension/saved_searches/role-custom-assignments.json @@ -1,5 +1,5 @@ { "name": "Okta: Role Assignments - All Custom Roles", "description": "Lists all role assignments, linking principals to their assigned custom roles.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta_User:Okta_Group:Okta_Application)-[:Okta_HasRole]->(:Okta_CustomRole)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(assignee)-[:Okta_HasRole]->(:Okta_CustomRole)\nWHERE assignee:Okta_User OR assignee:Okta_Group OR assignee:Okta_Application\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/role-direct-assignments.json b/extension/saved_searches/role-direct-assignments.json index 2c70ebb..915460c 100644 --- a/extension/saved_searches/role-direct-assignments.json +++ b/extension/saved_searches/role-direct-assignments.json @@ -1,5 +1,5 @@ { "name": "Okta: Role Assignments - All Built-in Roles", "description": "Lists all role assignments, linking principals to their assigned built-in roles.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta_User:Okta_Group:Okta_Application)-[:Okta_HasRole]->(:Okta_Role)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(assignee)-[:Okta_HasRole]->(:Okta_Role)\nWHERE assignee:Okta_User OR assignee:Okta_Group OR assignee:Okta_Application\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/role-group-admins.json b/extension/saved_searches/role-group-admins.json index 7d5c53b..0e1edb4 100644 --- a/extension/saved_searches/role-group-admins.json +++ b/extension/saved_searches/role-group-admins.json @@ -1,5 +1,5 @@ { "name": "Okta: Role Assignments - Group Administrators", "description": "List all Group Administrators and Group Membership Administrators.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta_User:Okta_Group:Okta_Application)-[:Okta_GroupAdmin|Okta_GroupMembershipAdmin|Okta_OrgAdmin]->(:Okta_Group)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(admin)-[:Okta_GroupAdmin|Okta_GroupMembershipAdmin|Okta_OrgAdmin]->(:Okta_Group)\nWHERE admin:Okta_User OR admin:Okta_Group OR admin:Okta_Application\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/scim-read-passwords.json b/extension/saved_searches/scim-read-passwords.json index e819cca..d2a3e4c 100644 --- a/extension/saved_searches/scim-read-passwords.json +++ b/extension/saved_searches/scim-read-passwords.json @@ -1,5 +1,5 @@ { "name": "Okta: SCIM Apps Receiving Password Updates", "description": "Lists application-to-user assignments where the app receives password updates.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta_Application)-[:Okta_ReadPasswordUpdates]->(:Okta_User)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(:Okta_Application)-[:Okta_ReadPasswordUpdates]->(:Okta_User)\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/service-integration-creators.json b/extension/saved_searches/service-integration-creators.json index f66a70a..db9a6a9 100644 --- a/extension/saved_searches/service-integration-creators.json +++ b/extension/saved_searches/service-integration-creators.json @@ -1,5 +1,5 @@ { "name": "Okta: API Service Integration Creators", "description": "Lists all API service integrations and their creators.", - "query": "MATCH p = (:Okta_Organization)-[:Okta_Contains]->(:Okta)-[:Okta_CreatorOf]->(:Okta_ApiServiceIntegration)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_Organization)-[:Okta_Contains]->(:Okta)-[:Okta_CreatorOf]->(:Okta_ApiServiceIntegration)\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/stale-privileged-accounts-direct.json b/extension/saved_searches/stale-privileged-accounts-direct.json index 4faf90e..0c3a2fe 100644 --- a/extension/saved_searches/stale-privileged-accounts-direct.json +++ b/extension/saved_searches/stale-privileged-accounts-direct.json @@ -1,5 +1,5 @@ { "name": "Okta: Stale Privileged Users (Direct)", "description": "Finds user accounts that have not logged in for at least 180 days and directly hold privileged role assignments.", - "query": "MATCH p = (u:Okta_User)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE u.lastLogin IS NULL OR datetime(u.lastLogin) <= datetime() - duration(\"P180D\")\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (user:Okta_User)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE user.lastLogin IS NULL OR datetime(user.lastLogin) <= datetime() - duration(\"P180D\")\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/stale-privileged-accounts-indirect.json b/extension/saved_searches/stale-privileged-accounts-indirect.json index 15be028..80d51fb 100644 --- a/extension/saved_searches/stale-privileged-accounts-indirect.json +++ b/extension/saved_searches/stale-privileged-accounts-indirect.json @@ -1,5 +1,5 @@ { "name": "Okta: Stale Privileged Users (Indirect)", "description": "Finds user accounts that have not logged in for at least 180 days and hold privileged role assignments through group membership.", - "query": "MATCH p = (u:Okta_User)-[:Okta_MemberOf]->(:Okta_Group)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE u.lastLogin IS NULL OR datetime(u.lastLogin) <= datetime() - duration(\"P180D\")\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (user:Okta_User)-[:Okta_MemberOf]->(:Okta_Group)-[:Okta_HasRoleAssignment]->(:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta)\nWHERE user.lastLogin IS NULL OR datetime(user.lastLogin) <= datetime() - duration(\"P180D\")\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/swa-applications.json b/extension/saved_searches/swa-applications.json index 7154142..121ff78 100644 --- a/extension/saved_searches/swa-applications.json +++ b/extension/saved_searches/swa-applications.json @@ -1,5 +1,5 @@ { "name": "Okta: Secure Web Authentication Applications", "description": "Secure Web Authentication (SWA) relationships between Okta users and their linked accounts in external applications.", - "query": "MATCH p = (:Okta_User)-[:Okta_SWA]->(n)\nWHERE NOT n:Okta\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_User)-[:Okta_SWA]->(target)\nWHERE NOT target:Okta\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/sync-relationships-inbound.json b/extension/saved_searches/sync-relationships-inbound.json index 71efbff..4176fe0 100644 --- a/extension/saved_searches/sync-relationships-inbound.json +++ b/extension/saved_searches/sync-relationships-inbound.json @@ -1,5 +1,5 @@ { "name": "Okta: Inbound User and Group Synchronization", "description": "Lists all inbound user and group synchronization relationships to Okta, including password synchronization across Org2Org setups.", - "query": "MATCH p = (n)-[:Okta_UserSync|Okta_MembershipSync|Okta_PasswordSync]->(:Okta_User:Okta_Group)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (source)-[:Okta_UserSync|Okta_MembershipSync|Okta_PasswordSync]->(target)\nWHERE target:Okta_User OR target:Okta_Group\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/sync-relationships-outbound.json b/extension/saved_searches/sync-relationships-outbound.json index a786b5f..f32aab0 100644 --- a/extension/saved_searches/sync-relationships-outbound.json +++ b/extension/saved_searches/sync-relationships-outbound.json @@ -1,5 +1,5 @@ { "name": "Okta: Outbound User and Group Synchronization", "description": "Lists all outbound user and group synchronization relationships from Okta, including password synchronization across Org2Org setups.", - "query": "MATCH p = (:Okta_User:Okta_Group)-[:Okta_UserSync|Okta_MembershipSync|Okta_PasswordSync]->(n)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (source)-[:Okta_UserSync|Okta_MembershipSync|Okta_PasswordSync]->(target)\nWHERE source:Okta_User OR source:Okta_Group\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/tier0.json b/extension/saved_searches/tier0.json index 0b0e953..46d8079 100644 --- a/extension/saved_searches/tier0.json +++ b/extension/saved_searches/tier0.json @@ -1,5 +1,5 @@ { "name": "Okta: Tier Zero Principals and Devices", "description": "Principals with SUPER_ADMIN or ORG_ADMIN role assignments and their associated devices.", - "query": "MATCH p = (:Okta)-[:Okta_HasRoleAssignment|Okta_MemberOf|Okta_DeviceOf*1..3]->(r:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta_Organization)\nWHERE r.type = \"SUPER_ADMIN\"\nOR r.type = \"ORG_ADMIN\"\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta)-[:Okta_HasRoleAssignment|Okta_MemberOf|Okta_DeviceOf*1..3]->(role:Okta_RoleAssignment)-[:Okta_ScopedTo]->(:Okta_Organization)\nWHERE role.type = \"SUPER_ADMIN\"\nOR role.type = \"ORG_ADMIN\"\nRETURN path\nLIMIT 1000" } diff --git a/extension/saved_searches/users-api-tokens.json b/extension/saved_searches/users-api-tokens.json index b278b81..6a15d8b 100644 --- a/extension/saved_searches/users-api-tokens.json +++ b/extension/saved_searches/users-api-tokens.json @@ -1,5 +1,5 @@ { "name": "Okta: Users with API Tokens", "description": "Retrieves all (privileged) users who have been assigned API tokens.", - "query": "MATCH p = (:Okta_ApiToken)-[:Okta_ApiTokenFor]->(:Okta_User)<-[:Okta_Contains]-(:Okta_Organization)\nRETURN p\nLIMIT 1000" + "query": "MATCH path = (:Okta_ApiToken)-[:Okta_ApiTokenFor]->(:Okta_User)<-[:Okta_Contains]-(:Okta_Organization)\nRETURN path\nLIMIT 1000" }