diff --git a/.openapi-generator/FILES b/.openapi-generator/FILES
index 1d586f4..c39d745 100644
--- a/.openapi-generator/FILES
+++ b/.openapi-generator/FILES
@@ -31,10 +31,18 @@ docs/Bundle.md
docs/BundleGroup.md
docs/BundleResource.md
docs/BundlesApi.md
+docs/Campaign.md
+docs/CampaignConfiguration.md
+docs/CampaignGroupAssetVisibilityPolicyEnum.md
+docs/CampaignRevokeOnEnum.md
+docs/CampaignStatusEnum.md
+docs/CampaignsApi.md
docs/Condition.md
docs/ConfigurationTemplate.md
docs/ConfigurationTemplatesApi.md
docs/CreateBundleInfo.md
+docs/CreateCampaignConfigurationInfo.md
+docs/CreateCampaignInfo.md
docs/CreateConfigurationTemplateInfo.md
docs/CreateDelegationRequest.md
docs/CreateEventStreamInfo.md
@@ -59,6 +67,7 @@ docs/CreateUARInfo.md
docs/Delegation.md
docs/DelegationsApi.md
docs/DenyRequestRequest.md
+docs/EntityAdminFilter.md
docs/EntityItemTypeEnum.md
docs/EntityNameFilter.md
docs/EntityTagFilter.md
@@ -102,6 +111,7 @@ docs/GroupRemoteInfoPagerdutyOnCallSchedule.md
docs/GroupRemoteInfoRootlyOnCallSchedule.md
docs/GroupRemoteInfoSlackUserGroup.md
docs/GroupRemoteInfoSnowflakeRole.md
+docs/GroupRemoteInfoTableauGroup.md
docs/GroupRemoteInfoTailscaleGroup.md
docs/GroupRemoteInfoTwingateGroup.md
docs/GroupRemoteInfoTwingateGroupSynced.md
@@ -118,6 +128,7 @@ docs/GroupsApi.md
docs/IdpGroupMapping.md
docs/IdpGroupMappingList.md
docs/IdpGroupMappingsApi.md
+docs/IdpStatusFilter.md
docs/MessageChannel.md
docs/MessageChannelIDList.md
docs/MessageChannelList.md
@@ -129,12 +140,19 @@ docs/OnCallScheduleIDList.md
docs/OnCallScheduleList.md
docs/OnCallScheduleProviderEnum.md
docs/OnCallSchedulesApi.md
+docs/OpalAccessPathEdgeFilter.md
+docs/OpalAccessPathQuery.md
+docs/OpalAccessPathQueryBody.md
+docs/OpalAccessPathQueryResults.md
+docs/OpalAccessPathResultEdge.md
+docs/OpalAccessPathResultNode.md
docs/OpalNodeQuery.md
docs/OpalNodeQueryBody.md
docs/OpalNodeQueryResults.md
docs/OpalQueriesApi.md
docs/OpalQueryResultEdge.md
docs/OpalQueryResultNode.md
+docs/OpalQueryResults.md
docs/Owner.md
docs/OwnersApi.md
docs/PageInfo.md
@@ -143,6 +161,7 @@ docs/PaginatedAssignedRequestList.md
docs/PaginatedBundleGroupList.md
docs/PaginatedBundleList.md
docs/PaginatedBundleResourceList.md
+docs/PaginatedCampaignsList.md
docs/PaginatedConfigurationTemplateList.md
docs/PaginatedDelegationsList.md
docs/PaginatedEventList.md
@@ -155,6 +174,9 @@ docs/PaginatedTagsList.md
docs/PaginatedTokensList.md
docs/PaginatedUARsList.md
docs/PaginatedUsersList.md
+docs/Paladin.md
+docs/PaladinApi.md
+docs/PaladinList.md
docs/PropagationStatus.md
docs/PropagationStatusEnum.md
docs/RDSEngineEnum.md
@@ -183,6 +205,8 @@ docs/ResourceAccessUser.md
docs/ResourceAccessUserList.md
docs/ResourceNHI.md
docs/ResourceRemoteInfo.md
+docs/ResourceRemoteInfoAlicloudEcsInstance.md
+docs/ResourceRemoteInfoAlicloudRamRole.md
docs/ResourceRemoteInfoAnthropicWorkspace.md
docs/ResourceRemoteInfoAwsAccount.md
docs/ResourceRemoteInfoAwsEc2Instance.md
@@ -271,11 +295,13 @@ docs/RolePermissionTargetTypeEnum.md
docs/RuleClauses.md
docs/RuleConjunction.md
docs/RuleDisjunction.md
+docs/RunOpalQueryRequest.md
docs/ScopedRolePermission.md
docs/ScopedRolePermissionList.md
docs/Session.md
docs/SessionsApi.md
docs/SessionsList.md
+docs/StopCampaignRequest.md
docs/StringMatchType.md
docs/SubEvent.md
docs/SyncError.md
@@ -296,6 +322,8 @@ docs/UARReviewerAssignmentPolicyEnum.md
docs/UARScope.md
docs/UarsApi.md
docs/UpdateAccessRuleInfo.md
+docs/UpdateCampaignConfigurationInfo.md
+docs/UpdateCampaignInfo.md
docs/UpdateConfigurationTemplateInfo.md
docs/UpdateEventStreamInfo.md
docs/UpdateGroupBindingInfo.md
@@ -330,6 +358,7 @@ opal_security/api/__init__.py
opal_security/api/access_rules_api.py
opal_security/api/apps_api.py
opal_security/api/bundles_api.py
+opal_security/api/campaigns_api.py
opal_security/api/configuration_templates_api.py
opal_security/api/delegations_api.py
opal_security/api/event_streams_api.py
@@ -342,6 +371,7 @@ opal_security/api/non_human_identities_api.py
opal_security/api/on_call_schedules_api.py
opal_security/api/opal_queries_api.py
opal_security/api/owners_api.py
+opal_security/api/paladin_api.py
opal_security/api/requests_api.py
opal_security/api/resources_api.py
opal_security/api/sessions_api.py
@@ -379,9 +409,16 @@ opal_security/models/aws_permission_set_metadata_aws_permission_set.py
opal_security/models/bundle.py
opal_security/models/bundle_group.py
opal_security/models/bundle_resource.py
+opal_security/models/campaign.py
+opal_security/models/campaign_configuration.py
+opal_security/models/campaign_group_asset_visibility_policy_enum.py
+opal_security/models/campaign_revoke_on_enum.py
+opal_security/models/campaign_status_enum.py
opal_security/models/condition.py
opal_security/models/configuration_template.py
opal_security/models/create_bundle_info.py
+opal_security/models/create_campaign_configuration_info.py
+opal_security/models/create_campaign_info.py
opal_security/models/create_configuration_template_info.py
opal_security/models/create_delegation_request.py
opal_security/models/create_event_stream_info.py
@@ -405,6 +442,7 @@ opal_security/models/create_tag_info.py
opal_security/models/create_uar_info.py
opal_security/models/delegation.py
opal_security/models/deny_request_request.py
+opal_security/models/entity_admin_filter.py
opal_security/models/entity_item_type_enum.py
opal_security/models/entity_name_filter.py
opal_security/models/entity_tag_filter.py
@@ -445,6 +483,7 @@ opal_security/models/group_remote_info_pagerduty_on_call_schedule.py
opal_security/models/group_remote_info_rootly_on_call_schedule.py
opal_security/models/group_remote_info_slack_user_group.py
opal_security/models/group_remote_info_snowflake_role.py
+opal_security/models/group_remote_info_tableau_group.py
opal_security/models/group_remote_info_tailscale_group.py
opal_security/models/group_remote_info_twingate_group.py
opal_security/models/group_remote_info_twingate_group_synced.py
@@ -459,6 +498,7 @@ opal_security/models/group_user_list.py
opal_security/models/group_with_access_level.py
opal_security/models/idp_group_mapping.py
opal_security/models/idp_group_mapping_list.py
+opal_security/models/idp_status_filter.py
opal_security/models/message_channel.py
opal_security/models/message_channel_id_list.py
opal_security/models/message_channel_list.py
@@ -467,11 +507,18 @@ opal_security/models/on_call_schedule.py
opal_security/models/on_call_schedule_id_list.py
opal_security/models/on_call_schedule_list.py
opal_security/models/on_call_schedule_provider_enum.py
+opal_security/models/opal_access_path_edge_filter.py
+opal_security/models/opal_access_path_query.py
+opal_security/models/opal_access_path_query_body.py
+opal_security/models/opal_access_path_query_results.py
+opal_security/models/opal_access_path_result_edge.py
+opal_security/models/opal_access_path_result_node.py
opal_security/models/opal_node_query.py
opal_security/models/opal_node_query_body.py
opal_security/models/opal_node_query_results.py
opal_security/models/opal_query_result_edge.py
opal_security/models/opal_query_result_node.py
+opal_security/models/opal_query_results.py
opal_security/models/owner.py
opal_security/models/page_info.py
opal_security/models/paginated_access_rules_list.py
@@ -479,6 +526,7 @@ opal_security/models/paginated_assigned_request_list.py
opal_security/models/paginated_bundle_group_list.py
opal_security/models/paginated_bundle_list.py
opal_security/models/paginated_bundle_resource_list.py
+opal_security/models/paginated_campaigns_list.py
opal_security/models/paginated_configuration_template_list.py
opal_security/models/paginated_delegations_list.py
opal_security/models/paginated_event_list.py
@@ -491,6 +539,8 @@ opal_security/models/paginated_tags_list.py
opal_security/models/paginated_tokens_list.py
opal_security/models/paginated_uars_list.py
opal_security/models/paginated_users_list.py
+opal_security/models/paladin.py
+opal_security/models/paladin_list.py
opal_security/models/propagation_status.py
opal_security/models/propagation_status_enum.py
opal_security/models/rds_engine_enum.py
@@ -518,6 +568,8 @@ opal_security/models/resource_access_user.py
opal_security/models/resource_access_user_list.py
opal_security/models/resource_nhi.py
opal_security/models/resource_remote_info.py
+opal_security/models/resource_remote_info_alicloud_ecs_instance.py
+opal_security/models/resource_remote_info_alicloud_ram_role.py
opal_security/models/resource_remote_info_anthropic_workspace.py
opal_security/models/resource_remote_info_aws_account.py
opal_security/models/resource_remote_info_aws_ec2_instance.py
@@ -605,10 +657,12 @@ opal_security/models/role_permission_target_type_enum.py
opal_security/models/rule_clauses.py
opal_security/models/rule_conjunction.py
opal_security/models/rule_disjunction.py
+opal_security/models/run_opal_query_request.py
opal_security/models/scoped_role_permission.py
opal_security/models/scoped_role_permission_list.py
opal_security/models/session.py
opal_security/models/sessions_list.py
+opal_security/models/stop_campaign_request.py
opal_security/models/string_match_type.py
opal_security/models/sub_event.py
opal_security/models/sync_error.py
@@ -626,6 +680,8 @@ opal_security/models/uar.py
opal_security/models/uar_reviewer_assignment_policy_enum.py
opal_security/models/uar_scope.py
opal_security/models/update_access_rule_info.py
+opal_security/models/update_campaign_configuration_info.py
+opal_security/models/update_campaign_info.py
opal_security/models/update_configuration_template_info.py
opal_security/models/update_event_stream_info.py
opal_security/models/update_group_binding_info.py
@@ -655,47 +711,37 @@ opal_security/models/webhook_credentials.py
opal_security/models/webhook_hmac_credential.py
opal_security/py.typed
opal_security/rest.py
-pyproject.toml
requirements.txt
setup.cfg
setup.py
test-requirements.txt
test/__init__.py
-test/test_access_entity_filters.py
-test/test_access_relationship_filters.py
-test/test_create_event_stream_info.py
-test/test_entity_item_type_enum.py
-test/test_entity_name_filter.py
-test/test_entity_tag_filter.py
-test/test_event_stream.py
-test/test_event_stream_connection.py
-test/test_event_stream_connection_type_enum.py
-test/test_event_stream_list.py
-test/test_event_streams_api.py
-test/test_group_remote_info_grafana_team.py
-test/test_group_remote_info_hubspot_team.py
-test/test_group_remote_info_slack_user_group.py
-test/test_group_remote_info_twingate_group_synced.py
-test/test_group_remote_info_zendesk_group.py
-test/test_group_remote_info_zendesk_organization.py
-test/test_opal_node_query.py
-test/test_opal_node_query_body.py
-test/test_opal_node_query_results.py
-test/test_opal_queries_api.py
-test/test_opal_query_result_edge.py
-test/test_opal_query_result_node.py
-test/test_paginated_access_rules_list.py
-test/test_resource_remote_info_grafana_dashboard.py
-test/test_resource_remote_info_grafana_folder.py
-test/test_resource_remote_info_grafana_role.py
-test/test_resource_remote_info_hubspot_role.py
-test/test_resource_remote_info_zendesk_role.py
-test/test_string_match_type.py
-test/test_update_event_stream_info.py
-test/test_user_attribute_selector.py
-test/test_webhook_api_key_credential.py
-test/test_webhook_api_key_location_enum.py
-test/test_webhook_auth_type_enum.py
-test/test_webhook_credentials.py
-test/test_webhook_hmac_credential.py
+test/test_campaign.py
+test/test_campaign_configuration.py
+test/test_campaign_group_asset_visibility_policy_enum.py
+test/test_campaign_revoke_on_enum.py
+test/test_campaign_status_enum.py
+test/test_campaigns_api.py
+test/test_create_campaign_configuration_info.py
+test/test_create_campaign_info.py
+test/test_entity_admin_filter.py
+test/test_group_remote_info_tableau_group.py
+test/test_idp_status_filter.py
+test/test_opal_access_path_edge_filter.py
+test/test_opal_access_path_query.py
+test/test_opal_access_path_query_body.py
+test/test_opal_access_path_query_results.py
+test/test_opal_access_path_result_edge.py
+test/test_opal_access_path_result_node.py
+test/test_opal_query_results.py
+test/test_paginated_campaigns_list.py
+test/test_paladin.py
+test/test_paladin_api.py
+test/test_paladin_list.py
+test/test_resource_remote_info_alicloud_ecs_instance.py
+test/test_resource_remote_info_alicloud_ram_role.py
+test/test_run_opal_query_request.py
+test/test_stop_campaign_request.py
+test/test_update_campaign_configuration_info.py
+test/test_update_campaign_info.py
tox.ini
diff --git a/README.md b/README.md
index 81688b4..4b3e825 100644
--- a/README.md
+++ b/README.md
@@ -160,6 +160,13 @@ Class | Method | HTTP request | Description
*BundlesApi* | [**remove_bundle_resource**](docs/BundlesApi.md#remove_bundle_resource) | **DELETE** /bundles/{bundle_id}/resources/{resource_id} |
*BundlesApi* | [**set_bundle_visibility**](docs/BundlesApi.md#set_bundle_visibility) | **PUT** /bundles/{bundle_id}/visibility |
*BundlesApi* | [**update_bundle**](docs/BundlesApi.md#update_bundle) | **PUT** /bundles/{bundle_id} |
+*CampaignsApi* | [**create_campaign**](docs/CampaignsApi.md#create_campaign) | **POST** /campaigns |
+*CampaignsApi* | [**end_campaign**](docs/CampaignsApi.md#end_campaign) | **POST** /campaigns/{campaign_id}/end | End campaign
+*CampaignsApi* | [**get_campaign**](docs/CampaignsApi.md#get_campaign) | **GET** /campaigns/{campaign_id} | Get campaign by ID
+*CampaignsApi* | [**get_campaigns**](docs/CampaignsApi.md#get_campaigns) | **GET** /campaigns |
+*CampaignsApi* | [**start_campaign**](docs/CampaignsApi.md#start_campaign) | **POST** /campaigns/{campaign_id}/start | Start campaign
+*CampaignsApi* | [**stop_campaign**](docs/CampaignsApi.md#stop_campaign) | **POST** /campaigns/{campaign_id}/stop | Stop campaign
+*CampaignsApi* | [**update_campaign**](docs/CampaignsApi.md#update_campaign) | **PUT** /campaigns/{campaign_id} | Update campaign
*ConfigurationTemplatesApi* | [**create_configuration_template**](docs/ConfigurationTemplatesApi.md#create_configuration_template) | **POST** /configuration-templates |
*ConfigurationTemplatesApi* | [**delete_configuration_template**](docs/ConfigurationTemplatesApi.md#delete_configuration_template) | **DELETE** /configuration-templates/{configuration_template_id} |
*ConfigurationTemplatesApi* | [**get_configuration_templates**](docs/ConfigurationTemplatesApi.md#get_configuration_templates) | **GET** /configuration-templates |
@@ -228,6 +235,8 @@ Class | Method | HTTP request | Description
*OwnersApi* | [**get_owners**](docs/OwnersApi.md#get_owners) | **GET** /owners | Get owners
*OwnersApi* | [**set_owner_users**](docs/OwnersApi.md#set_owner_users) | **PUT** /owners/{owner_id}/users |
*OwnersApi* | [**update_owners**](docs/OwnersApi.md#update_owners) | **PUT** /owners |
+*PaladinApi* | [**get_paladin**](docs/PaladinApi.md#get_paladin) | **GET** /paladin/{paladin_id} | Get Paladin by ID
+*PaladinApi* | [**get_paladin_from_name**](docs/PaladinApi.md#get_paladin_from_name) | **GET** /paladin/name/{paladin_name} | Get Paladins by name
*RequestsApi* | [**approve_request**](docs/RequestsApi.md#approve_request) | **POST** /requests/{id}/approve |
*RequestsApi* | [**create_request**](docs/RequestsApi.md#create_request) | **POST** /requests |
*RequestsApi* | [**create_request_comment**](docs/RequestsApi.md#create_request_comment) | **POST** /requests/{id}/comments |
@@ -282,6 +291,7 @@ Class | Method | HTTP request | Description
*UarsApi* | [**get_uars**](docs/UarsApi.md#get_uars) | **GET** /uars |
*UsersApi* | [**get_remote_users**](docs/UsersApi.md#get_remote_users) | **GET** /users/remote_users |
*UsersApi* | [**get_user_tags**](docs/UsersApi.md#get_user_tags) | **GET** /users/{user_id}/tags |
+*UsersApi* | [**get_user_whoami**](docs/UsersApi.md#get_user_whoami) | **GET** /users/whoami |
*UsersApi* | [**get_users**](docs/UsersApi.md#get_users) | **GET** /users |
*UsersApi* | [**user**](docs/UsersApi.md#user) | **GET** /user |
@@ -313,9 +323,16 @@ Class | Method | HTTP request | Description
- [Bundle](docs/Bundle.md)
- [BundleGroup](docs/BundleGroup.md)
- [BundleResource](docs/BundleResource.md)
+ - [Campaign](docs/Campaign.md)
+ - [CampaignConfiguration](docs/CampaignConfiguration.md)
+ - [CampaignGroupAssetVisibilityPolicyEnum](docs/CampaignGroupAssetVisibilityPolicyEnum.md)
+ - [CampaignRevokeOnEnum](docs/CampaignRevokeOnEnum.md)
+ - [CampaignStatusEnum](docs/CampaignStatusEnum.md)
- [Condition](docs/Condition.md)
- [ConfigurationTemplate](docs/ConfigurationTemplate.md)
- [CreateBundleInfo](docs/CreateBundleInfo.md)
+ - [CreateCampaignConfigurationInfo](docs/CreateCampaignConfigurationInfo.md)
+ - [CreateCampaignInfo](docs/CreateCampaignInfo.md)
- [CreateConfigurationTemplateInfo](docs/CreateConfigurationTemplateInfo.md)
- [CreateDelegationRequest](docs/CreateDelegationRequest.md)
- [CreateEventStreamInfo](docs/CreateEventStreamInfo.md)
@@ -339,6 +356,7 @@ Class | Method | HTTP request | Description
- [CreateUARInfo](docs/CreateUARInfo.md)
- [Delegation](docs/Delegation.md)
- [DenyRequestRequest](docs/DenyRequestRequest.md)
+ - [EntityAdminFilter](docs/EntityAdminFilter.md)
- [EntityItemTypeEnum](docs/EntityItemTypeEnum.md)
- [EntityNameFilter](docs/EntityNameFilter.md)
- [EntityTagFilter](docs/EntityTagFilter.md)
@@ -379,6 +397,7 @@ Class | Method | HTTP request | Description
- [GroupRemoteInfoRootlyOnCallSchedule](docs/GroupRemoteInfoRootlyOnCallSchedule.md)
- [GroupRemoteInfoSlackUserGroup](docs/GroupRemoteInfoSlackUserGroup.md)
- [GroupRemoteInfoSnowflakeRole](docs/GroupRemoteInfoSnowflakeRole.md)
+ - [GroupRemoteInfoTableauGroup](docs/GroupRemoteInfoTableauGroup.md)
- [GroupRemoteInfoTailscaleGroup](docs/GroupRemoteInfoTailscaleGroup.md)
- [GroupRemoteInfoTwingateGroup](docs/GroupRemoteInfoTwingateGroup.md)
- [GroupRemoteInfoTwingateGroupSynced](docs/GroupRemoteInfoTwingateGroupSynced.md)
@@ -393,6 +412,7 @@ Class | Method | HTTP request | Description
- [GroupWithAccessLevel](docs/GroupWithAccessLevel.md)
- [IdpGroupMapping](docs/IdpGroupMapping.md)
- [IdpGroupMappingList](docs/IdpGroupMappingList.md)
+ - [IdpStatusFilter](docs/IdpStatusFilter.md)
- [MessageChannel](docs/MessageChannel.md)
- [MessageChannelIDList](docs/MessageChannelIDList.md)
- [MessageChannelList](docs/MessageChannelList.md)
@@ -401,11 +421,18 @@ Class | Method | HTTP request | Description
- [OnCallScheduleIDList](docs/OnCallScheduleIDList.md)
- [OnCallScheduleList](docs/OnCallScheduleList.md)
- [OnCallScheduleProviderEnum](docs/OnCallScheduleProviderEnum.md)
+ - [OpalAccessPathEdgeFilter](docs/OpalAccessPathEdgeFilter.md)
+ - [OpalAccessPathQuery](docs/OpalAccessPathQuery.md)
+ - [OpalAccessPathQueryBody](docs/OpalAccessPathQueryBody.md)
+ - [OpalAccessPathQueryResults](docs/OpalAccessPathQueryResults.md)
+ - [OpalAccessPathResultEdge](docs/OpalAccessPathResultEdge.md)
+ - [OpalAccessPathResultNode](docs/OpalAccessPathResultNode.md)
- [OpalNodeQuery](docs/OpalNodeQuery.md)
- [OpalNodeQueryBody](docs/OpalNodeQueryBody.md)
- [OpalNodeQueryResults](docs/OpalNodeQueryResults.md)
- [OpalQueryResultEdge](docs/OpalQueryResultEdge.md)
- [OpalQueryResultNode](docs/OpalQueryResultNode.md)
+ - [OpalQueryResults](docs/OpalQueryResults.md)
- [Owner](docs/Owner.md)
- [PageInfo](docs/PageInfo.md)
- [PaginatedAccessRulesList](docs/PaginatedAccessRulesList.md)
@@ -413,6 +440,7 @@ Class | Method | HTTP request | Description
- [PaginatedBundleGroupList](docs/PaginatedBundleGroupList.md)
- [PaginatedBundleList](docs/PaginatedBundleList.md)
- [PaginatedBundleResourceList](docs/PaginatedBundleResourceList.md)
+ - [PaginatedCampaignsList](docs/PaginatedCampaignsList.md)
- [PaginatedConfigurationTemplateList](docs/PaginatedConfigurationTemplateList.md)
- [PaginatedDelegationsList](docs/PaginatedDelegationsList.md)
- [PaginatedEventList](docs/PaginatedEventList.md)
@@ -425,6 +453,8 @@ Class | Method | HTTP request | Description
- [PaginatedTokensList](docs/PaginatedTokensList.md)
- [PaginatedUARsList](docs/PaginatedUARsList.md)
- [PaginatedUsersList](docs/PaginatedUsersList.md)
+ - [Paladin](docs/Paladin.md)
+ - [PaladinList](docs/PaladinList.md)
- [PropagationStatus](docs/PropagationStatus.md)
- [PropagationStatusEnum](docs/PropagationStatusEnum.md)
- [RDSEngineEnum](docs/RDSEngineEnum.md)
@@ -452,6 +482,8 @@ Class | Method | HTTP request | Description
- [ResourceAccessUserList](docs/ResourceAccessUserList.md)
- [ResourceNHI](docs/ResourceNHI.md)
- [ResourceRemoteInfo](docs/ResourceRemoteInfo.md)
+ - [ResourceRemoteInfoAlicloudEcsInstance](docs/ResourceRemoteInfoAlicloudEcsInstance.md)
+ - [ResourceRemoteInfoAlicloudRamRole](docs/ResourceRemoteInfoAlicloudRamRole.md)
- [ResourceRemoteInfoAnthropicWorkspace](docs/ResourceRemoteInfoAnthropicWorkspace.md)
- [ResourceRemoteInfoAwsAccount](docs/ResourceRemoteInfoAwsAccount.md)
- [ResourceRemoteInfoAwsEc2Instance](docs/ResourceRemoteInfoAwsEc2Instance.md)
@@ -539,10 +571,12 @@ Class | Method | HTTP request | Description
- [RuleClauses](docs/RuleClauses.md)
- [RuleConjunction](docs/RuleConjunction.md)
- [RuleDisjunction](docs/RuleDisjunction.md)
+ - [RunOpalQueryRequest](docs/RunOpalQueryRequest.md)
- [ScopedRolePermission](docs/ScopedRolePermission.md)
- [ScopedRolePermissionList](docs/ScopedRolePermissionList.md)
- [Session](docs/Session.md)
- [SessionsList](docs/SessionsList.md)
+ - [StopCampaignRequest](docs/StopCampaignRequest.md)
- [StringMatchType](docs/StringMatchType.md)
- [SubEvent](docs/SubEvent.md)
- [SyncError](docs/SyncError.md)
@@ -560,6 +594,8 @@ Class | Method | HTTP request | Description
- [UARReviewerAssignmentPolicyEnum](docs/UARReviewerAssignmentPolicyEnum.md)
- [UARScope](docs/UARScope.md)
- [UpdateAccessRuleInfo](docs/UpdateAccessRuleInfo.md)
+ - [UpdateCampaignConfigurationInfo](docs/UpdateCampaignConfigurationInfo.md)
+ - [UpdateCampaignInfo](docs/UpdateCampaignInfo.md)
- [UpdateConfigurationTemplateInfo](docs/UpdateConfigurationTemplateInfo.md)
- [UpdateEventStreamInfo](docs/UpdateEventStreamInfo.md)
- [UpdateGroupBindingInfo](docs/UpdateGroupBindingInfo.md)
diff --git a/api/openapi.yaml b/api/openapi.yaml
index b1418bc..3942fc3 100644
--- a/api/openapi.yaml
+++ b/api/openapi.yaml
@@ -20,6 +20,8 @@ tags:
description: Operations related to apps
- name: bundles
description: Operations related to bundles
+ - name: campaigns
+ description: Operations related to access review campaigns
- name: configuration-templates
description: Operations related to configuration templates
- name: delegations
@@ -48,6 +50,9 @@ tags:
description: Operations related to requests
- name: resources
description: Operations related to resources
+ - name: paladin
+ description: Operations related to Paladin
+
- name: sessions
description: Operations related to sessions
- name: tags
@@ -55,7 +60,8 @@ tags:
- name: tokens
description: Operations related to API tokens
- name: uars
- description: Operations related to UARs
+ description:
+ Operations related to UARs. Deprecated in favor of the `campaigns` API.
- name: users
description: Operations related to users
paths:
@@ -598,6 +604,329 @@ paths:
- BearerAuth: []
tags:
- bundles
+ /campaigns:
+ get:
+ description: Returns a list of `Campaign` objects.
+ operationId: getCampaigns
+ parameters:
+ - description: The pagination cursor value.
+ example: cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw
+ explode: true
+ in: query
+ name: cursor
+ required: false
+ schema:
+ type: string
+ style: form
+ - description: Number of results to return per page. Default is 200.
+ example: 200
+ explode: true
+ in: query
+ name: page_size
+ required: false
+ schema:
+ type: integer
+ maximum: 1000
+ style: form
+ - description: Campaign name to filter by. Returns campaigns whose names contain this substring (case-insensitive).
+ example: Q3 Access Review
+ explode: true
+ in: query
+ name: name
+ required: false
+ schema:
+ type: string
+ style: form
+ - description: Filter by campaign status. Status is derived from lifecycle timestamps and review progress.
+ example: ONGOING
+ explode: true
+ in: query
+ name: status
+ required: false
+ schema:
+ $ref: "#/components/schemas/CampaignStatusEnum"
+ style: form
+ - description: Include campaigns created after this timestamp (exclusive). ISO 8601 format.
+ example: 2026-01-01T00:00:00Z
+ explode: true
+ in: query
+ name: created_at_after
+ required: false
+ schema:
+ type: string
+ format: date-time
+ style: form
+ - description: Include campaigns created before this timestamp (exclusive). ISO 8601 format.
+ example: 2026-12-31T23:59:59Z
+ explode: true
+ in: query
+ name: created_at_before
+ required: false
+ schema:
+ type: string
+ format: date-time
+ style: form
+ - description: Include campaigns started after this timestamp (exclusive). ISO 8601 format.
+ example: 2026-01-01T00:00:00Z
+ explode: true
+ in: query
+ name: started_at_after
+ required: false
+ schema:
+ type: string
+ format: date-time
+ style: form
+ - description: Include campaigns started before this timestamp (exclusive). ISO 8601 format.
+ example: 2026-12-31T23:59:59Z
+ explode: true
+ in: query
+ name: started_at_before
+ required: false
+ schema:
+ type: string
+ format: date-time
+ style: form
+ - description: Include campaigns ended after this timestamp (exclusive). ISO 8601 format.
+ example: 2026-01-01T00:00:00Z
+ explode: true
+ in: query
+ name: ended_at_after
+ required: false
+ schema:
+ type: string
+ format: date-time
+ style: form
+ - description: Include campaigns ended before this timestamp (exclusive). ISO 8601 format.
+ example: 2026-12-31T23:59:59Z
+ explode: true
+ in: query
+ name: ended_at_before
+ required: false
+ schema:
+ type: string
+ format: date-time
+ style: form
+ - description: Include campaigns stopped after this timestamp (exclusive). ISO 8601 format.
+ example: 2026-01-01T00:00:00Z
+ explode: true
+ in: query
+ name: stopped_at_after
+ required: false
+ schema:
+ type: string
+ format: date-time
+ style: form
+ - description: Include campaigns stopped before this timestamp (exclusive). ISO 8601 format.
+ example: 2026-12-31T23:59:59Z
+ explode: true
+ in: query
+ name: stopped_at_before
+ required: false
+ schema:
+ type: string
+ format: date-time
+ style: form
+ responses:
+ "200":
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/PaginatedCampaignsList"
+ description: A list of campaigns for your organization.
+ security:
+ - BearerAuth: []
+ tags:
+ - campaigns
+ post:
+ description: |
+ Creates a campaign. Campaign scope only supports direct access edges:
+ `configuration.query.edgeFilter.directOnly` defaults to `true`, is
+ always stored as `true`, and passing `false` returns 400.
+ operationId: createCampaign
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/CreateCampaignInfo"
+ responses:
+ "201":
+ description: The campaign successfully created.
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Campaign"
+ security:
+ - BearerAuth: []
+ tags:
+ - campaigns
+ /campaigns/{campaign_id}:
+ get:
+ summary: Get campaign by ID
+ description: Returns a `Campaign` object.
+ operationId: getCampaign
+ parameters:
+ - description: The ID of the campaign.
+ example: f454d283-ca87-4a8a-bdbb-df212eca5353
+ explode: true
+ in: path
+ name: campaign_id
+ required: true
+ schema:
+ format: uuid
+ type: string
+ style: simple
+ responses:
+ "200":
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Campaign"
+ description: The requested `Campaign`.
+ security:
+ - BearerAuth: []
+ tags:
+ - campaigns
+ put:
+ summary: Update campaign
+ description: |
+ Partially updates a campaign. Omitted fields are left unchanged.
+ `configuration.query` and `configuration.reviewer_assignment_policy`
+ cannot be updated after create; including either field returns 400.
+ `configuration.cron_expression` and
+ `configuration.recurring_duration_days` may only be set on template
+ campaigns; setting them on a one-off campaign returns 400.
+ `configuration.is_template` is immutable and not accepted on update.
+ Configuration updates on a stopped or ended (non-template) campaign
+ return 400. Name-only updates are still allowed.
+ operationId: updateCampaign
+ parameters:
+ - description: The ID of the campaign.
+ example: f454d283-ca87-4a8a-bdbb-df212eca5353
+ explode: true
+ in: path
+ name: campaign_id
+ required: true
+ schema:
+ format: uuid
+ type: string
+ style: simple
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/UpdateCampaignInfo"
+ responses:
+ "200":
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Campaign"
+ description: The updated `Campaign`.
+ security:
+ - BearerAuth: []
+ tags:
+ - campaigns
+ /campaigns/{campaign_id}/start:
+ post:
+ summary: Start campaign
+ description: |
+ Starts a draft campaign immediately, setting `started_at` and
+ `started_by_user_id`. Returns 400 if the campaign is not in draft
+ state, or if it is a recurring template (`is_template: true`) —
+ templates spawn draft campaigns on their schedule and cannot be
+ started directly.
+ operationId: startCampaign
+ parameters:
+ - description: The ID of the campaign.
+ example: f454d283-ca87-4a8a-bdbb-df212eca5353
+ explode: true
+ in: path
+ name: campaign_id
+ required: true
+ schema:
+ format: uuid
+ type: string
+ style: simple
+ responses:
+ "200":
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Campaign"
+ description: The started `Campaign`.
+ security:
+ - BearerAuth: []
+ tags:
+ - campaigns
+ /campaigns/{campaign_id}/stop:
+ post:
+ summary: Stop campaign
+ description: |
+ Stops an ongoing campaign immediately, setting `stopped_at` and
+ `stopped_by_user_id`. Returns 400 if the campaign has not started or
+ has already stopped.
+ operationId: stopCampaign
+ parameters:
+ - description: The ID of the campaign.
+ example: f454d283-ca87-4a8a-bdbb-df212eca5353
+ explode: true
+ in: path
+ name: campaign_id
+ required: true
+ schema:
+ format: uuid
+ type: string
+ style: simple
+ requestBody:
+ required: false
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/StopCampaignRequest"
+ responses:
+ "200":
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Campaign"
+ description: The stopped `Campaign`.
+ security:
+ - BearerAuth: []
+ tags:
+ - campaigns
+ /campaigns/{campaign_id}/end:
+ post:
+ summary: End campaign
+ description: |
+ Ends a stopped campaign, setting `ended_at` and `ended_by_user_id`,
+ applying pending access changes, and queuing report generation.
+ Returns 400 unless the campaign is started and stopped and not already
+ ended.
+ operationId: endCampaign
+ parameters:
+ - description: The ID of the campaign.
+ example: f454d283-ca87-4a8a-bdbb-df212eca5353
+ explode: true
+ in: path
+ name: campaign_id
+ required: true
+ schema:
+ format: uuid
+ type: string
+ style: simple
+ responses:
+ "200":
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Campaign"
+ description: The ended `Campaign`.
+ security:
+ - BearerAuth: []
+ tags:
+ - campaigns
/configuration-templates:
get:
description: Returns a list of `ConfigurationTemplate` objects.
@@ -1706,7 +2035,13 @@ paths:
schema:
type: string
style: form
- - description: Number of results to return per page. Default is 200.
+ - description:
+ Number of results to return per page, up to 1000. When set (or when a
+ cursor is provided), the response contains a single page of results and
+ a `next` cursor; the default page size is 200. When both page_size and
+ cursor are omitted, the entire group membership is returned in one
+ response with no `next` cursor. For large groups, prefer setting
+ page_size and following `next`.
example: 200
explode: true
in: query
@@ -4044,6 +4379,61 @@ paths:
- BearerAuth: []
tags:
- resources
+ /paladin/{paladin_id}:
+ get:
+ summary: Get Paladin by ID
+ description: Returns a `Paladin` object.
+ operationId: getPaladin
+ parameters:
+ - description: The ID of the Paladin.
+ example: 32acc112-21ff-4669-91c2-21e27683eaa1
+ explode: true
+ in: path
+ name: paladin_id
+ required: true
+ schema:
+ format: uuid
+ type: string
+ style: simple
+ responses:
+ "200":
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/Paladin"
+ description: The Paladin associated with the passed-in ID.
+ security:
+ - BearerAuth: []
+ tags:
+ - paladin
+ /paladin/name/{paladin_name}:
+ get:
+ summary: Get Paladins by name
+ description:
+ Returns all Paladins whose name exactly matches the given name. Names
+ are not unique, so the result is a list and may be empty.
+ operationId: getPaladinFromName
+ parameters:
+ - description: The name of the Paladin.
+ example: paladin-agent-1
+ explode: true
+ in: path
+ name: paladin_name
+ required: true
+ schema:
+ type: string
+ style: simple
+ responses:
+ "200":
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/PaladinList"
+ description: The list of Paladins matching the passed-in name.
+ security:
+ - BearerAuth: []
+ tags:
+ - paladin
/sessions:
get:
description: Returns a list of `Session` objects.
@@ -4230,16 +4620,32 @@ paths:
- BearerAuth: []
tags:
- users
- /users/{user_id}/tags:
+ /users/whoami:
get:
- description: Returns all tags applied to the user.
- operationId: get_user_tags
- parameters:
- - description: The ID of the user whose tags to return.
- name: user_id
- example: 1b978423-db0a-4037-a4cf-f79c60cb67b3
- explode: false
- in: path
+ description:
+ Returns the user that the provided API token authenticates as.
+ operationId: getUserWhoami
+ responses:
+ "200":
+ content:
+ application/json:
+ schema:
+ $ref: "#/components/schemas/User"
+ description: The user that the API token authenticates as.
+ security:
+ - BearerAuth: []
+ tags:
+ - users
+ /users/{user_id}/tags:
+ get:
+ description: Returns all tags applied to the user.
+ operationId: get_user_tags
+ parameters:
+ - description: The ID of the user whose tags to return.
+ name: user_id
+ example: 1b978423-db0a-4037-a4cf-f79c60cb67b3
+ explode: false
+ in: path
required: true
schema:
format: uuid
@@ -4864,8 +5270,9 @@ paths:
/queries/run:
post:
summary: Run an ad-hoc OpalQuery
- description: Runs an ad-hoc OpalQuery and returns the results. Currently
- supports NODE queries (users, resources, groups). This endpoint is only
+ description: Runs an ad-hoc OpalQuery and returns the results. Supports
+ NODE queries (users, resources, groups) and ACCESS_PATH queries
+ (principal-to-entitlement access edges). This endpoint is only
available to our OpalQuery beta group. Please contact Opal support if
you'd like to be added to the beta.
operationId: runOpalQuery
@@ -4976,7 +5383,9 @@ paths:
- tokens
/uars:
get:
- description: Returns a list of `UAR` objects.
+ deprecated: true
+ description:
+ Returns a list of `UAR` objects. Deprecated in favor of `GET /campaigns`.
operationId: getUARs
parameters:
- description: The pagination cursor value.
@@ -5011,7 +5420,9 @@ paths:
- uars
/uar:
post:
- description: Starts a User Access Review.
+ deprecated: true
+ description:
+ Starts a User Access Review. Deprecated in favor of `POST /campaigns`.
operationId: create_uar
requestBody:
description: The settings of the UAR.
@@ -5033,7 +5444,10 @@ paths:
- uars
/uar/{uar_id}:
get:
- description: Retrieves a specific UAR.
+ deprecated: true
+ description:
+ Retrieves a specific UAR. Deprecated in favor of
+ `GET /campaigns/{campaign_id}`.
operationId: get_uar
parameters:
- description: The ID of the UAR.
@@ -5265,6 +5679,10 @@ components:
$ref: "#/components/schemas/EntityNameFilter"
entityTag:
$ref: "#/components/schemas/EntityTagFilter"
+ hrIdpStatus:
+ $ref: "#/components/schemas/IdpStatusFilter"
+ entityAdminOwner:
+ $ref: "#/components/schemas/EntityAdminFilter"
entityIDs:
type: array
description: Filter by specific entity UUIDs.
@@ -5318,10 +5736,12 @@ components:
determines which query schema applies.
oneOf:
- $ref: "#/components/schemas/OpalNodeQuery"
+ - $ref: "#/components/schemas/OpalAccessPathQuery"
discriminator:
propertyName: type
mapping:
NODE: "#/components/schemas/OpalNodeQuery"
+ ACCESS_PATH: "#/components/schemas/OpalAccessPathQuery"
# example:
# type: NODE
# query:
@@ -5436,10 +5856,12 @@ components:
which result schema applies and mirrors the `type` field on the request.
oneOf:
- $ref: "#/components/schemas/OpalNodeQueryResults"
+ - $ref: "#/components/schemas/OpalAccessPathQueryResults"
discriminator:
propertyName: type
mapping:
NODE: "#/components/schemas/OpalNodeQueryResults"
+ ACCESS_PATH: "#/components/schemas/OpalAccessPathQueryResults"
OpalNodeQueryResults:
type: object
@@ -5463,6 +5885,189 @@ components:
pageInfo:
$ref: "#/components/schemas/PageInfo"
+ OpalAccessPathQuery:
+ type: object
+ required:
+ - type
+ description:
+ Request body for an ACCESS_PATH-type OpalQuery. Returns principal-to-
+ entitlement access paths matching the given edge filters.
+ example:
+ type: ACCESS_PATH
+ query:
+ principalFilter:
+ entityTypes: [USER]
+ entitlementFilter:
+ entityItemTypes: [AWS_IAM_ROLE]
+ edgeFilter:
+ directOnly: true
+ first: 50
+ properties:
+ type:
+ type: string
+ enum:
+ - ACCESS_PATH
+ query:
+ $ref: "#/components/schemas/OpalAccessPathQueryBody"
+ first:
+ type: integer
+ description: Maximum number of results to return. Defaults to 200.
+ example: 200
+ after:
+ type: string
+ description:
+ Opaque cursor from a previous ACCESS_PATH response to fetch the
+ next page of results.
+ includeCount:
+ type: boolean
+ description:
+ When true, populate totalCount in the response. Defaults to false.
+ example: false
+
+ OpalAccessPathQueryBody:
+ type: object
+ description:
+ Edge-query filters for an ACCESS_PATH OpalQuery. At least one of
+ principalFilter or entitlementFilter is required.
+ properties:
+ principalFilter:
+ $ref: "#/components/schemas/AccessEntityFilters"
+ entitlementFilter:
+ $ref: "#/components/schemas/AccessEntityFilters"
+ principalAccessFilters:
+ description: >
+ Advanced access filter on the principal side of each path. Restricts
+ results to principals that additionally satisfy these access-edge
+ constraints: `hasAccessTo` keeps only principals that also have
+ access to a matching entity; `isAccessibleBy` keeps only principals
+ that are also accessible by a matching entity. Only takes effect when
+ `principalFilter` is also supplied (it refines that filter); on its
+ own it has no effect.
+ $ref: "#/components/schemas/AccessRelationshipFilters"
+ entitlementAccessFilters:
+ description: >
+ Advanced access filter on the entitlement side of each path.
+ Restricts results to entitlements that additionally satisfy these
+ access-edge constraints: `hasAccessTo` keeps only entitlements that
+ also have access to a matching entity; `isAccessibleBy` keeps only
+ entitlements that are also accessible by a matching entity. Only
+ takes effect when `entitlementFilter` is also supplied (it refines
+ that filter); on its own it has no effect.
+ $ref: "#/components/schemas/AccessRelationshipFilters"
+ accessLevelRemoteIds:
+ type: array
+ description: Filter by access-level remote IDs on the terminal edge.
+ items:
+ type: string
+ accessLevelNames:
+ type: array
+ description: Filter by access-level display names on the terminal edge.
+ items:
+ type: string
+ edgeFilter:
+ $ref: "#/components/schemas/OpalAccessPathEdgeFilter"
+
+ OpalAccessPathEdgeFilter:
+ type: object
+ description: Constraints on the access path edges themselves.
+ properties:
+ directOnly:
+ type: boolean
+ description:
+ When true, only return direct (depth-1) principal-to-entitlement
+ edges.
+ example: true
+ accessDurationType:
+ type: string
+ description: Constrain results by whether the terminal access expires.
+ enum:
+ - EXPIRING_ONLY
+ - PERMANENT_ONLY
+ example: EXPIRING_ONLY
+
+ OpalAccessPathResultNode:
+ type: object
+ required:
+ - principalId
+ - entitlementId
+ - depth
+ - path
+ description: A matched access path from an ACCESS_PATH OpalQuery.
+ properties:
+ principalId:
+ type: string
+ format: uuid
+ description: The principal entity ID.
+ entitlementId:
+ type: string
+ format: uuid
+ description: The entitlement entity ID.
+ accessLevelRemoteId:
+ type: string
+ nullable: true
+ description: Remote ID of the terminal access level.
+ accessLevelName:
+ type: string
+ nullable: true
+ description: Display name of the terminal access level.
+ expiration:
+ type: string
+ format: date-time
+ nullable: true
+ description: Expiration of the terminal access, if any.
+ depth:
+ type: integer
+ description: Number of hops from principal to entitlement (path length - 1).
+ path:
+ type: array
+ description: Entity IDs along the path from principal to entitlement.
+ items:
+ type: string
+ format: uuid
+
+ OpalAccessPathResultEdge:
+ type: object
+ required:
+ - node
+ - cursor
+ description:
+ A single ACCESS_PATH result edge containing the matched path and its
+ pagination cursor.
+ properties:
+ node:
+ $ref: "#/components/schemas/OpalAccessPathResultNode"
+ cursor:
+ type: string
+ description: Opaque cursor for this path, used for pagination.
+
+ OpalAccessPathQueryResults:
+ type: object
+ required:
+ - type
+ - edges
+ - pageInfo
+ description:
+ Paginated results of an ACCESS_PATH-type OpalQuery — one edge per
+ matched principal-to-entitlement access path.
+ properties:
+ type:
+ type: string
+ enum:
+ - ACCESS_PATH
+ edges:
+ type: array
+ description: List of matched access paths.
+ items:
+ $ref: "#/components/schemas/OpalAccessPathResultEdge"
+ pageInfo:
+ $ref: "#/components/schemas/PageInfo"
+ totalCount:
+ type: integer
+ nullable: true
+ description:
+ Exact total number of matching paths when includeCount was true on
+ the request; otherwise null.
+
AccessRelationshipFilters:
type: object
description: >
@@ -5518,6 +6123,49 @@ components:
format: uuid
description: If specified, filters by tags associated with this connection.
+ IdpStatusFilter:
+ type: object
+ description: >
+ Filters USER entities by their HR/IDP lifecycle status. Only applies to
+ USER entities; GROUP and RESOURCE entities never match, in either
+ polarity. `statuses` combine with OR. `not` inverts the match within the
+ user domain (e.g. "IDP status is NOT active"), so it still returns only
+ users rather than sweeping in groups/resources.
+ properties:
+ statuses:
+ type: array
+ description: Match users whose HR/IDP status is one of these values.
+ items:
+ $ref: "#/components/schemas/UserHrIdpStatusEnum"
+ not:
+ type: boolean
+ description:
+ Invert the match within the user domain (e.g. "IDP status is NOT
+ active").
+
+ EntityAdminFilter:
+ type: object
+ required:
+ - ownerIDs
+ description: >
+ Filters GROUP and RESOURCE entities by their admin owner. USER entities
+ never match, in either polarity. `not` inverts the match within the
+ resource/group domain (self-negating, like IdpStatusFilter): omit it (or
+ false) to include entities owned by the given owners, set it true to
+ exclude them.
+ properties:
+ ownerIDs:
+ type: array
+ description: The owner (group) UUIDs to match entities against.
+ items:
+ type: string
+ format: uuid
+ not:
+ type: boolean
+ description:
+ Invert the match — return resources/groups NOT owned by the given
+ owners.
+
StringMatchType:
type: string
description: How to match a string value against entity names.
@@ -5634,63 +6282,650 @@ components:
type: array
filter_operator:
description:
- Specifies whether entities must match all (AND) or any (OR) of the
- filters.
+ Specifies whether entities must match all (AND) or any (OR) of the
+ filters.
+ type: string
+ enum: [ANY, ALL]
+ entities:
+ description:
+ This access review will include resources and groups with ids in
+ the given strings.
+ items:
+ example: f454d283-as87-4a8a-bdbb-df212eca5353
+ type: string
+ format: uuid
+ type: array
+ apps:
+ description: This access review will include items in the specified applications
+ items:
+ example: pas2d283-ca87-4a8a-bdbb-df212eca5353
+ type: string
+ format: uuid
+ type: array
+ admins:
+ description:
+ This access review will include resources and groups who are owned
+ by one of the owners corresponding to the given IDs.
+ items:
+ example: f454d283-ca87-4a8a-bdbb-df212eca5353
+ type: string
+ format: uuid
+ type: array
+ group_types:
+ description: This access review will include items of the specified group types
+ type: array
+ items:
+ $ref: "#/components/schemas/GroupTypeEnum"
+ resource_types:
+ description: This access review will include items of the specified resource types
+ type: array
+ items:
+ $ref: "#/components/schemas/ResourceTypeEnum"
+ include_group_bindings:
+ type: boolean
+ example: False
+ tags:
+ description:
+ This access review will include resources and groups who are tagged
+ with one of the given tags.
+ items:
+ $ref: "#/components/schemas/TagFilter"
+ type: array
+ names:
+ description:
+ This access review will include resources and groups whose name
+ contains one of the given strings.
+ items:
+ example: demo
+ type: string
+ type: array
+ type: object
+ CampaignStatusEnum:
+ description: The current status of a campaign.
+ enum:
+ - DRAFT
+ - ONGOING
+ - COMPLETED
+ - STOPPED
+ - ENDED
+ example: ONGOING
+ type: string
+ CampaignRevokeOnEnum:
+ description: When access decisions take effect during a campaign.
+ enum:
+ - ACTION
+ - END
+ - NONE
+ example: END
+ type: string
+ CampaignGroupAssetVisibilityPolicyEnum:
+ description: Controls what group assets reviewers can see during the campaign.
+ enum:
+ - STRICT
+ - VIEW_VISIBLE_AND_ASSIGNED
+ - VIEW_ALL
+ example: STRICT
+ type: string
+ CampaignConfiguration:
+ description: Configuration for an access review campaign.
+ example:
+ configuration_id: 39a4d283-ca87-4a8a-bdbb-df212eca5fdb
+ created_at: 2026-07-01T00:00:00Z
+ updated_at: 2026-07-01T00:00:00Z
+ query: null
+ reviewer_assignment_policy: MANUALLY
+ allow_self_review: false
+ send_reviewer_assignment_notification: true
+ allow_reviewer_reassignment: false
+ start_date: null
+ end_date: 2026-09-30T00:00:00Z
+ timezone: America/Los_Angeles
+ revoke_on: END
+ reminder_schedule: [7, 3, 1]
+ reminder_include_manager: true
+ require_reason_on_denial: false
+ hide_ai_suggestions: false
+ custom_start_message: null
+ group_asset_visibility_policy: STRICT
+ is_template: false
+ cron_expression: null
+ next_scheduled_run: null
+ last_scheduled_run: null
+ recurring_duration_days: null
+ properties:
+ configuration_id:
+ description: The ID of the campaign configuration.
+ example: 39a4d283-ca87-4a8a-bdbb-df212eca5fdb
+ format: uuid
+ type: string
+ created_at:
+ description: The creation time of the configuration.
+ example: 2026-07-01T00:00:00Z
+ format: date-time
+ type: string
+ updated_at:
+ description: The last updated time of the configuration.
+ example: 2026-07-01T00:00:00Z
+ format: date-time
+ type: string
+ query:
+ description:
+ Access-path query defining the scope of access to review. Uses the
+ same principalFilter / entitlementFilter shape as ACCESS_PATH
+ OpalQuery.
+ allOf:
+ - $ref: "#/components/schemas/OpalAccessPathQueryBody"
+ nullable: true
+ reviewer_assignment_policy:
+ $ref: "#/components/schemas/UARReviewerAssignmentPolicyEnum"
+ allow_self_review:
+ description: Whether reviewers can review their own access.
+ example: false
+ type: boolean
+ send_reviewer_assignment_notification:
+ description: Whether to notify reviewers upon assignment.
+ example: true
+ type: boolean
+ allow_reviewer_reassignment:
+ description: Whether reviewers may reassign their reviews to another user.
+ example: false
+ type: boolean
+ start_date:
+ description: Scheduled start date of the campaign.
+ example: 2026-07-02T00:00:00Z
+ format: date-time
+ nullable: true
+ type: string
+ end_date:
+ description: Scheduled end date of the campaign.
+ example: 2026-09-30T00:00:00Z
+ format: date-time
+ nullable: true
+ type: string
+ timezone:
+ description:
+ IANA timezone used to interpret campaign deadlines (e.g.
+ America/Los_Angeles).
+ example: America/Los_Angeles
+ type: string
+ revoke_on:
+ $ref: "#/components/schemas/CampaignRevokeOnEnum"
+ reminder_schedule:
+ description: Days before end date to send reminder notifications.
+ example: [7, 3, 1]
+ items:
+ type: integer
+ type: array
+ reminder_include_manager:
+ description: Whether to include the reviewer's manager in reminders.
+ example: true
+ type: boolean
+ require_reason_on_denial:
+ description:
+ Whether reviewers must provide a reason when denying (revoking)
+ access.
+ example: false
+ type: boolean
+ hide_ai_suggestions:
+ description: Whether AI suggestions are hidden from reviewers.
+ example: false
+ type: boolean
+ custom_start_message:
+ description:
+ Optional custom message included when notifying reviewers that the
+ campaign started.
+ example: Please complete your reviews by Friday.
+ nullable: true
+ type: string
+ group_asset_visibility_policy:
+ $ref: "#/components/schemas/CampaignGroupAssetVisibilityPolicyEnum"
+ is_template:
+ description:
+ Whether this configuration is a recurring schedule template.
+ example: false
+ type: boolean
+ cron_expression:
+ description:
+ Cron expression driving the recurring schedule. Null for one-off
+ campaigns.
+ example: 0 9 1 * *
+ nullable: true
+ type: string
+ next_scheduled_run:
+ description: Next time a draft will be generated from this template.
+ example: 2026-08-01T16:00:00Z
+ format: date-time
+ nullable: true
+ type: string
+ last_scheduled_run:
+ description: Most recent time a draft was generated from this template.
+ example: 2026-07-01T16:00:00Z
+ format: date-time
+ nullable: true
+ type: string
+ recurring_duration_days:
+ description:
+ Deadline window in days applied to each draft generated from this
+ template.
+ example: 14
+ nullable: true
+ type: integer
+ required:
+ - configuration_id
+ - created_at
+ - updated_at
+ - reviewer_assignment_policy
+ - allow_self_review
+ - send_reviewer_assignment_notification
+ - allow_reviewer_reassignment
+ - timezone
+ - revoke_on
+ - reminder_include_manager
+ - require_reason_on_denial
+ - hide_ai_suggestions
+ - group_asset_visibility_policy
+ - is_template
+ type: object
+ CreateCampaignConfigurationInfo:
+ description:
+ Configuration to apply when creating a campaign. `query` is required;
+ other omitted fields use defaults.
+ example:
+ query:
+ principalFilter:
+ entityTypes: [USER]
+ end_date: 2026-09-30T00:00:00Z
+ timezone: America/Los_Angeles
+ allow_self_review: false
+ properties:
+ query:
+ description: |
+ Access-path query defining the scope of access to review. Required.
+ Uses the same principalFilter / entitlementFilter shape as
+ ACCESS_PATH OpalQuery. Must include at least one of
+ principalFilter or entitlementFilter.
+
+ Campaign scope only supports direct access edges:
+ `edgeFilter.directOnly` defaults to `true`, is always stored as
+ `true`, and passing `false` returns 400.
+ allOf:
+ - $ref: "#/components/schemas/OpalAccessPathQueryBody"
+ reviewer_assignment_policy:
+ $ref: "#/components/schemas/UARReviewerAssignmentPolicyEnum"
+ allow_self_review:
+ description: Whether reviewers can review their own access.
+ example: false
+ type: boolean
+ send_reviewer_assignment_notification:
+ description: Whether to notify reviewers upon assignment.
+ example: true
+ type: boolean
+ allow_reviewer_reassignment:
+ description: Whether reviewers may reassign their reviews to another user.
+ example: false
+ type: boolean
+ start_date:
+ description: Scheduled start date of the campaign.
+ example: 2026-07-02T00:00:00Z
+ format: date-time
+ nullable: true
+ type: string
+ end_date:
+ description: Scheduled end date of the campaign.
+ example: 2026-09-30T00:00:00Z
+ format: date-time
+ nullable: true
+ type: string
+ timezone:
+ description:
+ IANA timezone used to interpret campaign deadlines (e.g.
+ America/Los_Angeles).
+ example: America/Los_Angeles
+ type: string
+ revoke_on:
+ $ref: "#/components/schemas/CampaignRevokeOnEnum"
+ reminder_schedule:
+ description: Days before end date to send reminder notifications.
+ example: [7, 3, 1]
+ items:
+ type: integer
+ type: array
+ reminder_include_manager:
+ description: Whether to include the reviewer's manager in reminders.
+ example: true
+ type: boolean
+ require_reason_on_denial:
+ description:
+ Whether reviewers must provide a reason when denying (revoking)
+ access.
+ example: false
+ type: boolean
+ hide_ai_suggestions:
+ description: Whether AI suggestions are hidden from reviewers.
+ example: false
+ type: boolean
+ custom_start_message:
+ description:
+ Optional custom message included when notifying reviewers that the
+ campaign started.
+ example: Please complete your reviews by Friday.
+ nullable: true
+ type: string
+ group_asset_visibility_policy:
+ $ref: "#/components/schemas/CampaignGroupAssetVisibilityPolicyEnum"
+ is_template:
+ description:
+ Whether this configuration is a recurring schedule template.
+ example: false
+ type: boolean
+ cron_expression:
+ description:
+ Cron expression driving the recurring schedule. Null for one-off
+ campaigns.
+ example: 0 9 1 * *
+ nullable: true
type: string
- enum: [ANY, ALL]
- entities:
+ recurring_duration_days:
description:
- This access review will include resources and groups with ids in
- the given strings.
+ Deadline window in days applied to each draft generated from this
+ template.
+ example: 14
+ nullable: true
+ type: integer
+ excluded_role_assignment_ids:
+ description:
+ Role assignment IDs to exclude from the campaign scope during
+ population.
items:
- example: f454d283-as87-4a8a-bdbb-df212eca5353
- type: string
format: uuid
- type: array
- apps:
- description: This access review will include items in the specified applications
- items:
- example: pas2d283-ca87-4a8a-bdbb-df212eca5353
type: string
- format: uuid
type: array
- admins:
+ required:
+ - query
+ type: object
+ CreateCampaignInfo:
+ description: |-
+ # CreateCampaignInfo Object
+ ### Description
+ The `CreateCampaignInfo` object is used to create a campaign.
+
+ ### Usage Example
+ Use in the `POST Campaigns` endpoint.
+ example:
+ name: Q3 Access Review
+ configuration:
+ query:
+ principalFilter:
+ entityTypes: [USER]
+ end_date: 2026-09-30T00:00:00Z
+ timezone: America/Los_Angeles
+ properties:
+ name:
+ description: The name of the campaign.
+ example: Q3 Access Review
+ type: string
+ configuration:
description:
- This access review will include resources and groups who are owned
- by one of the owners corresponding to the given IDs.
- items:
- example: f454d283-ca87-4a8a-bdbb-df212eca5353
- type: string
- format: uuid
- type: array
- group_types:
- description: This access review will include items of the specified group types
- type: array
- items:
- $ref: "#/components/schemas/GroupTypeEnum"
- resource_types:
- description: This access review will include items of the specified resource types
- type: array
- items:
- $ref: "#/components/schemas/ResourceTypeEnum"
- include_group_bindings:
+ Configuration for the campaign. Required; must include a query.
+ Other omitted fields use defaults.
+ allOf:
+ - $ref: "#/components/schemas/CreateCampaignConfigurationInfo"
+ required:
+ - name
+ - configuration
+ type: object
+ UpdateCampaignConfigurationInfo:
+ description: |
+ Configuration fields to update on a campaign. All fields are optional;
+ omitted fields are left unchanged. `query` and
+ `reviewer_assignment_policy` are set at create time and cannot be
+ updated here; including either field returns 400.
+ `cron_expression` and `recurring_duration_days` may only be set when
+ the campaign is a template; setting them on a one-off campaign returns
+ 400. `is_template` is immutable and not accepted on update.
+ example:
+ end_date: 2026-09-30T00:00:00Z
+ timezone: America/Los_Angeles
+ allow_self_review: false
+ properties:
+ allow_self_review:
+ description: Whether reviewers can review their own access.
+ example: false
type: boolean
- example: False
- tags:
+ send_reviewer_assignment_notification:
+ description: Whether to notify reviewers upon assignment.
+ example: true
+ type: boolean
+ allow_reviewer_reassignment:
+ description: Whether reviewers may reassign their reviews to another user.
+ example: false
+ type: boolean
+ start_date:
+ description: |
+ Scheduled start date of the campaign. May only be updated while the
+ campaign has not started (started_at is null). When set, the date's
+ calendar day in the campaign timezone must be at least tomorrow.
+ example: 2026-07-02T00:00:00Z
+ format: date-time
+ nullable: true
+ type: string
+ end_date:
+ description: |
+ Scheduled end date of the campaign. When set, the date's calendar
+ day in the campaign timezone must be at least tomorrow.
+ example: 2026-09-30T00:00:00Z
+ format: date-time
+ nullable: true
+ type: string
+ timezone:
description:
- This access review will include resources and groups who are tagged
- with one of the given tags.
+ IANA timezone used to interpret campaign deadlines (e.g.
+ America/Los_Angeles).
+ example: America/Los_Angeles
+ type: string
+ revoke_on:
+ $ref: "#/components/schemas/CampaignRevokeOnEnum"
+ reminder_schedule:
+ description: Days before end date to send reminder notifications.
+ example: [7, 3, 1]
items:
- $ref: "#/components/schemas/TagFilter"
+ type: integer
type: array
- names:
+ reminder_include_manager:
+ description: Whether to include the reviewer's manager in reminders.
+ example: true
+ type: boolean
+ require_reason_on_denial:
description:
- This access review will include resources and groups whose name
- contains one of the given strings.
+ Whether reviewers must provide a reason when denying (revoking)
+ access.
+ example: false
+ type: boolean
+ hide_ai_suggestions:
+ description: Whether AI suggestions are hidden from reviewers.
+ example: false
+ type: boolean
+ custom_start_message:
+ description:
+ Optional custom message included when notifying reviewers that the
+ campaign started.
+ example: Please complete your reviews by Friday.
+ nullable: true
+ type: string
+ group_asset_visibility_policy:
+ $ref: "#/components/schemas/CampaignGroupAssetVisibilityPolicyEnum"
+ cron_expression:
+ description:
+ Cron expression driving the recurring schedule. Only valid on
+ template campaigns. Pass an empty string to clear the active months
+ (next_scheduled_run is cleared); the campaign remains a template.
+ example: 0 9 1 * *
+ nullable: true
+ type: string
+ recurring_duration_days:
+ description:
+ Deadline window in days applied to each draft generated from this
+ template. Only valid on template campaigns.
+ example: 14
+ nullable: true
+ type: integer
+ type: object
+ UpdateCampaignInfo:
+ description: |-
+ # UpdateCampaignInfo Object
+ ### Description
+ The `UpdateCampaignInfo` object is used to partially update a campaign.
+ Omitted fields are left unchanged.
+
+ ### Usage Example
+ Use in the `PUT Campaign` endpoint.
+ example:
+ name: Q3 Access Review (Updated)
+ configuration:
+ end_date: 2026-09-30T00:00:00Z
+ timezone: America/Los_Angeles
+ properties:
+ name:
+ description: The name of the campaign.
+ example: Q3 Access Review (Updated)
+ type: string
+ configuration:
+ description: Configuration fields to create or update.
+ allOf:
+ - $ref: "#/components/schemas/UpdateCampaignConfigurationInfo"
+ type: object
+ Campaign:
+ description: An access review campaign.
+ example:
+ campaign_id: f454d283-ca87-4a8a-bdbb-df212eca5353
+ name: Q3 Access Review
+ status: DRAFT
+ is_template: false
+ created_at: 2026-07-01T00:00:00Z
+ updated_at: 2026-07-01T00:00:00Z
+ created_by_user_id: 32acc112-21ff-4669-91c2-21e27683eaa1
+ configuration: null
+ started_at: null
+ started_by_user_id: null
+ stopped_at: null
+ stopped_by_user_id: null
+ ended_at: null
+ ended_by_user_id: null
+ properties:
+ campaign_id:
+ description: The ID of the campaign.
+ example: f454d283-ca87-4a8a-bdbb-df212eca5353
+ format: uuid
+ type: string
+ name:
+ description: The name of the campaign.
+ example: Q3 Access Review
+ type: string
+ status:
+ $ref: "#/components/schemas/CampaignStatusEnum"
+ is_template:
+ description:
+ Whether this campaign is a recurring schedule template. Templates
+ spawn draft campaigns on schedule rather than being reviewed directly.
+ example: false
+ type: boolean
+ created_at:
+ description: The creation time of the campaign.
+ example: 2026-07-01T00:00:00Z
+ format: date-time
+ type: string
+ updated_at:
+ description: The last updated time of the campaign.
+ example: 2026-07-01T00:00:00Z
+ format: date-time
+ type: string
+ created_by_user_id:
+ description: The ID of the user who created the campaign.
+ example: 32acc112-21ff-4669-91c2-21e27683eaa1
+ format: uuid
+ type: string
+ configuration:
+ description: The campaign's configuration, if set.
+ allOf:
+ - $ref: "#/components/schemas/CampaignConfiguration"
+ nullable: true
+ started_at:
+ description: The time the campaign was started, if started.
+ example: 2026-07-02T00:00:00Z
+ format: date-time
+ nullable: true
+ type: string
+ started_by_user_id:
+ description: The ID of the user who started the campaign, if started.
+ example: 32acc112-21ff-4669-91c2-21e27683eaa1
+ format: uuid
+ nullable: true
+ type: string
+ stopped_at:
+ description: The time the campaign was manually stopped, if stopped.
+ example: 2026-07-10T00:00:00Z
+ format: date-time
+ nullable: true
+ type: string
+ stopped_by_user_id:
+ description: The ID of the user who stopped the campaign, if stopped.
+ example: 32acc112-21ff-4669-91c2-21e27683eaa1
+ format: uuid
+ nullable: true
+ type: string
+ ended_at:
+ description: The time the campaign reached its scheduled end, if ended.
+ example: 2026-07-14T00:00:00Z
+ format: date-time
+ nullable: true
+ type: string
+ ended_by_user_id:
+ description: The ID of the user who ended the campaign, if ended.
+ example: 32acc112-21ff-4669-91c2-21e27683eaa1
+ format: uuid
+ nullable: true
+ type: string
+ required:
+ - campaign_id
+ - name
+ - status
+ - is_template
+ - created_at
+ - updated_at
+ - created_by_user_id
+ type: object
+ PaginatedCampaignsList:
+ description: A list of campaigns.
+ example:
+ next: cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw
+ previous: cj1sZXdwd2VycWVtY29zZnNkc2NzUWxNMEUxTXk0ME16UXpNallsTWtJ
+ results:
+ - campaign_id: f454d283-ca87-4a8a-bdbb-df212eca5353
+ name: Q3 Access Review
+ status: DRAFT
+ is_template: false
+ created_at: 2026-07-01T00:00:00Z
+ updated_at: 2026-07-01T00:00:00Z
+ created_by_user_id: 32acc112-21ff-4669-91c2-21e27683eaa1
+ properties:
+ next:
+ description:
+ The cursor with which to continue pagination if additional result
+ pages exist.
+ example: cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw
+ nullable: true
+ type: string
+ previous:
+ description: The cursor used to obtain the current result page.
+ example: cj1sZXdwd2VycWVtY29zZnNkc2NzUWxNMEUxTXk0ME16UXpNallsTWtJ
+ nullable: true
+ type: string
+ results:
items:
- example: demo
- type: string
+ $ref: "#/components/schemas/Campaign"
type: array
+ required:
+ - results
type: object
PaginatedUARsList:
description: A list of UARs.
@@ -6016,6 +7251,7 @@ components:
- CUSTOM_CONNECTOR
- DATABRICKS
- DATASTAX_ASTRA
+ - ALICLOUD
- DEVIN
- DUO
- GCP
@@ -6045,6 +7281,7 @@ components:
- SALESFORCE
- SNOWFLAKE
- SLACK
+ - TABLEAU
- TAILSCALE
- TELEPORT
- TWINGATE
@@ -6621,6 +7858,44 @@ components:
$ref: "#/components/schemas/Session"
type: array
type: object
+ Paladin:
+ description: |-
+ # Paladin Object
+ ### Description
+ The `Paladin` object represents a Paladin, Opal's AI access-request
+ reviewer.
+ example:
+ paladin_id: 32acc112-21ff-4669-91c2-21e27683eaa1
+ name: paladin-agent-1
+ properties:
+ paladin_id:
+ description:
+ The ID of the Paladin. Use this value as a reviewer in a request
+ configuration's service_user_ids.
+ example: 32acc112-21ff-4669-91c2-21e27683eaa1
+ format: uuid
+ type: string
+ name:
+ description: The name of the Paladin.
+ example: paladin-agent-1
+ type: string
+ required:
+ - paladin_id
+ - name
+ type: object
+ PaladinList:
+ description: |-
+ # PaladinList Object
+ ### Description
+ A list of `Paladin` objects.
+ properties:
+ results:
+ items:
+ $ref: "#/components/schemas/Paladin"
+ type: array
+ required:
+ - results
+ type: object
Session:
description: |-
# Session Object
@@ -7189,6 +8464,21 @@ components:
risk_sensitivity_override:
allOf:
- $ref: "#/components/schemas/RiskSensitivityEnum"
+ match_remote_name:
+ description:
+ A bool representing whether or not the group's name is synced from
+ the end system. When true, the name is overwritten with the remote
+ name on each sync. Defaults to false.
+ example: False
+ type: boolean
+ match_remote_description:
+ description:
+ A bool representing whether or not the group's description is
+ synced from the end system. When true, the description is
+ overwritten with the remote description on each sync. Defaults to
+ false.
+ example: False
+ type: boolean
last_successful_sync:
readOnly: true
description: Information about the last successful sync of this group.
@@ -7349,6 +8639,7 @@ components:
- ERR_DRY_RUN_MODE_ENABLED
- ERR_HR_IDP_PROVIDER_NOT_LINKED
- ERR_REMOTE_UNRECOVERABLE_ERROR
+ - ERR_REMOTE_TICKET_NOT_FOUND
example:
- SUCCESS
type: string
@@ -7577,6 +8868,25 @@ components:
risk_sensitivity_override:
allOf:
- $ref: "#/components/schemas/RiskSensitivityEnum"
+ match_remote_name:
+ description:
+ A bool representing whether or not the group's name should be
+ synced from the end system. When true, the name is overwritten
+ with the remote name on each sync, so a `name` provided together
+ with this field set to true will be replaced at the next sync. If
+ not provided, the current value is left unchanged.
+ example: False
+ type: boolean
+ match_remote_description:
+ description:
+ A bool representing whether or not the group's description should
+ be synced from the end system. When true, the description is
+ overwritten with the remote description on each sync, so a
+ `description` provided together with this field set to true will
+ be replaced at the next sync. If not provided, the current value
+ is left unchanged.
+ example: False
+ type: boolean
required:
- group_id
type: object
@@ -7615,6 +8925,7 @@ components:
- ZENDESK_GROUP
- ZENDESK_ORGANIZATION
- HUBSPOT_TEAM
+ - TABLEAU_GROUP
example: OPAL_GROUP
type: string
ResourceTypeEnum:
@@ -7706,6 +9017,8 @@ components:
- TWINGATE_RESOURCE
- ZENDESK_ROLE
- HUBSPOT_ROLE
+ - ALICLOUD_RAM_ROLE
+ - ALICLOUD_ECS_INSTANCE
example: AWS_IAM_ROLE
type: string
EntityItemTypeEnum:
@@ -8566,6 +9879,16 @@ components:
type: object
required:
- team_id
+ tableau_group:
+ description: Remote info for Tableau group.
+ properties:
+ group_id:
+ description: The ID of the Tableau group.
+ example: "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
+ type: string
+ type: object
+ required:
+ - group_id
type: object
ResourceRemoteInfo:
description:
@@ -9462,6 +10785,26 @@ components:
type: object
required:
- role_id
+ alicloud_ram_role:
+ description: Remote info for AliCloud RAM role.
+ properties:
+ role_arn:
+ description: The ARN of the AliCloud RAM role.
+ example: "acs:ram::1234567890:role/MyRole"
+ type: string
+ type: object
+ required:
+ - role_arn
+ alicloud_ecs_instance:
+ description: Remote info for AliCloud ECS instance.
+ properties:
+ instance_id:
+ description: The ID of the ECS instance.
+ example: "i-bp1a1234567890abcd"
+ type: string
+ type: object
+ required:
+ - instance_id
type: object
RiskSensitivityEnum:
type: string
@@ -9760,6 +11103,24 @@ components:
risk_sensitivity_override:
allOf:
- $ref: "#/components/schemas/RiskSensitivityEnum"
+ match_remote_name:
+ description:
+ A bool representing whether or not the resource's name should be
+ synced from the end system. When true, the name is overwritten
+ with the remote name on each sync, so a `name` provided together
+ with this field set to true will be replaced at the next sync.
+ Defaults to false.
+ example: False
+ type: boolean
+ match_remote_description:
+ description:
+ A bool representing whether or not the resource's description
+ should be synced from the end system. When true, the description
+ is overwritten with the remote description on each sync, so a
+ `description` provided together with this field set to true will
+ be replaced at the next sync. Defaults to false.
+ example: False
+ type: boolean
required:
- name
- resource_type
@@ -9939,6 +11300,24 @@ components:
risk_sensitivity_override:
allOf:
- $ref: "#/components/schemas/RiskSensitivityEnum"
+ match_remote_name:
+ description:
+ A bool representing whether or not the group's name should be
+ synced from the end system. When true, the name is overwritten
+ with the remote name on each sync, so a `name` provided together
+ with this field set to true will be replaced at the next sync.
+ Defaults to false.
+ example: False
+ type: boolean
+ match_remote_description:
+ description:
+ A bool representing whether or not the group's description should
+ be synced from the end system. When true, the description is
+ overwritten with the remote description on each sync, so a
+ `description` provided together with this field set to true will
+ be replaced at the next sync. Defaults to false.
+ example: False
+ type: boolean
required:
- name
- group_type
@@ -10579,6 +11958,21 @@ components:
example:
- f454d283-ca67-4a8a-bdbb-df212eca5347
- f454d283-ca67-4a8a-bdbb-df212eca5348
+ match_remote_name:
+ description:
+ A bool representing whether or not the resource's name is synced
+ from the end system. When true, the name is overwritten with the
+ remote name on each sync. Defaults to false.
+ example: False
+ type: boolean
+ match_remote_description:
+ description:
+ A bool representing whether or not the resource's description is
+ synced from the end system. When true, the description is
+ overwritten with the remote description on each sync. Defaults to
+ false.
+ example: False
+ type: boolean
last_successful_sync:
readOnly: true
description: Information about the last successful sync of this resource.
@@ -10743,6 +12137,25 @@ components:
risk_sensitivity_override:
allOf:
- $ref: "#/components/schemas/RiskSensitivityEnum"
+ match_remote_name:
+ description:
+ A bool representing whether or not the resource's name should be
+ synced from the end system. When true, the name is overwritten
+ with the remote name on each sync, so a `name` provided together
+ with this field set to true will be replaced at the next sync. If
+ not provided, the current value is left unchanged.
+ example: False
+ type: boolean
+ match_remote_description:
+ description:
+ A bool representing whether or not the resource's description
+ should be synced from the end system. When true, the description
+ is overwritten with the remote description on each sync, so a
+ `description` provided together with this field set to true will
+ be replaced at the next sync. If not provided, the current value
+ is left unchanged.
+ example: False
+ type: boolean
configuration_template_id:
description: The ID of the associated configuration template.
example: 06851574-e50d-40ca-8c78-f72ae6ab4304
@@ -12952,7 +14365,14 @@ components:
required:
- results
type: object
+ StopCampaignRequest:
+ properties:
+ revoke_unreviewed:
+ default: false
+ description: Revoke all unreviewed access grants. Access grants with no reviewer decision will be immediately revoked.
+ type: boolean
+ type: object
securitySchemes:
BearerAuth:
scheme: bearer
- type: http
\ No newline at end of file
+ type: http
diff --git a/docs/AccessEntityFilters.md b/docs/AccessEntityFilters.md
index 73e34e2..b697c37 100644
--- a/docs/AccessEntityFilters.md
+++ b/docs/AccessEntityFilters.md
@@ -10,6 +10,8 @@ Name | Type | Description | Notes
**entity_item_types** | [**List[EntityItemTypeEnum]**](EntityItemTypeEnum.md) | Filter by entity item types. | [optional]
**entity_name** | [**EntityNameFilter**](EntityNameFilter.md) | | [optional]
**entity_tag** | [**EntityTagFilter**](EntityTagFilter.md) | | [optional]
+**hr_idp_status** | [**IdpStatusFilter**](IdpStatusFilter.md) | | [optional]
+**entity_admin_owner** | [**EntityAdminFilter**](EntityAdminFilter.md) | | [optional]
**entity_ids** | **List[UUID]** | Filter by specific entity UUIDs. | [optional]
**imported_from_app** | **List[UUID]** | Filter by app IDs from which returned nodes will be imported from. | [optional]
**role_remote_ids** | **List[str]** | Filter by role remote IDs. Can only be applied within a hasAccessTo clause. | [optional]
diff --git a/docs/AppTypeEnum.md b/docs/AppTypeEnum.md
index 2bc6e0a..526d961 100644
--- a/docs/AppTypeEnum.md
+++ b/docs/AppTypeEnum.md
@@ -28,6 +28,8 @@ The type of an app.
* `DATASTAX_ASTRA` (value: `'DATASTAX_ASTRA'`)
+* `ALICLOUD` (value: `'ALICLOUD'`)
+
* `DEVIN` (value: `'DEVIN'`)
* `DUO` (value: `'DUO'`)
@@ -86,6 +88,8 @@ The type of an app.
* `SLACK` (value: `'SLACK'`)
+* `TABLEAU` (value: `'TABLEAU'`)
+
* `TAILSCALE` (value: `'TAILSCALE'`)
* `TELEPORT` (value: `'TELEPORT'`)
diff --git a/docs/Campaign.md b/docs/Campaign.md
new file mode 100644
index 0000000..e59f4f9
--- /dev/null
+++ b/docs/Campaign.md
@@ -0,0 +1,43 @@
+# Campaign
+
+An access review campaign.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**campaign_id** | **UUID** | The ID of the campaign. |
+**name** | **str** | The name of the campaign. |
+**status** | [**CampaignStatusEnum**](CampaignStatusEnum.md) | |
+**is_template** | **bool** | Whether this campaign is a recurring schedule template. Templates spawn draft campaigns on schedule rather than being reviewed directly. |
+**created_at** | **datetime** | The creation time of the campaign. |
+**updated_at** | **datetime** | The last updated time of the campaign. |
+**created_by_user_id** | **UUID** | The ID of the user who created the campaign. |
+**configuration** | [**CampaignConfiguration**](CampaignConfiguration.md) | The campaign's configuration, if set. | [optional]
+**started_at** | **datetime** | The time the campaign was started, if started. | [optional]
+**started_by_user_id** | **UUID** | The ID of the user who started the campaign, if started. | [optional]
+**stopped_at** | **datetime** | The time the campaign was manually stopped, if stopped. | [optional]
+**stopped_by_user_id** | **UUID** | The ID of the user who stopped the campaign, if stopped. | [optional]
+**ended_at** | **datetime** | The time the campaign reached its scheduled end, if ended. | [optional]
+**ended_by_user_id** | **UUID** | The ID of the user who ended the campaign, if ended. | [optional]
+
+## Example
+
+```python
+from opal_security.models.campaign import Campaign
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of Campaign from a JSON string
+campaign_instance = Campaign.from_json(json)
+# print the JSON string representation of the object
+print(Campaign.to_json())
+
+# convert the object into a dict
+campaign_dict = campaign_instance.to_dict()
+# create an instance of Campaign from a dict
+campaign_from_dict = Campaign.from_dict(campaign_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/CampaignConfiguration.md b/docs/CampaignConfiguration.md
new file mode 100644
index 0000000..5a4ab1b
--- /dev/null
+++ b/docs/CampaignConfiguration.md
@@ -0,0 +1,52 @@
+# CampaignConfiguration
+
+Configuration for an access review campaign.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**configuration_id** | **UUID** | The ID of the campaign configuration. |
+**created_at** | **datetime** | The creation time of the configuration. |
+**updated_at** | **datetime** | The last updated time of the configuration. |
+**query** | [**OpalAccessPathQueryBody**](OpalAccessPathQueryBody.md) | Access-path query defining the scope of access to review. Uses the same principalFilter / entitlementFilter shape as ACCESS_PATH OpalQuery. | [optional]
+**reviewer_assignment_policy** | [**UARReviewerAssignmentPolicyEnum**](UARReviewerAssignmentPolicyEnum.md) | |
+**allow_self_review** | **bool** | Whether reviewers can review their own access. |
+**send_reviewer_assignment_notification** | **bool** | Whether to notify reviewers upon assignment. |
+**allow_reviewer_reassignment** | **bool** | Whether reviewers may reassign their reviews to another user. |
+**start_date** | **datetime** | Scheduled start date of the campaign. | [optional]
+**end_date** | **datetime** | Scheduled end date of the campaign. | [optional]
+**timezone** | **str** | IANA timezone used to interpret campaign deadlines (e.g. America/Los_Angeles). |
+**revoke_on** | [**CampaignRevokeOnEnum**](CampaignRevokeOnEnum.md) | |
+**reminder_schedule** | **List[int]** | Days before end date to send reminder notifications. | [optional]
+**reminder_include_manager** | **bool** | Whether to include the reviewer's manager in reminders. |
+**require_reason_on_denial** | **bool** | Whether reviewers must provide a reason when denying (revoking) access. |
+**hide_ai_suggestions** | **bool** | Whether AI suggestions are hidden from reviewers. |
+**custom_start_message** | **str** | Optional custom message included when notifying reviewers that the campaign started. | [optional]
+**group_asset_visibility_policy** | [**CampaignGroupAssetVisibilityPolicyEnum**](CampaignGroupAssetVisibilityPolicyEnum.md) | |
+**is_template** | **bool** | Whether this configuration is a recurring schedule template. |
+**cron_expression** | **str** | Cron expression driving the recurring schedule. Null for one-off campaigns. | [optional]
+**next_scheduled_run** | **datetime** | Next time a draft will be generated from this template. | [optional]
+**last_scheduled_run** | **datetime** | Most recent time a draft was generated from this template. | [optional]
+**recurring_duration_days** | **int** | Deadline window in days applied to each draft generated from this template. | [optional]
+
+## Example
+
+```python
+from opal_security.models.campaign_configuration import CampaignConfiguration
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of CampaignConfiguration from a JSON string
+campaign_configuration_instance = CampaignConfiguration.from_json(json)
+# print the JSON string representation of the object
+print(CampaignConfiguration.to_json())
+
+# convert the object into a dict
+campaign_configuration_dict = campaign_configuration_instance.to_dict()
+# create an instance of CampaignConfiguration from a dict
+campaign_configuration_from_dict = CampaignConfiguration.from_dict(campaign_configuration_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/CampaignGroupAssetVisibilityPolicyEnum.md b/docs/CampaignGroupAssetVisibilityPolicyEnum.md
new file mode 100644
index 0000000..d3fdd4c
--- /dev/null
+++ b/docs/CampaignGroupAssetVisibilityPolicyEnum.md
@@ -0,0 +1,15 @@
+# CampaignGroupAssetVisibilityPolicyEnum
+
+Controls what group assets reviewers can see during the campaign.
+
+## Enum
+
+* `STRICT` (value: `'STRICT'`)
+
+* `VIEW_VISIBLE_AND_ASSIGNED` (value: `'VIEW_VISIBLE_AND_ASSIGNED'`)
+
+* `VIEW_ALL` (value: `'VIEW_ALL'`)
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/CampaignRevokeOnEnum.md b/docs/CampaignRevokeOnEnum.md
new file mode 100644
index 0000000..9e0f7d0
--- /dev/null
+++ b/docs/CampaignRevokeOnEnum.md
@@ -0,0 +1,15 @@
+# CampaignRevokeOnEnum
+
+When access decisions take effect during a campaign.
+
+## Enum
+
+* `ACTION` (value: `'ACTION'`)
+
+* `END` (value: `'END'`)
+
+* `NONE` (value: `'NONE'`)
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/CampaignStatusEnum.md b/docs/CampaignStatusEnum.md
new file mode 100644
index 0000000..362f82c
--- /dev/null
+++ b/docs/CampaignStatusEnum.md
@@ -0,0 +1,19 @@
+# CampaignStatusEnum
+
+The current status of a campaign.
+
+## Enum
+
+* `DRAFT` (value: `'DRAFT'`)
+
+* `ONGOING` (value: `'ONGOING'`)
+
+* `COMPLETED` (value: `'COMPLETED'`)
+
+* `STOPPED` (value: `'STOPPED'`)
+
+* `ENDED` (value: `'ENDED'`)
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/CampaignsApi.md b/docs/CampaignsApi.md
new file mode 100644
index 0000000..4f85b00
--- /dev/null
+++ b/docs/CampaignsApi.md
@@ -0,0 +1,623 @@
+# opal_security.CampaignsApi
+
+All URIs are relative to *https://api.opal.dev/v1*
+
+Method | HTTP request | Description
+------------- | ------------- | -------------
+[**create_campaign**](CampaignsApi.md#create_campaign) | **POST** /campaigns |
+[**end_campaign**](CampaignsApi.md#end_campaign) | **POST** /campaigns/{campaign_id}/end | End campaign
+[**get_campaign**](CampaignsApi.md#get_campaign) | **GET** /campaigns/{campaign_id} | Get campaign by ID
+[**get_campaigns**](CampaignsApi.md#get_campaigns) | **GET** /campaigns |
+[**start_campaign**](CampaignsApi.md#start_campaign) | **POST** /campaigns/{campaign_id}/start | Start campaign
+[**stop_campaign**](CampaignsApi.md#stop_campaign) | **POST** /campaigns/{campaign_id}/stop | Stop campaign
+[**update_campaign**](CampaignsApi.md#update_campaign) | **PUT** /campaigns/{campaign_id} | Update campaign
+
+
+# **create_campaign**
+> Campaign create_campaign(create_campaign_info)
+
+Creates a campaign. Campaign scope only supports direct access edges:
+`configuration.query.edgeFilter.directOnly` defaults to `true`, is
+always stored as `true`, and passing `false` returns 400.
+
+
+### Example
+
+* Bearer Authentication (BearerAuth):
+
+```python
+import opal_security
+from opal_security.models.campaign import Campaign
+from opal_security.models.create_campaign_info import CreateCampaignInfo
+from opal_security.rest import ApiException
+from pprint import pprint
+
+# Defining the host is optional and defaults to https://api.opal.dev/v1
+# See configuration.py for a list of all supported configuration parameters.
+import opal_security as opal
+
+configuration = opal.Configuration(
+ host = "https://api.opal.dev/v1"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure Bearer authorization: BearerAuth
+configuration = opal.Configuration(
+ access_token = os.environ["BEARER_TOKEN"]
+)
+
+# Enter a context with an instance of the API client
+with opal_security.ApiClient(configuration) as api_client:
+ # Create an instance of the API class
+ api_instance = opal_security.CampaignsApi(api_client)
+ create_campaign_info = opal_security.CreateCampaignInfo() # CreateCampaignInfo |
+
+ try:
+ api_response = api_instance.create_campaign(create_campaign_info)
+ print("The response of CampaignsApi->create_campaign:\n")
+ pprint(api_response)
+ except Exception as e:
+ print("Exception when calling CampaignsApi->create_campaign: %s\n" % e)
+```
+
+
+
+### Parameters
+
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **create_campaign_info** | [**CreateCampaignInfo**](CreateCampaignInfo.md)| |
+
+### Return type
+
+[**Campaign**](Campaign.md)
+
+### Authorization
+
+[BearerAuth](../README.md#BearerAuth)
+
+### HTTP request headers
+
+ - **Content-Type**: application/json
+ - **Accept**: application/json
+
+### HTTP response details
+
+| Status code | Description | Response headers |
+|-------------|-------------|------------------|
+**201** | The campaign successfully created. | - |
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
+# **end_campaign**
+> Campaign end_campaign(campaign_id)
+
+End campaign
+
+Ends a stopped campaign, setting `ended_at` and `ended_by_user_id`,
+applying pending access changes, and queuing report generation.
+Returns 400 unless the campaign is started and stopped and not already
+ended.
+
+
+### Example
+
+* Bearer Authentication (BearerAuth):
+
+```python
+import opal_security
+from opal_security.models.campaign import Campaign
+from opal_security.rest import ApiException
+from pprint import pprint
+
+# Defining the host is optional and defaults to https://api.opal.dev/v1
+# See configuration.py for a list of all supported configuration parameters.
+import opal_security as opal
+
+configuration = opal.Configuration(
+ host = "https://api.opal.dev/v1"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure Bearer authorization: BearerAuth
+configuration = opal.Configuration(
+ access_token = os.environ["BEARER_TOKEN"]
+)
+
+# Enter a context with an instance of the API client
+with opal_security.ApiClient(configuration) as api_client:
+ # Create an instance of the API class
+ api_instance = opal_security.CampaignsApi(api_client)
+ campaign_id = UUID('f454d283-ca87-4a8a-bdbb-df212eca5353') # UUID | The ID of the campaign.
+
+ try:
+ # End campaign
+ api_response = api_instance.end_campaign(campaign_id)
+ print("The response of CampaignsApi->end_campaign:\n")
+ pprint(api_response)
+ except Exception as e:
+ print("Exception when calling CampaignsApi->end_campaign: %s\n" % e)
+```
+
+
+
+### Parameters
+
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **campaign_id** | **UUID**| The ID of the campaign. |
+
+### Return type
+
+[**Campaign**](Campaign.md)
+
+### Authorization
+
+[BearerAuth](../README.md#BearerAuth)
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
+### HTTP response details
+
+| Status code | Description | Response headers |
+|-------------|-------------|------------------|
+**200** | The ended `Campaign`. | - |
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
+# **get_campaign**
+> Campaign get_campaign(campaign_id)
+
+Get campaign by ID
+
+Returns a `Campaign` object.
+
+### Example
+
+* Bearer Authentication (BearerAuth):
+
+```python
+import opal_security
+from opal_security.models.campaign import Campaign
+from opal_security.rest import ApiException
+from pprint import pprint
+
+# Defining the host is optional and defaults to https://api.opal.dev/v1
+# See configuration.py for a list of all supported configuration parameters.
+import opal_security as opal
+
+configuration = opal.Configuration(
+ host = "https://api.opal.dev/v1"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure Bearer authorization: BearerAuth
+configuration = opal.Configuration(
+ access_token = os.environ["BEARER_TOKEN"]
+)
+
+# Enter a context with an instance of the API client
+with opal_security.ApiClient(configuration) as api_client:
+ # Create an instance of the API class
+ api_instance = opal_security.CampaignsApi(api_client)
+ campaign_id = UUID('f454d283-ca87-4a8a-bdbb-df212eca5353') # UUID | The ID of the campaign.
+
+ try:
+ # Get campaign by ID
+ api_response = api_instance.get_campaign(campaign_id)
+ print("The response of CampaignsApi->get_campaign:\n")
+ pprint(api_response)
+ except Exception as e:
+ print("Exception when calling CampaignsApi->get_campaign: %s\n" % e)
+```
+
+
+
+### Parameters
+
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **campaign_id** | **UUID**| The ID of the campaign. |
+
+### Return type
+
+[**Campaign**](Campaign.md)
+
+### Authorization
+
+[BearerAuth](../README.md#BearerAuth)
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
+### HTTP response details
+
+| Status code | Description | Response headers |
+|-------------|-------------|------------------|
+**200** | The requested `Campaign`. | - |
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
+# **get_campaigns**
+> PaginatedCampaignsList get_campaigns(cursor=cursor, page_size=page_size, name=name, status=status, created_at_after=created_at_after, created_at_before=created_at_before, started_at_after=started_at_after, started_at_before=started_at_before, ended_at_after=ended_at_after, ended_at_before=ended_at_before, stopped_at_after=stopped_at_after, stopped_at_before=stopped_at_before)
+
+Returns a list of `Campaign` objects.
+
+### Example
+
+* Bearer Authentication (BearerAuth):
+
+```python
+import opal_security
+from opal_security.models.campaign_status_enum import CampaignStatusEnum
+from opal_security.models.paginated_campaigns_list import PaginatedCampaignsList
+from opal_security.rest import ApiException
+from pprint import pprint
+
+# Defining the host is optional and defaults to https://api.opal.dev/v1
+# See configuration.py for a list of all supported configuration parameters.
+import opal_security as opal
+
+configuration = opal.Configuration(
+ host = "https://api.opal.dev/v1"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure Bearer authorization: BearerAuth
+configuration = opal.Configuration(
+ access_token = os.environ["BEARER_TOKEN"]
+)
+
+# Enter a context with an instance of the API client
+with opal_security.ApiClient(configuration) as api_client:
+ # Create an instance of the API class
+ api_instance = opal_security.CampaignsApi(api_client)
+ cursor = 'cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw' # str | The pagination cursor value. (optional)
+ page_size = 200 # int | Number of results to return per page. Default is 200. (optional)
+ name = 'Q3 Access Review' # str | Campaign name to filter by. Returns campaigns whose names contain this substring (case-insensitive). (optional)
+ status = opal_security.CampaignStatusEnum() # CampaignStatusEnum | Filter by campaign status. Status is derived from lifecycle timestamps and review progress. (optional)
+ created_at_after = '2026-01-01T00:00:00Z' # datetime | Include campaigns created after this timestamp (exclusive). ISO 8601 format. (optional)
+ created_at_before = '2026-12-31T23:59:59Z' # datetime | Include campaigns created before this timestamp (exclusive). ISO 8601 format. (optional)
+ started_at_after = '2026-01-01T00:00:00Z' # datetime | Include campaigns started after this timestamp (exclusive). ISO 8601 format. (optional)
+ started_at_before = '2026-12-31T23:59:59Z' # datetime | Include campaigns started before this timestamp (exclusive). ISO 8601 format. (optional)
+ ended_at_after = '2026-01-01T00:00:00Z' # datetime | Include campaigns ended after this timestamp (exclusive). ISO 8601 format. (optional)
+ ended_at_before = '2026-12-31T23:59:59Z' # datetime | Include campaigns ended before this timestamp (exclusive). ISO 8601 format. (optional)
+ stopped_at_after = '2026-01-01T00:00:00Z' # datetime | Include campaigns stopped after this timestamp (exclusive). ISO 8601 format. (optional)
+ stopped_at_before = '2026-12-31T23:59:59Z' # datetime | Include campaigns stopped before this timestamp (exclusive). ISO 8601 format. (optional)
+
+ try:
+ api_response = api_instance.get_campaigns(cursor=cursor, page_size=page_size, name=name, status=status, created_at_after=created_at_after, created_at_before=created_at_before, started_at_after=started_at_after, started_at_before=started_at_before, ended_at_after=ended_at_after, ended_at_before=ended_at_before, stopped_at_after=stopped_at_after, stopped_at_before=stopped_at_before)
+ print("The response of CampaignsApi->get_campaigns:\n")
+ pprint(api_response)
+ except Exception as e:
+ print("Exception when calling CampaignsApi->get_campaigns: %s\n" % e)
+```
+
+
+
+### Parameters
+
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **cursor** | **str**| The pagination cursor value. | [optional]
+ **page_size** | **int**| Number of results to return per page. Default is 200. | [optional]
+ **name** | **str**| Campaign name to filter by. Returns campaigns whose names contain this substring (case-insensitive). | [optional]
+ **status** | [**CampaignStatusEnum**](.md)| Filter by campaign status. Status is derived from lifecycle timestamps and review progress. | [optional]
+ **created_at_after** | **datetime**| Include campaigns created after this timestamp (exclusive). ISO 8601 format. | [optional]
+ **created_at_before** | **datetime**| Include campaigns created before this timestamp (exclusive). ISO 8601 format. | [optional]
+ **started_at_after** | **datetime**| Include campaigns started after this timestamp (exclusive). ISO 8601 format. | [optional]
+ **started_at_before** | **datetime**| Include campaigns started before this timestamp (exclusive). ISO 8601 format. | [optional]
+ **ended_at_after** | **datetime**| Include campaigns ended after this timestamp (exclusive). ISO 8601 format. | [optional]
+ **ended_at_before** | **datetime**| Include campaigns ended before this timestamp (exclusive). ISO 8601 format. | [optional]
+ **stopped_at_after** | **datetime**| Include campaigns stopped after this timestamp (exclusive). ISO 8601 format. | [optional]
+ **stopped_at_before** | **datetime**| Include campaigns stopped before this timestamp (exclusive). ISO 8601 format. | [optional]
+
+### Return type
+
+[**PaginatedCampaignsList**](PaginatedCampaignsList.md)
+
+### Authorization
+
+[BearerAuth](../README.md#BearerAuth)
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
+### HTTP response details
+
+| Status code | Description | Response headers |
+|-------------|-------------|------------------|
+**200** | A list of campaigns for your organization. | - |
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
+# **start_campaign**
+> Campaign start_campaign(campaign_id)
+
+Start campaign
+
+Starts a draft campaign immediately, setting `started_at` and
+`started_by_user_id`. Returns 400 if the campaign is not in draft
+state, or if it is a recurring template (`is_template: true`) —
+templates spawn draft campaigns on their schedule and cannot be
+started directly.
+
+
+### Example
+
+* Bearer Authentication (BearerAuth):
+
+```python
+import opal_security
+from opal_security.models.campaign import Campaign
+from opal_security.rest import ApiException
+from pprint import pprint
+
+# Defining the host is optional and defaults to https://api.opal.dev/v1
+# See configuration.py for a list of all supported configuration parameters.
+import opal_security as opal
+
+configuration = opal.Configuration(
+ host = "https://api.opal.dev/v1"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure Bearer authorization: BearerAuth
+configuration = opal.Configuration(
+ access_token = os.environ["BEARER_TOKEN"]
+)
+
+# Enter a context with an instance of the API client
+with opal_security.ApiClient(configuration) as api_client:
+ # Create an instance of the API class
+ api_instance = opal_security.CampaignsApi(api_client)
+ campaign_id = UUID('f454d283-ca87-4a8a-bdbb-df212eca5353') # UUID | The ID of the campaign.
+
+ try:
+ # Start campaign
+ api_response = api_instance.start_campaign(campaign_id)
+ print("The response of CampaignsApi->start_campaign:\n")
+ pprint(api_response)
+ except Exception as e:
+ print("Exception when calling CampaignsApi->start_campaign: %s\n" % e)
+```
+
+
+
+### Parameters
+
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **campaign_id** | **UUID**| The ID of the campaign. |
+
+### Return type
+
+[**Campaign**](Campaign.md)
+
+### Authorization
+
+[BearerAuth](../README.md#BearerAuth)
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
+### HTTP response details
+
+| Status code | Description | Response headers |
+|-------------|-------------|------------------|
+**200** | The started `Campaign`. | - |
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
+# **stop_campaign**
+> Campaign stop_campaign(campaign_id, stop_campaign_request=stop_campaign_request)
+
+Stop campaign
+
+Stops an ongoing campaign immediately, setting `stopped_at` and
+`stopped_by_user_id`. Returns 400 if the campaign has not started or
+has already stopped.
+
+
+### Example
+
+* Bearer Authentication (BearerAuth):
+
+```python
+import opal_security
+from opal_security.models.campaign import Campaign
+from opal_security.models.stop_campaign_request import StopCampaignRequest
+from opal_security.rest import ApiException
+from pprint import pprint
+
+# Defining the host is optional and defaults to https://api.opal.dev/v1
+# See configuration.py for a list of all supported configuration parameters.
+import opal_security as opal
+
+configuration = opal.Configuration(
+ host = "https://api.opal.dev/v1"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure Bearer authorization: BearerAuth
+configuration = opal.Configuration(
+ access_token = os.environ["BEARER_TOKEN"]
+)
+
+# Enter a context with an instance of the API client
+with opal_security.ApiClient(configuration) as api_client:
+ # Create an instance of the API class
+ api_instance = opal_security.CampaignsApi(api_client)
+ campaign_id = UUID('f454d283-ca87-4a8a-bdbb-df212eca5353') # UUID | The ID of the campaign.
+ stop_campaign_request = opal_security.StopCampaignRequest() # StopCampaignRequest | (optional)
+
+ try:
+ # Stop campaign
+ api_response = api_instance.stop_campaign(campaign_id, stop_campaign_request=stop_campaign_request)
+ print("The response of CampaignsApi->stop_campaign:\n")
+ pprint(api_response)
+ except Exception as e:
+ print("Exception when calling CampaignsApi->stop_campaign: %s\n" % e)
+```
+
+
+
+### Parameters
+
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **campaign_id** | **UUID**| The ID of the campaign. |
+ **stop_campaign_request** | [**StopCampaignRequest**](StopCampaignRequest.md)| | [optional]
+
+### Return type
+
+[**Campaign**](Campaign.md)
+
+### Authorization
+
+[BearerAuth](../README.md#BearerAuth)
+
+### HTTP request headers
+
+ - **Content-Type**: application/json
+ - **Accept**: application/json
+
+### HTTP response details
+
+| Status code | Description | Response headers |
+|-------------|-------------|------------------|
+**200** | The stopped `Campaign`. | - |
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
+# **update_campaign**
+> Campaign update_campaign(campaign_id, update_campaign_info)
+
+Update campaign
+
+Partially updates a campaign. Omitted fields are left unchanged.
+`configuration.query` and `configuration.reviewer_assignment_policy`
+cannot be updated after create; including either field returns 400.
+`configuration.cron_expression` and
+`configuration.recurring_duration_days` may only be set on template
+campaigns; setting them on a one-off campaign returns 400.
+`configuration.is_template` is immutable and not accepted on update.
+Configuration updates on a stopped or ended (non-template) campaign
+return 400. Name-only updates are still allowed.
+
+
+### Example
+
+* Bearer Authentication (BearerAuth):
+
+```python
+import opal_security
+from opal_security.models.campaign import Campaign
+from opal_security.models.update_campaign_info import UpdateCampaignInfo
+from opal_security.rest import ApiException
+from pprint import pprint
+
+# Defining the host is optional and defaults to https://api.opal.dev/v1
+# See configuration.py for a list of all supported configuration parameters.
+import opal_security as opal
+
+configuration = opal.Configuration(
+ host = "https://api.opal.dev/v1"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure Bearer authorization: BearerAuth
+configuration = opal.Configuration(
+ access_token = os.environ["BEARER_TOKEN"]
+)
+
+# Enter a context with an instance of the API client
+with opal_security.ApiClient(configuration) as api_client:
+ # Create an instance of the API class
+ api_instance = opal_security.CampaignsApi(api_client)
+ campaign_id = UUID('f454d283-ca87-4a8a-bdbb-df212eca5353') # UUID | The ID of the campaign.
+ update_campaign_info = opal_security.UpdateCampaignInfo() # UpdateCampaignInfo |
+
+ try:
+ # Update campaign
+ api_response = api_instance.update_campaign(campaign_id, update_campaign_info)
+ print("The response of CampaignsApi->update_campaign:\n")
+ pprint(api_response)
+ except Exception as e:
+ print("Exception when calling CampaignsApi->update_campaign: %s\n" % e)
+```
+
+
+
+### Parameters
+
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **campaign_id** | **UUID**| The ID of the campaign. |
+ **update_campaign_info** | [**UpdateCampaignInfo**](UpdateCampaignInfo.md)| |
+
+### Return type
+
+[**Campaign**](Campaign.md)
+
+### Authorization
+
+[BearerAuth](../README.md#BearerAuth)
+
+### HTTP request headers
+
+ - **Content-Type**: application/json
+ - **Accept**: application/json
+
+### HTTP response details
+
+| Status code | Description | Response headers |
+|-------------|-------------|------------------|
+**200** | The updated `Campaign`. | - |
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
diff --git a/docs/CreateCampaignConfigurationInfo.md b/docs/CreateCampaignConfigurationInfo.md
new file mode 100644
index 0000000..7a4ac37
--- /dev/null
+++ b/docs/CreateCampaignConfigurationInfo.md
@@ -0,0 +1,48 @@
+# CreateCampaignConfigurationInfo
+
+Configuration to apply when creating a campaign. `query` is required; other omitted fields use defaults.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**query** | [**OpalAccessPathQueryBody**](OpalAccessPathQueryBody.md) | Access-path query defining the scope of access to review. Required. Uses the same principalFilter / entitlementFilter shape as ACCESS_PATH OpalQuery. Must include at least one of principalFilter or entitlementFilter. Campaign scope only supports direct access edges: `edgeFilter.directOnly` defaults to `true`, is always stored as `true`, and passing `false` returns 400. |
+**reviewer_assignment_policy** | [**UARReviewerAssignmentPolicyEnum**](UARReviewerAssignmentPolicyEnum.md) | | [optional]
+**allow_self_review** | **bool** | Whether reviewers can review their own access. | [optional]
+**send_reviewer_assignment_notification** | **bool** | Whether to notify reviewers upon assignment. | [optional]
+**allow_reviewer_reassignment** | **bool** | Whether reviewers may reassign their reviews to another user. | [optional]
+**start_date** | **datetime** | Scheduled start date of the campaign. | [optional]
+**end_date** | **datetime** | Scheduled end date of the campaign. | [optional]
+**timezone** | **str** | IANA timezone used to interpret campaign deadlines (e.g. America/Los_Angeles). | [optional]
+**revoke_on** | [**CampaignRevokeOnEnum**](CampaignRevokeOnEnum.md) | | [optional]
+**reminder_schedule** | **List[int]** | Days before end date to send reminder notifications. | [optional]
+**reminder_include_manager** | **bool** | Whether to include the reviewer's manager in reminders. | [optional]
+**require_reason_on_denial** | **bool** | Whether reviewers must provide a reason when denying (revoking) access. | [optional]
+**hide_ai_suggestions** | **bool** | Whether AI suggestions are hidden from reviewers. | [optional]
+**custom_start_message** | **str** | Optional custom message included when notifying reviewers that the campaign started. | [optional]
+**group_asset_visibility_policy** | [**CampaignGroupAssetVisibilityPolicyEnum**](CampaignGroupAssetVisibilityPolicyEnum.md) | | [optional]
+**is_template** | **bool** | Whether this configuration is a recurring schedule template. | [optional]
+**cron_expression** | **str** | Cron expression driving the recurring schedule. Null for one-off campaigns. | [optional]
+**recurring_duration_days** | **int** | Deadline window in days applied to each draft generated from this template. | [optional]
+**excluded_role_assignment_ids** | **List[UUID]** | Role assignment IDs to exclude from the campaign scope during population. | [optional]
+
+## Example
+
+```python
+from opal_security.models.create_campaign_configuration_info import CreateCampaignConfigurationInfo
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of CreateCampaignConfigurationInfo from a JSON string
+create_campaign_configuration_info_instance = CreateCampaignConfigurationInfo.from_json(json)
+# print the JSON string representation of the object
+print(CreateCampaignConfigurationInfo.to_json())
+
+# convert the object into a dict
+create_campaign_configuration_info_dict = create_campaign_configuration_info_instance.to_dict()
+# create an instance of CreateCampaignConfigurationInfo from a dict
+create_campaign_configuration_info_from_dict = CreateCampaignConfigurationInfo.from_dict(create_campaign_configuration_info_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/CreateCampaignInfo.md b/docs/CreateCampaignInfo.md
new file mode 100644
index 0000000..e7a1851
--- /dev/null
+++ b/docs/CreateCampaignInfo.md
@@ -0,0 +1,31 @@
+# CreateCampaignInfo
+
+# CreateCampaignInfo Object ### Description The `CreateCampaignInfo` object is used to create a campaign. ### Usage Example Use in the `POST Campaigns` endpoint.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**name** | **str** | The name of the campaign. |
+**configuration** | [**CreateCampaignConfigurationInfo**](CreateCampaignConfigurationInfo.md) | Configuration for the campaign. Required; must include a query. Other omitted fields use defaults. |
+
+## Example
+
+```python
+from opal_security.models.create_campaign_info import CreateCampaignInfo
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of CreateCampaignInfo from a JSON string
+create_campaign_info_instance = CreateCampaignInfo.from_json(json)
+# print the JSON string representation of the object
+print(CreateCampaignInfo.to_json())
+
+# convert the object into a dict
+create_campaign_info_dict = create_campaign_info_instance.to_dict()
+# create an instance of CreateCampaignInfo from a dict
+create_campaign_info_from_dict = CreateCampaignInfo.from_dict(create_campaign_info_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/CreateGroupInfo.md b/docs/CreateGroupInfo.md
index 28c71d7..6e00baf 100644
--- a/docs/CreateGroupInfo.md
+++ b/docs/CreateGroupInfo.md
@@ -15,6 +15,8 @@ Name | Type | Description | Notes
**metadata** | **str** | Deprecated - use remote_info instead. JSON metadata about the remote group. Include only for items linked to remote systems. See [this guide](https://docs.opal.dev/reference/end-system-objects) for details on how to specify this field. The required format is dependent on group_type and should have the following schema: <style type=\"text/css\"> code {max-height:300px !important} </style> ```json { \"$schema\": \"http://json-schema.org/draft-04/schema#\", \"title\": \"Group Metadata\", \"properties\": { \"ad_group\": { \"properties\": { \"object_guid\": { \"type\": \"string\" } }, \"required\": [\"object_guid\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"Active Directory Group\" }, \"duo_group\": { \"properties\": { \"group_id\": { \"type\": \"string\" } }, \"required\": [\"group_id\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"Duo Group\" }, \"git_hub_team\": { \"properties\": { \"org_name\": { \"type\": \"string\" }, \"team_slug\": { \"type\": \"string\" } }, \"required\": [\"org_name\", \"team_slug\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"GitHub Team\" }, \"google_groups_group\": { \"properties\": { \"group_id\": { \"type\": \"string\" } }, \"required\": [\"group_id\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"Google Groups Group\" }, \"ldap_group\": { \"properties\": { \"group_uid\": { \"type\": \"string\" } }, \"required\": [\"group_uid\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"LDAP Group\" }, \"okta_directory_group\": { \"properties\": { \"group_id\": { \"type\": \"string\" } }, \"required\": [\"group_id\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"Okta Directory Group\" } }, \"additionalProperties\": false, \"minProperties\": 1, \"maxProperties\": 1, \"type\": \"object\" } ``` | [optional]
**custom_request_notification** | **str** | Custom request notification sent upon request approval. | [optional]
**risk_sensitivity_override** | [**RiskSensitivityEnum**](RiskSensitivityEnum.md) | | [optional]
+**match_remote_name** | **bool** | A bool representing whether or not the group's name should be synced from the end system. When true, the name is overwritten with the remote name on each sync, so a `name` provided together with this field set to true will be replaced at the next sync. Defaults to false. | [optional]
+**match_remote_description** | **bool** | A bool representing whether or not the group's description should be synced from the end system. When true, the description is overwritten with the remote description on each sync, so a `description` provided together with this field set to true will be replaced at the next sync. Defaults to false. | [optional]
## Example
diff --git a/docs/CreateResourceInfo.md b/docs/CreateResourceInfo.md
index 6d0e662..066af7f 100644
--- a/docs/CreateResourceInfo.md
+++ b/docs/CreateResourceInfo.md
@@ -15,6 +15,8 @@ Name | Type | Description | Notes
**metadata** | **str** | Deprecated - use remote_info instead. JSON metadata about the remote resource. Include only for items linked to remote systems. See [this guide](https://docs.opal.dev/reference/end-system-objects) for details on how to specify this field. The required format is dependent on resource_type and should have the following schema: <style type=\"text/css\"> code {max-height:300px !important} </style> ```json { \"$schema\": \"http://json-schema.org/draft-04/schema#\", \"title\": \"Resource Metadata\", \"properties\": { \"aws_ec2_instance\": { \"properties\": { \"instance_id\": { \"type\": \"string\" }, \"region\": { \"type\": \"string\" } }, \"required\": [\"instance_id\", \"region\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"AWS EC2 Instance\" }, \"aws_eks_cluster\": { \"properties\": { \"cluster_name\": { \"type\": \"string\" }, \"cluster_region\": { \"type\": \"string\" }, \"cluster_arn\": { \"type\": \"string\" } }, \"required\": [\"cluster_name\", \"cluster_region\", \"cluster_arn\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"AWS EKS Cluster\" }, \"aws_rds_instance\": { \"properties\": { \"instance_id\": { \"type\": \"string\" }, \"engine\": { \"type\": \"string\" }, \"region\": { \"type\": \"string\" }, \"resource_id\": { \"type\": \"string\" }, \"database_name\": { \"type\": \"string\" } }, \"required\": [ \"instance_id\", \"engine\", \"region\", \"resource_id\", \"database_name\" ], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"AWS RDS Instance\" }, \"aws_role\": { \"properties\": { \"arn\": { \"type\": \"string\" }, \"name\": { \"type\": \"string\" } }, \"required\": [\"arn\", \"name\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"AWS Role\" }, \"gcp_bucket\": { \"properties\": { \"bucket_id\": { \"type\": \"string\" } }, \"required\": [\"bucket_id\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"GCP Bucket\" }, \"gcp_compute_instance\": { \"properties\": { \"instance_id\": { \"type\": \"string\" }, \"project_id\": { \"type\": \"string\" }, \"zone\": { \"type\": \"string\" } }, \"required\": [\"instance_id\", \"project_id\", \"zone\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"GCP Compute Instance\" }, \"gcp_folder\": { \"properties\": { \"folder_id\": { \"type\": \"string\" } }, \"required\": [\"folder_id\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"GCP Folder\" }, \"gcp_gke_cluster\": { \"properties\": { \"cluster_name\": { \"type\": \"string\" } }, \"required\": [\"cluster_name\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"GCP GKE Cluster\" }, \"gcp_project\": { \"properties\": { \"project_id\": { \"type\": \"string\" } }, \"required\": [\"project_id\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"GCP Project\" }, \"gcp_sql_instance\": { \"properties\": { \"instance_id\": { \"type\": \"string\" }, \"project_id\": { \"type\": \"string\" } }, \"required\": [\"instance_id\", \"project_id\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"GCP SQL Instance\" }, \"git_hub_repo\": { \"properties\": { \"org_name\": { \"type\": \"string\" }, \"repo_name\": { \"type\": \"string\" } }, \"required\": [\"org_name\", \"repo_name\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"GitHub Repo\" }, \"okta_directory_app\": { \"properties\": { \"app_id\": { \"type\": \"string\" }, \"logo_url\": { \"type\": \"string\" } }, \"required\": [\"app_id\", \"logo_url\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"Okta Directory App\" }, \"okta_directory_role\": { \"properties\": { \"role_type\": { \"type\": \"string\" }, \"role_id\": { \"type\": \"string\" } }, \"required\": [\"role_type\", \"role_id\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"Okta Directory Role\" }, \"salesforce_profile\": { \"properties\": { \"user_license\": { \"type\": \"string\" } }, \"required\": [\"user_license\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"Salesforce Profile\" } }, \"additionalProperties\": false, \"minProperties\": 1, \"maxProperties\": 1, \"type\": \"object\" } ``` | [optional]
**custom_request_notification** | **str** | Custom request notification sent upon request approval. | [optional]
**risk_sensitivity_override** | [**RiskSensitivityEnum**](RiskSensitivityEnum.md) | | [optional]
+**match_remote_name** | **bool** | A bool representing whether or not the resource's name should be synced from the end system. When true, the name is overwritten with the remote name on each sync, so a `name` provided together with this field set to true will be replaced at the next sync. Defaults to false. | [optional]
+**match_remote_description** | **bool** | A bool representing whether or not the resource's description should be synced from the end system. When true, the description is overwritten with the remote description on each sync, so a `description` provided together with this field set to true will be replaced at the next sync. Defaults to false. | [optional]
## Example
diff --git a/docs/EntityAdminFilter.md b/docs/EntityAdminFilter.md
new file mode 100644
index 0000000..9f7931d
--- /dev/null
+++ b/docs/EntityAdminFilter.md
@@ -0,0 +1,31 @@
+# EntityAdminFilter
+
+Filters GROUP and RESOURCE entities by their admin owner. USER entities never match, in either polarity. `not` inverts the match within the resource/group domain (self-negating, like IdpStatusFilter): omit it (or false) to include entities owned by the given owners, set it true to exclude them.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**owner_ids** | **List[UUID]** | The owner (group) UUIDs to match entities against. |
+**var_not** | **bool** | Invert the match — return resources/groups NOT owned by the given owners. | [optional]
+
+## Example
+
+```python
+from opal_security.models.entity_admin_filter import EntityAdminFilter
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of EntityAdminFilter from a JSON string
+entity_admin_filter_instance = EntityAdminFilter.from_json(json)
+# print the JSON string representation of the object
+print(EntityAdminFilter.to_json())
+
+# convert the object into a dict
+entity_admin_filter_dict = entity_admin_filter_instance.to_dict()
+# create an instance of EntityAdminFilter from a dict
+entity_admin_filter_from_dict = EntityAdminFilter.from_dict(entity_admin_filter_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/Group.md b/docs/Group.md
index 45928d5..846be1f 100644
--- a/docs/Group.md
+++ b/docs/Group.md
@@ -34,6 +34,8 @@ Name | Type | Description | Notes
**custom_request_notification** | **str** | Custom request notification sent to the requester when the request is approved. | [optional]
**risk_sensitivity** | [**RiskSensitivityEnum**](RiskSensitivityEnum.md) | The risk sensitivity level for the group. When an override is set, this field will match that. | [optional] [readonly]
**risk_sensitivity_override** | [**RiskSensitivityEnum**](RiskSensitivityEnum.md) | | [optional]
+**match_remote_name** | **bool** | A bool representing whether or not the group's name is synced from the end system. When true, the name is overwritten with the remote name on each sync. Defaults to false. | [optional]
+**match_remote_description** | **bool** | A bool representing whether or not the group's description is synced from the end system. When true, the description is overwritten with the remote description on each sync. Defaults to false. | [optional]
**last_successful_sync** | [**SyncTask**](SyncTask.md) | Information about the last successful sync of this group. | [optional] [readonly]
## Example
diff --git a/docs/GroupRemoteInfo.md b/docs/GroupRemoteInfo.md
index d96154d..461c51f 100644
--- a/docs/GroupRemoteInfo.md
+++ b/docs/GroupRemoteInfo.md
@@ -35,6 +35,7 @@ Name | Type | Description | Notes
**slack_user_group** | [**GroupRemoteInfoSlackUserGroup**](GroupRemoteInfoSlackUserGroup.md) | | [optional]
**zendesk_organization** | [**GroupRemoteInfoZendeskOrganization**](GroupRemoteInfoZendeskOrganization.md) | | [optional]
**hubspot_team** | [**GroupRemoteInfoHubspotTeam**](GroupRemoteInfoHubspotTeam.md) | | [optional]
+**tableau_group** | [**GroupRemoteInfoTableauGroup**](GroupRemoteInfoTableauGroup.md) | | [optional]
## Example
diff --git a/docs/GroupRemoteInfoTableauGroup.md b/docs/GroupRemoteInfoTableauGroup.md
new file mode 100644
index 0000000..3c70278
--- /dev/null
+++ b/docs/GroupRemoteInfoTableauGroup.md
@@ -0,0 +1,30 @@
+# GroupRemoteInfoTableauGroup
+
+Remote info for Tableau group.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**group_id** | **str** | The ID of the Tableau group. |
+
+## Example
+
+```python
+from opal_security.models.group_remote_info_tableau_group import GroupRemoteInfoTableauGroup
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of GroupRemoteInfoTableauGroup from a JSON string
+group_remote_info_tableau_group_instance = GroupRemoteInfoTableauGroup.from_json(json)
+# print the JSON string representation of the object
+print(GroupRemoteInfoTableauGroup.to_json())
+
+# convert the object into a dict
+group_remote_info_tableau_group_dict = group_remote_info_tableau_group_instance.to_dict()
+# create an instance of GroupRemoteInfoTableauGroup from a dict
+group_remote_info_tableau_group_from_dict = GroupRemoteInfoTableauGroup.from_dict(group_remote_info_tableau_group_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/GroupTypeEnum.md b/docs/GroupTypeEnum.md
index ca6fdbf..9da03f9 100644
--- a/docs/GroupTypeEnum.md
+++ b/docs/GroupTypeEnum.md
@@ -68,6 +68,8 @@ The type of the group.
* `HUBSPOT_TEAM` (value: `'HUBSPOT_TEAM'`)
+* `TABLEAU_GROUP` (value: `'TABLEAU_GROUP'`)
+
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
diff --git a/docs/GroupsApi.md b/docs/GroupsApi.md
index d311da4..0381d3f 100644
--- a/docs/GroupsApi.md
+++ b/docs/GroupsApi.md
@@ -1257,7 +1257,7 @@ with opal_security.ApiClient(configuration) as api_client:
api_instance = opal_security.GroupsApi(api_client)
group_id = UUID('4baf8423-db0a-4037-a4cf-f79c60cb67a5') # UUID | The ID of the group.
cursor = 'cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw' # str | The pagination cursor value. (optional)
- page_size = 200 # int | Number of results to return per page. Default is 200. (optional)
+ page_size = 200 # int | Number of results to return per page, up to 1000. When set (or when a cursor is provided), the response contains a single page of results and a `next` cursor; the default page size is 200. When both page_size and cursor are omitted, the entire group membership is returned in one response with no `next` cursor. For large groups, prefer setting page_size and following `next`. (optional)
try:
api_response = api_instance.get_group_users(group_id, cursor=cursor, page_size=page_size)
@@ -1276,7 +1276,7 @@ Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**group_id** | **UUID**| The ID of the group. |
**cursor** | **str**| The pagination cursor value. | [optional]
- **page_size** | **int**| Number of results to return per page. Default is 200. | [optional]
+ **page_size** | **int**| Number of results to return per page, up to 1000. When set (or when a cursor is provided), the response contains a single page of results and a `next` cursor; the default page size is 200. When both page_size and cursor are omitted, the entire group membership is returned in one response with no `next` cursor. For large groups, prefer setting page_size and following `next`. | [optional]
### Return type
diff --git a/docs/IdpStatusFilter.md b/docs/IdpStatusFilter.md
new file mode 100644
index 0000000..b4b76ae
--- /dev/null
+++ b/docs/IdpStatusFilter.md
@@ -0,0 +1,31 @@
+# IdpStatusFilter
+
+Filters USER entities by their HR/IDP lifecycle status. Only applies to USER entities; GROUP and RESOURCE entities never match, in either polarity. `statuses` combine with OR. `not` inverts the match within the user domain (e.g. \"IDP status is NOT active\"), so it still returns only users rather than sweeping in groups/resources.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**statuses** | [**List[UserHrIdpStatusEnum]**](UserHrIdpStatusEnum.md) | Match users whose HR/IDP status is one of these values. | [optional]
+**var_not** | **bool** | Invert the match within the user domain (e.g. \"IDP status is NOT active\"). | [optional]
+
+## Example
+
+```python
+from opal_security.models.idp_status_filter import IdpStatusFilter
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of IdpStatusFilter from a JSON string
+idp_status_filter_instance = IdpStatusFilter.from_json(json)
+# print the JSON string representation of the object
+print(IdpStatusFilter.to_json())
+
+# convert the object into a dict
+idp_status_filter_dict = idp_status_filter_instance.to_dict()
+# create an instance of IdpStatusFilter from a dict
+idp_status_filter_from_dict = IdpStatusFilter.from_dict(idp_status_filter_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/OpalAccessPathEdgeFilter.md b/docs/OpalAccessPathEdgeFilter.md
new file mode 100644
index 0000000..b0b9620
--- /dev/null
+++ b/docs/OpalAccessPathEdgeFilter.md
@@ -0,0 +1,31 @@
+# OpalAccessPathEdgeFilter
+
+Constraints on the access path edges themselves.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**direct_only** | **bool** | When true, only return direct (depth-1) principal-to-entitlement edges. | [optional]
+**access_duration_type** | **str** | Constrain results by whether the terminal access expires. | [optional]
+
+## Example
+
+```python
+from opal_security.models.opal_access_path_edge_filter import OpalAccessPathEdgeFilter
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of OpalAccessPathEdgeFilter from a JSON string
+opal_access_path_edge_filter_instance = OpalAccessPathEdgeFilter.from_json(json)
+# print the JSON string representation of the object
+print(OpalAccessPathEdgeFilter.to_json())
+
+# convert the object into a dict
+opal_access_path_edge_filter_dict = opal_access_path_edge_filter_instance.to_dict()
+# create an instance of OpalAccessPathEdgeFilter from a dict
+opal_access_path_edge_filter_from_dict = OpalAccessPathEdgeFilter.from_dict(opal_access_path_edge_filter_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/OpalAccessPathQuery.md b/docs/OpalAccessPathQuery.md
new file mode 100644
index 0000000..f23c918
--- /dev/null
+++ b/docs/OpalAccessPathQuery.md
@@ -0,0 +1,34 @@
+# OpalAccessPathQuery
+
+Request body for an ACCESS_PATH-type OpalQuery. Returns principal-to- entitlement access paths matching the given edge filters.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**type** | **str** | |
+**query** | [**OpalAccessPathQueryBody**](OpalAccessPathQueryBody.md) | | [optional]
+**first** | **int** | Maximum number of results to return. Defaults to 200. | [optional]
+**after** | **str** | Opaque cursor from a previous ACCESS_PATH response to fetch the next page of results. | [optional]
+**include_count** | **bool** | When true, populate totalCount in the response. Defaults to false. | [optional]
+
+## Example
+
+```python
+from opal_security.models.opal_access_path_query import OpalAccessPathQuery
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of OpalAccessPathQuery from a JSON string
+opal_access_path_query_instance = OpalAccessPathQuery.from_json(json)
+# print the JSON string representation of the object
+print(OpalAccessPathQuery.to_json())
+
+# convert the object into a dict
+opal_access_path_query_dict = opal_access_path_query_instance.to_dict()
+# create an instance of OpalAccessPathQuery from a dict
+opal_access_path_query_from_dict = OpalAccessPathQuery.from_dict(opal_access_path_query_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/OpalAccessPathQueryBody.md b/docs/OpalAccessPathQueryBody.md
new file mode 100644
index 0000000..eb0461e
--- /dev/null
+++ b/docs/OpalAccessPathQueryBody.md
@@ -0,0 +1,36 @@
+# OpalAccessPathQueryBody
+
+Edge-query filters for an ACCESS_PATH OpalQuery. At least one of principalFilter or entitlementFilter is required.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**principal_filter** | [**AccessEntityFilters**](AccessEntityFilters.md) | | [optional]
+**entitlement_filter** | [**AccessEntityFilters**](AccessEntityFilters.md) | | [optional]
+**principal_access_filters** | [**AccessRelationshipFilters**](AccessRelationshipFilters.md) | Advanced access filter on the principal side of each path. Restricts results to principals that additionally satisfy these access-edge constraints: `hasAccessTo` keeps only principals that also have access to a matching entity; `isAccessibleBy` keeps only principals that are also accessible by a matching entity. Only takes effect when `principalFilter` is also supplied (it refines that filter); on its own it has no effect. | [optional]
+**entitlement_access_filters** | [**AccessRelationshipFilters**](AccessRelationshipFilters.md) | Advanced access filter on the entitlement side of each path. Restricts results to entitlements that additionally satisfy these access-edge constraints: `hasAccessTo` keeps only entitlements that also have access to a matching entity; `isAccessibleBy` keeps only entitlements that are also accessible by a matching entity. Only takes effect when `entitlementFilter` is also supplied (it refines that filter); on its own it has no effect. | [optional]
+**access_level_remote_ids** | **List[str]** | Filter by access-level remote IDs on the terminal edge. | [optional]
+**access_level_names** | **List[str]** | Filter by access-level display names on the terminal edge. | [optional]
+**edge_filter** | [**OpalAccessPathEdgeFilter**](OpalAccessPathEdgeFilter.md) | | [optional]
+
+## Example
+
+```python
+from opal_security.models.opal_access_path_query_body import OpalAccessPathQueryBody
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of OpalAccessPathQueryBody from a JSON string
+opal_access_path_query_body_instance = OpalAccessPathQueryBody.from_json(json)
+# print the JSON string representation of the object
+print(OpalAccessPathQueryBody.to_json())
+
+# convert the object into a dict
+opal_access_path_query_body_dict = opal_access_path_query_body_instance.to_dict()
+# create an instance of OpalAccessPathQueryBody from a dict
+opal_access_path_query_body_from_dict = OpalAccessPathQueryBody.from_dict(opal_access_path_query_body_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/OpalAccessPathQueryResults.md b/docs/OpalAccessPathQueryResults.md
new file mode 100644
index 0000000..c196f33
--- /dev/null
+++ b/docs/OpalAccessPathQueryResults.md
@@ -0,0 +1,33 @@
+# OpalAccessPathQueryResults
+
+Paginated results of an ACCESS_PATH-type OpalQuery — one edge per matched principal-to-entitlement access path.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**type** | **str** | |
+**edges** | [**List[OpalAccessPathResultEdge]**](OpalAccessPathResultEdge.md) | List of matched access paths. |
+**page_info** | [**PageInfo**](PageInfo.md) | |
+**total_count** | **int** | Exact total number of matching paths when includeCount was true on the request; otherwise null. | [optional]
+
+## Example
+
+```python
+from opal_security.models.opal_access_path_query_results import OpalAccessPathQueryResults
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of OpalAccessPathQueryResults from a JSON string
+opal_access_path_query_results_instance = OpalAccessPathQueryResults.from_json(json)
+# print the JSON string representation of the object
+print(OpalAccessPathQueryResults.to_json())
+
+# convert the object into a dict
+opal_access_path_query_results_dict = opal_access_path_query_results_instance.to_dict()
+# create an instance of OpalAccessPathQueryResults from a dict
+opal_access_path_query_results_from_dict = OpalAccessPathQueryResults.from_dict(opal_access_path_query_results_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/OpalAccessPathResultEdge.md b/docs/OpalAccessPathResultEdge.md
new file mode 100644
index 0000000..35591bd
--- /dev/null
+++ b/docs/OpalAccessPathResultEdge.md
@@ -0,0 +1,31 @@
+# OpalAccessPathResultEdge
+
+A single ACCESS_PATH result edge containing the matched path and its pagination cursor.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**node** | [**OpalAccessPathResultNode**](OpalAccessPathResultNode.md) | |
+**cursor** | **str** | Opaque cursor for this path, used for pagination. |
+
+## Example
+
+```python
+from opal_security.models.opal_access_path_result_edge import OpalAccessPathResultEdge
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of OpalAccessPathResultEdge from a JSON string
+opal_access_path_result_edge_instance = OpalAccessPathResultEdge.from_json(json)
+# print the JSON string representation of the object
+print(OpalAccessPathResultEdge.to_json())
+
+# convert the object into a dict
+opal_access_path_result_edge_dict = opal_access_path_result_edge_instance.to_dict()
+# create an instance of OpalAccessPathResultEdge from a dict
+opal_access_path_result_edge_from_dict = OpalAccessPathResultEdge.from_dict(opal_access_path_result_edge_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/OpalAccessPathResultNode.md b/docs/OpalAccessPathResultNode.md
new file mode 100644
index 0000000..132073a
--- /dev/null
+++ b/docs/OpalAccessPathResultNode.md
@@ -0,0 +1,36 @@
+# OpalAccessPathResultNode
+
+A matched access path from an ACCESS_PATH OpalQuery.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**principal_id** | **UUID** | The principal entity ID. |
+**entitlement_id** | **UUID** | The entitlement entity ID. |
+**access_level_remote_id** | **str** | Remote ID of the terminal access level. | [optional]
+**access_level_name** | **str** | Display name of the terminal access level. | [optional]
+**expiration** | **datetime** | Expiration of the terminal access, if any. | [optional]
+**depth** | **int** | Number of hops from principal to entitlement (path length - 1). |
+**path** | **List[UUID]** | Entity IDs along the path from principal to entitlement. |
+
+## Example
+
+```python
+from opal_security.models.opal_access_path_result_node import OpalAccessPathResultNode
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of OpalAccessPathResultNode from a JSON string
+opal_access_path_result_node_instance = OpalAccessPathResultNode.from_json(json)
+# print the JSON string representation of the object
+print(OpalAccessPathResultNode.to_json())
+
+# convert the object into a dict
+opal_access_path_result_node_dict = opal_access_path_result_node_instance.to_dict()
+# create an instance of OpalAccessPathResultNode from a dict
+opal_access_path_result_node_from_dict = OpalAccessPathResultNode.from_dict(opal_access_path_result_node_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/OpalQueriesApi.md b/docs/OpalQueriesApi.md
index 3be1004..e0b22a3 100644
--- a/docs/OpalQueriesApi.md
+++ b/docs/OpalQueriesApi.md
@@ -8,11 +8,11 @@ Method | HTTP request | Description
# **run_opal_query**
-> OpalNodeQueryResults run_opal_query(body)
+> OpalQueryResults run_opal_query(run_opal_query_request)
Run an ad-hoc OpalQuery
-Runs an ad-hoc OpalQuery and returns the results. Currently supports NODE queries (users, resources, groups). This endpoint is only available to our OpalQuery beta group. Please contact Opal support if you'd like to be added to the beta.
+Runs an ad-hoc OpalQuery and returns the results. Supports NODE queries (users, resources, groups) and ACCESS_PATH queries (principal-to-entitlement access edges). This endpoint is only available to our OpalQuery beta group. Please contact Opal support if you'd like to be added to the beta.
### Example
@@ -20,8 +20,8 @@ Runs an ad-hoc OpalQuery and returns the results. Currently supports NODE querie
```python
import opal_security
-from opal_security.models.opal_node_query import OpalNodeQuery
-from opal_security.models.opal_node_query_results import OpalNodeQueryResults
+from opal_security.models.opal_query_results import OpalQueryResults
+from opal_security.models.run_opal_query_request import RunOpalQueryRequest
from opal_security.rest import ApiException
from pprint import pprint
@@ -47,11 +47,11 @@ configuration = opal.Configuration(
with opal_security.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = opal_security.OpalQueriesApi(api_client)
- body = opal_security.OpalNodeQuery() # OpalNodeQuery |
+ run_opal_query_request = opal_security.RunOpalQueryRequest() # RunOpalQueryRequest |
try:
# Run an ad-hoc OpalQuery
- api_response = api_instance.run_opal_query(body)
+ api_response = api_instance.run_opal_query(run_opal_query_request)
print("The response of OpalQueriesApi->run_opal_query:\n")
pprint(api_response)
except Exception as e:
@@ -65,11 +65,11 @@ with opal_security.ApiClient(configuration) as api_client:
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
- **body** | **OpalNodeQuery**| |
+ **run_opal_query_request** | [**RunOpalQueryRequest**](RunOpalQueryRequest.md)| |
### Return type
-[**OpalNodeQueryResults**](OpalNodeQueryResults.md)
+[**OpalQueryResults**](OpalQueryResults.md)
### Authorization
diff --git a/docs/OpalQueryResults.md b/docs/OpalQueryResults.md
new file mode 100644
index 0000000..3f65866
--- /dev/null
+++ b/docs/OpalQueryResults.md
@@ -0,0 +1,33 @@
+# OpalQueryResults
+
+Paginated results of an OpalQuery. The `type` field discriminates which result schema applies and mirrors the `type` field on the request.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**type** | **str** | |
+**edges** | [**List[OpalAccessPathResultEdge]**](OpalAccessPathResultEdge.md) | List of matched access paths. |
+**page_info** | [**PageInfo**](PageInfo.md) | |
+**total_count** | **int** | Exact total number of matching paths when includeCount was true on the request; otherwise null. | [optional]
+
+## Example
+
+```python
+from opal_security.models.opal_query_results import OpalQueryResults
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of OpalQueryResults from a JSON string
+opal_query_results_instance = OpalQueryResults.from_json(json)
+# print the JSON string representation of the object
+print(OpalQueryResults.to_json())
+
+# convert the object into a dict
+opal_query_results_dict = opal_query_results_instance.to_dict()
+# create an instance of OpalQueryResults from a dict
+opal_query_results_from_dict = OpalQueryResults.from_dict(opal_query_results_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/PaginatedCampaignsList.md b/docs/PaginatedCampaignsList.md
new file mode 100644
index 0000000..97bd506
--- /dev/null
+++ b/docs/PaginatedCampaignsList.md
@@ -0,0 +1,32 @@
+# PaginatedCampaignsList
+
+A list of campaigns.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**next** | **str** | The cursor with which to continue pagination if additional result pages exist. | [optional]
+**previous** | **str** | The cursor used to obtain the current result page. | [optional]
+**results** | [**List[Campaign]**](Campaign.md) | |
+
+## Example
+
+```python
+from opal_security.models.paginated_campaigns_list import PaginatedCampaignsList
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of PaginatedCampaignsList from a JSON string
+paginated_campaigns_list_instance = PaginatedCampaignsList.from_json(json)
+# print the JSON string representation of the object
+print(PaginatedCampaignsList.to_json())
+
+# convert the object into a dict
+paginated_campaigns_list_dict = paginated_campaigns_list_instance.to_dict()
+# create an instance of PaginatedCampaignsList from a dict
+paginated_campaigns_list_from_dict = PaginatedCampaignsList.from_dict(paginated_campaigns_list_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/Paladin.md b/docs/Paladin.md
new file mode 100644
index 0000000..12dd849
--- /dev/null
+++ b/docs/Paladin.md
@@ -0,0 +1,31 @@
+# Paladin
+
+# Paladin Object ### Description The `Paladin` object represents a Paladin, Opal's AI access-request reviewer.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**paladin_id** | **UUID** | The ID of the Paladin. Use this value as a reviewer in a request configuration's service_user_ids. |
+**name** | **str** | The name of the Paladin. |
+
+## Example
+
+```python
+from opal_security.models.paladin import Paladin
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of Paladin from a JSON string
+paladin_instance = Paladin.from_json(json)
+# print the JSON string representation of the object
+print(Paladin.to_json())
+
+# convert the object into a dict
+paladin_dict = paladin_instance.to_dict()
+# create an instance of Paladin from a dict
+paladin_from_dict = Paladin.from_dict(paladin_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/PaladinApi.md b/docs/PaladinApi.md
new file mode 100644
index 0000000..8f8c847
--- /dev/null
+++ b/docs/PaladinApi.md
@@ -0,0 +1,170 @@
+# opal_security.PaladinApi
+
+All URIs are relative to *https://api.opal.dev/v1*
+
+Method | HTTP request | Description
+------------- | ------------- | -------------
+[**get_paladin**](PaladinApi.md#get_paladin) | **GET** /paladin/{paladin_id} | Get Paladin by ID
+[**get_paladin_from_name**](PaladinApi.md#get_paladin_from_name) | **GET** /paladin/name/{paladin_name} | Get Paladins by name
+
+
+# **get_paladin**
+> Paladin get_paladin(paladin_id)
+
+Get Paladin by ID
+
+Returns a `Paladin` object.
+
+### Example
+
+* Bearer Authentication (BearerAuth):
+
+```python
+import opal_security
+from opal_security.models.paladin import Paladin
+from opal_security.rest import ApiException
+from pprint import pprint
+
+# Defining the host is optional and defaults to https://api.opal.dev/v1
+# See configuration.py for a list of all supported configuration parameters.
+import opal_security as opal
+
+configuration = opal.Configuration(
+ host = "https://api.opal.dev/v1"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure Bearer authorization: BearerAuth
+configuration = opal.Configuration(
+ access_token = os.environ["BEARER_TOKEN"]
+)
+
+# Enter a context with an instance of the API client
+with opal_security.ApiClient(configuration) as api_client:
+ # Create an instance of the API class
+ api_instance = opal_security.PaladinApi(api_client)
+ paladin_id = UUID('32acc112-21ff-4669-91c2-21e27683eaa1') # UUID | The ID of the Paladin.
+
+ try:
+ # Get Paladin by ID
+ api_response = api_instance.get_paladin(paladin_id)
+ print("The response of PaladinApi->get_paladin:\n")
+ pprint(api_response)
+ except Exception as e:
+ print("Exception when calling PaladinApi->get_paladin: %s\n" % e)
+```
+
+
+
+### Parameters
+
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **paladin_id** | **UUID**| The ID of the Paladin. |
+
+### Return type
+
+[**Paladin**](Paladin.md)
+
+### Authorization
+
+[BearerAuth](../README.md#BearerAuth)
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
+### HTTP response details
+
+| Status code | Description | Response headers |
+|-------------|-------------|------------------|
+**200** | The Paladin associated with the passed-in ID. | - |
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
+# **get_paladin_from_name**
+> PaladinList get_paladin_from_name(paladin_name)
+
+Get Paladins by name
+
+Returns all Paladins whose name exactly matches the given name. Names are not unique, so the result is a list and may be empty.
+
+### Example
+
+* Bearer Authentication (BearerAuth):
+
+```python
+import opal_security
+from opal_security.models.paladin_list import PaladinList
+from opal_security.rest import ApiException
+from pprint import pprint
+
+# Defining the host is optional and defaults to https://api.opal.dev/v1
+# See configuration.py for a list of all supported configuration parameters.
+import opal_security as opal
+
+configuration = opal.Configuration(
+ host = "https://api.opal.dev/v1"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure Bearer authorization: BearerAuth
+configuration = opal.Configuration(
+ access_token = os.environ["BEARER_TOKEN"]
+)
+
+# Enter a context with an instance of the API client
+with opal_security.ApiClient(configuration) as api_client:
+ # Create an instance of the API class
+ api_instance = opal_security.PaladinApi(api_client)
+ paladin_name = 'paladin-agent-1' # str | The name of the Paladin.
+
+ try:
+ # Get Paladins by name
+ api_response = api_instance.get_paladin_from_name(paladin_name)
+ print("The response of PaladinApi->get_paladin_from_name:\n")
+ pprint(api_response)
+ except Exception as e:
+ print("Exception when calling PaladinApi->get_paladin_from_name: %s\n" % e)
+```
+
+
+
+### Parameters
+
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **paladin_name** | **str**| The name of the Paladin. |
+
+### Return type
+
+[**PaladinList**](PaladinList.md)
+
+### Authorization
+
+[BearerAuth](../README.md#BearerAuth)
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
+### HTTP response details
+
+| Status code | Description | Response headers |
+|-------------|-------------|------------------|
+**200** | The list of Paladins matching the passed-in name. | - |
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
diff --git a/docs/PaladinList.md b/docs/PaladinList.md
new file mode 100644
index 0000000..fc5df40
--- /dev/null
+++ b/docs/PaladinList.md
@@ -0,0 +1,30 @@
+# PaladinList
+
+# PaladinList Object ### Description A list of `Paladin` objects.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**results** | [**List[Paladin]**](Paladin.md) | |
+
+## Example
+
+```python
+from opal_security.models.paladin_list import PaladinList
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of PaladinList from a JSON string
+paladin_list_instance = PaladinList.from_json(json)
+# print the JSON string representation of the object
+print(PaladinList.to_json())
+
+# convert the object into a dict
+paladin_list_dict = paladin_list_instance.to_dict()
+# create an instance of PaladinList from a dict
+paladin_list_from_dict = PaladinList.from_dict(paladin_list_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/PropagationStatusEnum.md b/docs/PropagationStatusEnum.md
index ded75f9..74eb900 100644
--- a/docs/PropagationStatusEnum.md
+++ b/docs/PropagationStatusEnum.md
@@ -46,6 +46,8 @@ The status of whether the user has been synced to the group or resource in the r
* `ERR_REMOTE_UNRECOVERABLE_ERROR` (value: `'ERR_REMOTE_UNRECOVERABLE_ERROR'`)
+* `ERR_REMOTE_TICKET_NOT_FOUND` (value: `'ERR_REMOTE_TICKET_NOT_FOUND'`)
+
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
diff --git a/docs/Resource.md b/docs/Resource.md
index f87a8d0..ce00690 100644
--- a/docs/Resource.md
+++ b/docs/Resource.md
@@ -37,6 +37,8 @@ Name | Type | Description | Notes
**remote_info** | [**ResourceRemoteInfo**](ResourceRemoteInfo.md) | | [optional]
**ancestor_resource_ids** | **List[UUID]** | List of resource IDs that are ancestors of this resource. | [optional]
**descendant_resource_ids** | **List[UUID]** | List of resource IDs that are descendants of this resource. | [optional]
+**match_remote_name** | **bool** | A bool representing whether or not the resource's name is synced from the end system. When true, the name is overwritten with the remote name on each sync. Defaults to false. | [optional]
+**match_remote_description** | **bool** | A bool representing whether or not the resource's description is synced from the end system. When true, the description is overwritten with the remote description on each sync. Defaults to false. | [optional]
**last_successful_sync** | [**SyncTask**](SyncTask.md) | Information about the last successful sync of this resource. | [optional] [readonly]
## Example
diff --git a/docs/ResourceRemoteInfo.md b/docs/ResourceRemoteInfo.md
index aad6e03..5cf13d0 100644
--- a/docs/ResourceRemoteInfo.md
+++ b/docs/ResourceRemoteInfo.md
@@ -78,6 +78,8 @@ Name | Type | Description | Notes
**grafana_role** | [**ResourceRemoteInfoGrafanaRole**](ResourceRemoteInfoGrafanaRole.md) | | [optional]
**zendesk_role** | [**ResourceRemoteInfoZendeskRole**](ResourceRemoteInfoZendeskRole.md) | | [optional]
**hubspot_role** | [**ResourceRemoteInfoHubspotRole**](ResourceRemoteInfoHubspotRole.md) | | [optional]
+**alicloud_ram_role** | [**ResourceRemoteInfoAlicloudRamRole**](ResourceRemoteInfoAlicloudRamRole.md) | | [optional]
+**alicloud_ecs_instance** | [**ResourceRemoteInfoAlicloudEcsInstance**](ResourceRemoteInfoAlicloudEcsInstance.md) | | [optional]
## Example
diff --git a/docs/ResourceRemoteInfoAlicloudEcsInstance.md b/docs/ResourceRemoteInfoAlicloudEcsInstance.md
new file mode 100644
index 0000000..d0a080a
--- /dev/null
+++ b/docs/ResourceRemoteInfoAlicloudEcsInstance.md
@@ -0,0 +1,30 @@
+# ResourceRemoteInfoAlicloudEcsInstance
+
+Remote info for AliCloud ECS instance.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**instance_id** | **str** | The ID of the ECS instance. |
+
+## Example
+
+```python
+from opal_security.models.resource_remote_info_alicloud_ecs_instance import ResourceRemoteInfoAlicloudEcsInstance
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of ResourceRemoteInfoAlicloudEcsInstance from a JSON string
+resource_remote_info_alicloud_ecs_instance_instance = ResourceRemoteInfoAlicloudEcsInstance.from_json(json)
+# print the JSON string representation of the object
+print(ResourceRemoteInfoAlicloudEcsInstance.to_json())
+
+# convert the object into a dict
+resource_remote_info_alicloud_ecs_instance_dict = resource_remote_info_alicloud_ecs_instance_instance.to_dict()
+# create an instance of ResourceRemoteInfoAlicloudEcsInstance from a dict
+resource_remote_info_alicloud_ecs_instance_from_dict = ResourceRemoteInfoAlicloudEcsInstance.from_dict(resource_remote_info_alicloud_ecs_instance_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/ResourceRemoteInfoAlicloudRamRole.md b/docs/ResourceRemoteInfoAlicloudRamRole.md
new file mode 100644
index 0000000..5473583
--- /dev/null
+++ b/docs/ResourceRemoteInfoAlicloudRamRole.md
@@ -0,0 +1,30 @@
+# ResourceRemoteInfoAlicloudRamRole
+
+Remote info for AliCloud RAM role.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**role_arn** | **str** | The ARN of the AliCloud RAM role. |
+
+## Example
+
+```python
+from opal_security.models.resource_remote_info_alicloud_ram_role import ResourceRemoteInfoAlicloudRamRole
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of ResourceRemoteInfoAlicloudRamRole from a JSON string
+resource_remote_info_alicloud_ram_role_instance = ResourceRemoteInfoAlicloudRamRole.from_json(json)
+# print the JSON string representation of the object
+print(ResourceRemoteInfoAlicloudRamRole.to_json())
+
+# convert the object into a dict
+resource_remote_info_alicloud_ram_role_dict = resource_remote_info_alicloud_ram_role_instance.to_dict()
+# create an instance of ResourceRemoteInfoAlicloudRamRole from a dict
+resource_remote_info_alicloud_ram_role_from_dict = ResourceRemoteInfoAlicloudRamRole.from_dict(resource_remote_info_alicloud_ram_role_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/ResourceTypeEnum.md b/docs/ResourceTypeEnum.md
index 6c667fc..53a230a 100644
--- a/docs/ResourceTypeEnum.md
+++ b/docs/ResourceTypeEnum.md
@@ -176,6 +176,10 @@ The type of the resource.
* `HUBSPOT_ROLE` (value: `'HUBSPOT_ROLE'`)
+* `ALICLOUD_RAM_ROLE` (value: `'ALICLOUD_RAM_ROLE'`)
+
+* `ALICLOUD_ECS_INSTANCE` (value: `'ALICLOUD_ECS_INSTANCE'`)
+
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
diff --git a/docs/RunOpalQueryRequest.md b/docs/RunOpalQueryRequest.md
new file mode 100644
index 0000000..348f3d4
--- /dev/null
+++ b/docs/RunOpalQueryRequest.md
@@ -0,0 +1,34 @@
+# RunOpalQueryRequest
+
+Request body for running an ad-hoc OpalQuery. The `type` field determines which query schema applies.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**type** | **str** | |
+**query** | [**OpalAccessPathQueryBody**](OpalAccessPathQueryBody.md) | | [optional]
+**first** | **int** | Maximum number of results to return. Defaults to 200. | [optional]
+**after** | **str** | Opaque cursor from a previous ACCESS_PATH response to fetch the next page of results. | [optional]
+**include_count** | **bool** | When true, populate totalCount in the response. Defaults to false. | [optional]
+
+## Example
+
+```python
+from opal_security.models.run_opal_query_request import RunOpalQueryRequest
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of RunOpalQueryRequest from a JSON string
+run_opal_query_request_instance = RunOpalQueryRequest.from_json(json)
+# print the JSON string representation of the object
+print(RunOpalQueryRequest.to_json())
+
+# convert the object into a dict
+run_opal_query_request_dict = run_opal_query_request_instance.to_dict()
+# create an instance of RunOpalQueryRequest from a dict
+run_opal_query_request_from_dict = RunOpalQueryRequest.from_dict(run_opal_query_request_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/StopCampaignRequest.md b/docs/StopCampaignRequest.md
new file mode 100644
index 0000000..da1e878
--- /dev/null
+++ b/docs/StopCampaignRequest.md
@@ -0,0 +1,29 @@
+# StopCampaignRequest
+
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**revoke_unreviewed** | **bool** | Revoke all unreviewed access grants. Access grants with no reviewer decision will be immediately revoked. | [optional] [default to False]
+
+## Example
+
+```python
+from opal_security.models.stop_campaign_request import StopCampaignRequest
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of StopCampaignRequest from a JSON string
+stop_campaign_request_instance = StopCampaignRequest.from_json(json)
+# print the JSON string representation of the object
+print(StopCampaignRequest.to_json())
+
+# convert the object into a dict
+stop_campaign_request_dict = stop_campaign_request_instance.to_dict()
+# create an instance of StopCampaignRequest from a dict
+stop_campaign_request_from_dict = StopCampaignRequest.from_dict(stop_campaign_request_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/UarsApi.md b/docs/UarsApi.md
index 24d66dd..a14213f 100644
--- a/docs/UarsApi.md
+++ b/docs/UarsApi.md
@@ -12,7 +12,7 @@ Method | HTTP request | Description
# **create_uar**
> UAR create_uar(create_uar_info)
-Starts a User Access Review.
+Starts a User Access Review. Deprecated in favor of `POST /campaigns`.
### Example
@@ -90,7 +90,7 @@ Name | Type | Description | Notes
# **get_uar**
> UAR get_uar(uar_id)
-Retrieves a specific UAR.
+Retrieves a specific UAR. Deprecated in favor of `GET /campaigns/{campaign_id}`.
### Example
@@ -167,7 +167,7 @@ Name | Type | Description | Notes
# **get_uars**
> PaginatedUARsList get_uars(cursor=cursor, page_size=page_size)
-Returns a list of `UAR` objects.
+Returns a list of `UAR` objects. Deprecated in favor of `GET /campaigns`.
### Example
diff --git a/docs/UpdateCampaignConfigurationInfo.md b/docs/UpdateCampaignConfigurationInfo.md
new file mode 100644
index 0000000..b38d08d
--- /dev/null
+++ b/docs/UpdateCampaignConfigurationInfo.md
@@ -0,0 +1,44 @@
+# UpdateCampaignConfigurationInfo
+
+Configuration fields to update on a campaign. All fields are optional; omitted fields are left unchanged. `query` and `reviewer_assignment_policy` are set at create time and cannot be updated here; including either field returns 400. `cron_expression` and `recurring_duration_days` may only be set when the campaign is a template; setting them on a one-off campaign returns 400. `is_template` is immutable and not accepted on update.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**allow_self_review** | **bool** | Whether reviewers can review their own access. | [optional]
+**send_reviewer_assignment_notification** | **bool** | Whether to notify reviewers upon assignment. | [optional]
+**allow_reviewer_reassignment** | **bool** | Whether reviewers may reassign their reviews to another user. | [optional]
+**start_date** | **datetime** | Scheduled start date of the campaign. May only be updated while the campaign has not started (started_at is null). When set, the date's calendar day in the campaign timezone must be at least tomorrow. | [optional]
+**end_date** | **datetime** | Scheduled end date of the campaign. When set, the date's calendar day in the campaign timezone must be at least tomorrow. | [optional]
+**timezone** | **str** | IANA timezone used to interpret campaign deadlines (e.g. America/Los_Angeles). | [optional]
+**revoke_on** | [**CampaignRevokeOnEnum**](CampaignRevokeOnEnum.md) | | [optional]
+**reminder_schedule** | **List[int]** | Days before end date to send reminder notifications. | [optional]
+**reminder_include_manager** | **bool** | Whether to include the reviewer's manager in reminders. | [optional]
+**require_reason_on_denial** | **bool** | Whether reviewers must provide a reason when denying (revoking) access. | [optional]
+**hide_ai_suggestions** | **bool** | Whether AI suggestions are hidden from reviewers. | [optional]
+**custom_start_message** | **str** | Optional custom message included when notifying reviewers that the campaign started. | [optional]
+**group_asset_visibility_policy** | [**CampaignGroupAssetVisibilityPolicyEnum**](CampaignGroupAssetVisibilityPolicyEnum.md) | | [optional]
+**cron_expression** | **str** | Cron expression driving the recurring schedule. Only valid on template campaigns. Pass an empty string to clear the active months (next_scheduled_run is cleared); the campaign remains a template. | [optional]
+**recurring_duration_days** | **int** | Deadline window in days applied to each draft generated from this template. Only valid on template campaigns. | [optional]
+
+## Example
+
+```python
+from opal_security.models.update_campaign_configuration_info import UpdateCampaignConfigurationInfo
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of UpdateCampaignConfigurationInfo from a JSON string
+update_campaign_configuration_info_instance = UpdateCampaignConfigurationInfo.from_json(json)
+# print the JSON string representation of the object
+print(UpdateCampaignConfigurationInfo.to_json())
+
+# convert the object into a dict
+update_campaign_configuration_info_dict = update_campaign_configuration_info_instance.to_dict()
+# create an instance of UpdateCampaignConfigurationInfo from a dict
+update_campaign_configuration_info_from_dict = UpdateCampaignConfigurationInfo.from_dict(update_campaign_configuration_info_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/UpdateCampaignInfo.md b/docs/UpdateCampaignInfo.md
new file mode 100644
index 0000000..6870a0e
--- /dev/null
+++ b/docs/UpdateCampaignInfo.md
@@ -0,0 +1,31 @@
+# UpdateCampaignInfo
+
+# UpdateCampaignInfo Object ### Description The `UpdateCampaignInfo` object is used to partially update a campaign. Omitted fields are left unchanged. ### Usage Example Use in the `PUT Campaign` endpoint.
+
+## Properties
+
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**name** | **str** | The name of the campaign. | [optional]
+**configuration** | [**UpdateCampaignConfigurationInfo**](UpdateCampaignConfigurationInfo.md) | Configuration fields to create or update. | [optional]
+
+## Example
+
+```python
+from opal_security.models.update_campaign_info import UpdateCampaignInfo
+
+# TODO update the JSON string below
+json = "{}"
+# create an instance of UpdateCampaignInfo from a JSON string
+update_campaign_info_instance = UpdateCampaignInfo.from_json(json)
+# print the JSON string representation of the object
+print(UpdateCampaignInfo.to_json())
+
+# convert the object into a dict
+update_campaign_info_dict = update_campaign_info_instance.to_dict()
+# create an instance of UpdateCampaignInfo from a dict
+update_campaign_info_from_dict = UpdateCampaignInfo.from_dict(update_campaign_info_dict)
+```
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/docs/UpdateGroupInfo.md b/docs/UpdateGroupInfo.md
index 489f5e1..da77dad 100644
--- a/docs/UpdateGroupInfo.md
+++ b/docs/UpdateGroupInfo.md
@@ -27,6 +27,8 @@ Name | Type | Description | Notes
**request_configuration_list** | [**CreateRequestConfigurationInfoList**](CreateRequestConfigurationInfoList.md) | The request configuration list of the configuration template. If not provided, the default request configuration will be used. Deprecated in favor of `request_configurations`. | [optional]
**custom_request_notification** | **str** | Custom request notification sent to the requester when the request is approved. | [optional]
**risk_sensitivity_override** | [**RiskSensitivityEnum**](RiskSensitivityEnum.md) | | [optional]
+**match_remote_name** | **bool** | A bool representing whether or not the group's name should be synced from the end system. When true, the name is overwritten with the remote name on each sync, so a `name` provided together with this field set to true will be replaced at the next sync. If not provided, the current value is left unchanged. | [optional]
+**match_remote_description** | **bool** | A bool representing whether or not the group's description should be synced from the end system. When true, the description is overwritten with the remote description on each sync, so a `description` provided together with this field set to true will be replaced at the next sync. If not provided, the current value is left unchanged. | [optional]
## Example
diff --git a/docs/UpdateResourceInfo.md b/docs/UpdateResourceInfo.md
index 29865dd..07513a9 100644
--- a/docs/UpdateResourceInfo.md
+++ b/docs/UpdateResourceInfo.md
@@ -22,6 +22,8 @@ Name | Type | Description | Notes
**ticket_propagation** | [**TicketPropagationConfiguration**](TicketPropagationConfiguration.md) | | [optional]
**custom_request_notification** | **str** | Custom request notification sent upon request approval. | [optional]
**risk_sensitivity_override** | [**RiskSensitivityEnum**](RiskSensitivityEnum.md) | | [optional]
+**match_remote_name** | **bool** | A bool representing whether or not the resource's name should be synced from the end system. When true, the name is overwritten with the remote name on each sync, so a `name` provided together with this field set to true will be replaced at the next sync. If not provided, the current value is left unchanged. | [optional]
+**match_remote_description** | **bool** | A bool representing whether or not the resource's description should be synced from the end system. When true, the description is overwritten with the remote description on each sync, so a `description` provided together with this field set to true will be replaced at the next sync. If not provided, the current value is left unchanged. | [optional]
**configuration_template_id** | **UUID** | The ID of the associated configuration template. | [optional]
**request_template_id** | **UUID** | The ID of the associated request template. Deprecated in favor of `request_configurations`. | [optional]
**is_requestable** | **bool** | A bool representing whether or not to allow access requests to this resource. Deprecated in favor of `request_configurations`. | [optional]
diff --git a/docs/UsersApi.md b/docs/UsersApi.md
index 262d8ec..c443f06 100644
--- a/docs/UsersApi.md
+++ b/docs/UsersApi.md
@@ -6,6 +6,7 @@ Method | HTTP request | Description
------------- | ------------- | -------------
[**get_remote_users**](UsersApi.md#get_remote_users) | **GET** /users/remote_users |
[**get_user_tags**](UsersApi.md#get_user_tags) | **GET** /users/{user_id}/tags |
+[**get_user_whoami**](UsersApi.md#get_user_whoami) | **GET** /users/whoami |
[**get_users**](UsersApi.md#get_users) | **GET** /users |
[**user**](UsersApi.md#user) | **GET** /user |
@@ -173,6 +174,79 @@ Name | Type | Description | Notes
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+# **get_user_whoami**
+> User get_user_whoami()
+
+Returns the user that the provided API token authenticates as.
+
+### Example
+
+* Bearer Authentication (BearerAuth):
+
+```python
+import opal_security
+from opal_security.models.user import User
+from opal_security.rest import ApiException
+from pprint import pprint
+
+# Defining the host is optional and defaults to https://api.opal.dev/v1
+# See configuration.py for a list of all supported configuration parameters.
+import opal_security as opal
+
+configuration = opal.Configuration(
+ host = "https://api.opal.dev/v1"
+)
+
+# The client must configure the authentication and authorization parameters
+# in accordance with the API server security policy.
+# Examples for each auth method are provided below, use the example that
+# satisfies your auth use case.
+
+# Configure Bearer authorization: BearerAuth
+configuration = opal.Configuration(
+ access_token = os.environ["BEARER_TOKEN"]
+)
+
+# Enter a context with an instance of the API client
+with opal_security.ApiClient(configuration) as api_client:
+ # Create an instance of the API class
+ api_instance = opal_security.UsersApi(api_client)
+
+ try:
+ api_response = api_instance.get_user_whoami()
+ print("The response of UsersApi->get_user_whoami:\n")
+ pprint(api_response)
+ except Exception as e:
+ print("Exception when calling UsersApi->get_user_whoami: %s\n" % e)
+```
+
+
+
+### Parameters
+
+This endpoint does not need any parameter.
+
+### Return type
+
+[**User**](User.md)
+
+### Authorization
+
+[BearerAuth](../README.md#BearerAuth)
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
+### HTTP response details
+
+| Status code | Description | Response headers |
+|-------------|-------------|------------------|
+**200** | The user that the API token authenticates as. | - |
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
# **get_users**
> PaginatedUsersList get_users(cursor=cursor, page_size=page_size, tag_ids=tag_ids)
diff --git a/opal_security/__init__.py b/opal_security/__init__.py
index bfd68aa..5023134 100644
--- a/opal_security/__init__.py
+++ b/opal_security/__init__.py
@@ -22,6 +22,7 @@
"AccessRulesApi",
"AppsApi",
"BundlesApi",
+ "CampaignsApi",
"ConfigurationTemplatesApi",
"DelegationsApi",
"EventStreamsApi",
@@ -34,6 +35,7 @@
"OnCallSchedulesApi",
"OpalQueriesApi",
"OwnersApi",
+ "PaladinApi",
"RequestsApi",
"ResourcesApi",
"SessionsApi",
@@ -75,9 +77,16 @@
"Bundle",
"BundleGroup",
"BundleResource",
+ "Campaign",
+ "CampaignConfiguration",
+ "CampaignGroupAssetVisibilityPolicyEnum",
+ "CampaignRevokeOnEnum",
+ "CampaignStatusEnum",
"Condition",
"ConfigurationTemplate",
"CreateBundleInfo",
+ "CreateCampaignConfigurationInfo",
+ "CreateCampaignInfo",
"CreateConfigurationTemplateInfo",
"CreateDelegationRequest",
"CreateEventStreamInfo",
@@ -101,6 +110,7 @@
"CreateUARInfo",
"Delegation",
"DenyRequestRequest",
+ "EntityAdminFilter",
"EntityItemTypeEnum",
"EntityNameFilter",
"EntityTagFilter",
@@ -141,6 +151,7 @@
"GroupRemoteInfoRootlyOnCallSchedule",
"GroupRemoteInfoSlackUserGroup",
"GroupRemoteInfoSnowflakeRole",
+ "GroupRemoteInfoTableauGroup",
"GroupRemoteInfoTailscaleGroup",
"GroupRemoteInfoTwingateGroup",
"GroupRemoteInfoTwingateGroupSynced",
@@ -155,6 +166,7 @@
"GroupWithAccessLevel",
"IdpGroupMapping",
"IdpGroupMappingList",
+ "IdpStatusFilter",
"MessageChannel",
"MessageChannelIDList",
"MessageChannelList",
@@ -163,11 +175,18 @@
"OnCallScheduleIDList",
"OnCallScheduleList",
"OnCallScheduleProviderEnum",
+ "OpalAccessPathEdgeFilter",
+ "OpalAccessPathQuery",
+ "OpalAccessPathQueryBody",
+ "OpalAccessPathQueryResults",
+ "OpalAccessPathResultEdge",
+ "OpalAccessPathResultNode",
"OpalNodeQuery",
"OpalNodeQueryBody",
"OpalNodeQueryResults",
"OpalQueryResultEdge",
"OpalQueryResultNode",
+ "OpalQueryResults",
"Owner",
"PageInfo",
"PaginatedAccessRulesList",
@@ -175,6 +194,7 @@
"PaginatedBundleGroupList",
"PaginatedBundleList",
"PaginatedBundleResourceList",
+ "PaginatedCampaignsList",
"PaginatedConfigurationTemplateList",
"PaginatedDelegationsList",
"PaginatedEventList",
@@ -187,6 +207,8 @@
"PaginatedTokensList",
"PaginatedUARsList",
"PaginatedUsersList",
+ "Paladin",
+ "PaladinList",
"PropagationStatus",
"PropagationStatusEnum",
"RDSEngineEnum",
@@ -214,6 +236,8 @@
"ResourceAccessUserList",
"ResourceNHI",
"ResourceRemoteInfo",
+ "ResourceRemoteInfoAlicloudEcsInstance",
+ "ResourceRemoteInfoAlicloudRamRole",
"ResourceRemoteInfoAnthropicWorkspace",
"ResourceRemoteInfoAwsAccount",
"ResourceRemoteInfoAwsEc2Instance",
@@ -301,10 +325,12 @@
"RuleClauses",
"RuleConjunction",
"RuleDisjunction",
+ "RunOpalQueryRequest",
"ScopedRolePermission",
"ScopedRolePermissionList",
"Session",
"SessionsList",
+ "StopCampaignRequest",
"StringMatchType",
"SubEvent",
"SyncError",
@@ -322,6 +348,8 @@
"UARReviewerAssignmentPolicyEnum",
"UARScope",
"UpdateAccessRuleInfo",
+ "UpdateCampaignConfigurationInfo",
+ "UpdateCampaignInfo",
"UpdateConfigurationTemplateInfo",
"UpdateEventStreamInfo",
"UpdateGroupBindingInfo",
@@ -355,6 +383,7 @@
from opal_security.api.access_rules_api import AccessRulesApi as AccessRulesApi
from opal_security.api.apps_api import AppsApi as AppsApi
from opal_security.api.bundles_api import BundlesApi as BundlesApi
+from opal_security.api.campaigns_api import CampaignsApi as CampaignsApi
from opal_security.api.configuration_templates_api import ConfigurationTemplatesApi as ConfigurationTemplatesApi
from opal_security.api.delegations_api import DelegationsApi as DelegationsApi
from opal_security.api.event_streams_api import EventStreamsApi as EventStreamsApi
@@ -367,6 +396,7 @@
from opal_security.api.on_call_schedules_api import OnCallSchedulesApi as OnCallSchedulesApi
from opal_security.api.opal_queries_api import OpalQueriesApi as OpalQueriesApi
from opal_security.api.owners_api import OwnersApi as OwnersApi
+from opal_security.api.paladin_api import PaladinApi as PaladinApi
from opal_security.api.requests_api import RequestsApi as RequestsApi
from opal_security.api.resources_api import ResourcesApi as ResourcesApi
from opal_security.api.sessions_api import SessionsApi as SessionsApi
@@ -412,9 +442,16 @@
from opal_security.models.bundle import Bundle as Bundle
from opal_security.models.bundle_group import BundleGroup as BundleGroup
from opal_security.models.bundle_resource import BundleResource as BundleResource
+from opal_security.models.campaign import Campaign as Campaign
+from opal_security.models.campaign_configuration import CampaignConfiguration as CampaignConfiguration
+from opal_security.models.campaign_group_asset_visibility_policy_enum import CampaignGroupAssetVisibilityPolicyEnum as CampaignGroupAssetVisibilityPolicyEnum
+from opal_security.models.campaign_revoke_on_enum import CampaignRevokeOnEnum as CampaignRevokeOnEnum
+from opal_security.models.campaign_status_enum import CampaignStatusEnum as CampaignStatusEnum
from opal_security.models.condition import Condition as Condition
from opal_security.models.configuration_template import ConfigurationTemplate as ConfigurationTemplate
from opal_security.models.create_bundle_info import CreateBundleInfo as CreateBundleInfo
+from opal_security.models.create_campaign_configuration_info import CreateCampaignConfigurationInfo as CreateCampaignConfigurationInfo
+from opal_security.models.create_campaign_info import CreateCampaignInfo as CreateCampaignInfo
from opal_security.models.create_configuration_template_info import CreateConfigurationTemplateInfo as CreateConfigurationTemplateInfo
from opal_security.models.create_delegation_request import CreateDelegationRequest as CreateDelegationRequest
from opal_security.models.create_event_stream_info import CreateEventStreamInfo as CreateEventStreamInfo
@@ -438,6 +475,7 @@
from opal_security.models.create_uar_info import CreateUARInfo as CreateUARInfo
from opal_security.models.delegation import Delegation as Delegation
from opal_security.models.deny_request_request import DenyRequestRequest as DenyRequestRequest
+from opal_security.models.entity_admin_filter import EntityAdminFilter as EntityAdminFilter
from opal_security.models.entity_item_type_enum import EntityItemTypeEnum as EntityItemTypeEnum
from opal_security.models.entity_name_filter import EntityNameFilter as EntityNameFilter
from opal_security.models.entity_tag_filter import EntityTagFilter as EntityTagFilter
@@ -478,6 +516,7 @@
from opal_security.models.group_remote_info_rootly_on_call_schedule import GroupRemoteInfoRootlyOnCallSchedule as GroupRemoteInfoRootlyOnCallSchedule
from opal_security.models.group_remote_info_slack_user_group import GroupRemoteInfoSlackUserGroup as GroupRemoteInfoSlackUserGroup
from opal_security.models.group_remote_info_snowflake_role import GroupRemoteInfoSnowflakeRole as GroupRemoteInfoSnowflakeRole
+from opal_security.models.group_remote_info_tableau_group import GroupRemoteInfoTableauGroup as GroupRemoteInfoTableauGroup
from opal_security.models.group_remote_info_tailscale_group import GroupRemoteInfoTailscaleGroup as GroupRemoteInfoTailscaleGroup
from opal_security.models.group_remote_info_twingate_group import GroupRemoteInfoTwingateGroup as GroupRemoteInfoTwingateGroup
from opal_security.models.group_remote_info_twingate_group_synced import GroupRemoteInfoTwingateGroupSynced as GroupRemoteInfoTwingateGroupSynced
@@ -492,6 +531,7 @@
from opal_security.models.group_with_access_level import GroupWithAccessLevel as GroupWithAccessLevel
from opal_security.models.idp_group_mapping import IdpGroupMapping as IdpGroupMapping
from opal_security.models.idp_group_mapping_list import IdpGroupMappingList as IdpGroupMappingList
+from opal_security.models.idp_status_filter import IdpStatusFilter as IdpStatusFilter
from opal_security.models.message_channel import MessageChannel as MessageChannel
from opal_security.models.message_channel_id_list import MessageChannelIDList as MessageChannelIDList
from opal_security.models.message_channel_list import MessageChannelList as MessageChannelList
@@ -500,11 +540,18 @@
from opal_security.models.on_call_schedule_id_list import OnCallScheduleIDList as OnCallScheduleIDList
from opal_security.models.on_call_schedule_list import OnCallScheduleList as OnCallScheduleList
from opal_security.models.on_call_schedule_provider_enum import OnCallScheduleProviderEnum as OnCallScheduleProviderEnum
+from opal_security.models.opal_access_path_edge_filter import OpalAccessPathEdgeFilter as OpalAccessPathEdgeFilter
+from opal_security.models.opal_access_path_query import OpalAccessPathQuery as OpalAccessPathQuery
+from opal_security.models.opal_access_path_query_body import OpalAccessPathQueryBody as OpalAccessPathQueryBody
+from opal_security.models.opal_access_path_query_results import OpalAccessPathQueryResults as OpalAccessPathQueryResults
+from opal_security.models.opal_access_path_result_edge import OpalAccessPathResultEdge as OpalAccessPathResultEdge
+from opal_security.models.opal_access_path_result_node import OpalAccessPathResultNode as OpalAccessPathResultNode
from opal_security.models.opal_node_query import OpalNodeQuery as OpalNodeQuery
from opal_security.models.opal_node_query_body import OpalNodeQueryBody as OpalNodeQueryBody
from opal_security.models.opal_node_query_results import OpalNodeQueryResults as OpalNodeQueryResults
from opal_security.models.opal_query_result_edge import OpalQueryResultEdge as OpalQueryResultEdge
from opal_security.models.opal_query_result_node import OpalQueryResultNode as OpalQueryResultNode
+from opal_security.models.opal_query_results import OpalQueryResults as OpalQueryResults
from opal_security.models.owner import Owner as Owner
from opal_security.models.page_info import PageInfo as PageInfo
from opal_security.models.paginated_access_rules_list import PaginatedAccessRulesList as PaginatedAccessRulesList
@@ -512,6 +559,7 @@
from opal_security.models.paginated_bundle_group_list import PaginatedBundleGroupList as PaginatedBundleGroupList
from opal_security.models.paginated_bundle_list import PaginatedBundleList as PaginatedBundleList
from opal_security.models.paginated_bundle_resource_list import PaginatedBundleResourceList as PaginatedBundleResourceList
+from opal_security.models.paginated_campaigns_list import PaginatedCampaignsList as PaginatedCampaignsList
from opal_security.models.paginated_configuration_template_list import PaginatedConfigurationTemplateList as PaginatedConfigurationTemplateList
from opal_security.models.paginated_delegations_list import PaginatedDelegationsList as PaginatedDelegationsList
from opal_security.models.paginated_event_list import PaginatedEventList as PaginatedEventList
@@ -524,6 +572,8 @@
from opal_security.models.paginated_tokens_list import PaginatedTokensList as PaginatedTokensList
from opal_security.models.paginated_uars_list import PaginatedUARsList as PaginatedUARsList
from opal_security.models.paginated_users_list import PaginatedUsersList as PaginatedUsersList
+from opal_security.models.paladin import Paladin as Paladin
+from opal_security.models.paladin_list import PaladinList as PaladinList
from opal_security.models.propagation_status import PropagationStatus as PropagationStatus
from opal_security.models.propagation_status_enum import PropagationStatusEnum as PropagationStatusEnum
from opal_security.models.rds_engine_enum import RDSEngineEnum as RDSEngineEnum
@@ -551,6 +601,8 @@
from opal_security.models.resource_access_user_list import ResourceAccessUserList as ResourceAccessUserList
from opal_security.models.resource_nhi import ResourceNHI as ResourceNHI
from opal_security.models.resource_remote_info import ResourceRemoteInfo as ResourceRemoteInfo
+from opal_security.models.resource_remote_info_alicloud_ecs_instance import ResourceRemoteInfoAlicloudEcsInstance as ResourceRemoteInfoAlicloudEcsInstance
+from opal_security.models.resource_remote_info_alicloud_ram_role import ResourceRemoteInfoAlicloudRamRole as ResourceRemoteInfoAlicloudRamRole
from opal_security.models.resource_remote_info_anthropic_workspace import ResourceRemoteInfoAnthropicWorkspace as ResourceRemoteInfoAnthropicWorkspace
from opal_security.models.resource_remote_info_aws_account import ResourceRemoteInfoAwsAccount as ResourceRemoteInfoAwsAccount
from opal_security.models.resource_remote_info_aws_ec2_instance import ResourceRemoteInfoAwsEc2Instance as ResourceRemoteInfoAwsEc2Instance
@@ -638,10 +690,12 @@
from opal_security.models.rule_clauses import RuleClauses as RuleClauses
from opal_security.models.rule_conjunction import RuleConjunction as RuleConjunction
from opal_security.models.rule_disjunction import RuleDisjunction as RuleDisjunction
+from opal_security.models.run_opal_query_request import RunOpalQueryRequest as RunOpalQueryRequest
from opal_security.models.scoped_role_permission import ScopedRolePermission as ScopedRolePermission
from opal_security.models.scoped_role_permission_list import ScopedRolePermissionList as ScopedRolePermissionList
from opal_security.models.session import Session as Session
from opal_security.models.sessions_list import SessionsList as SessionsList
+from opal_security.models.stop_campaign_request import StopCampaignRequest as StopCampaignRequest
from opal_security.models.string_match_type import StringMatchType as StringMatchType
from opal_security.models.sub_event import SubEvent as SubEvent
from opal_security.models.sync_error import SyncError as SyncError
@@ -659,6 +713,8 @@
from opal_security.models.uar_reviewer_assignment_policy_enum import UARReviewerAssignmentPolicyEnum as UARReviewerAssignmentPolicyEnum
from opal_security.models.uar_scope import UARScope as UARScope
from opal_security.models.update_access_rule_info import UpdateAccessRuleInfo as UpdateAccessRuleInfo
+from opal_security.models.update_campaign_configuration_info import UpdateCampaignConfigurationInfo as UpdateCampaignConfigurationInfo
+from opal_security.models.update_campaign_info import UpdateCampaignInfo as UpdateCampaignInfo
from opal_security.models.update_configuration_template_info import UpdateConfigurationTemplateInfo as UpdateConfigurationTemplateInfo
from opal_security.models.update_event_stream_info import UpdateEventStreamInfo as UpdateEventStreamInfo
from opal_security.models.update_group_binding_info import UpdateGroupBindingInfo as UpdateGroupBindingInfo
diff --git a/opal_security/api/__init__.py b/opal_security/api/__init__.py
index 27c0e8e..3a51ce9 100644
--- a/opal_security/api/__init__.py
+++ b/opal_security/api/__init__.py
@@ -4,6 +4,7 @@
from opal_security.api.access_rules_api import AccessRulesApi
from opal_security.api.apps_api import AppsApi
from opal_security.api.bundles_api import BundlesApi
+from opal_security.api.campaigns_api import CampaignsApi
from opal_security.api.configuration_templates_api import ConfigurationTemplatesApi
from opal_security.api.delegations_api import DelegationsApi
from opal_security.api.event_streams_api import EventStreamsApi
@@ -16,6 +17,7 @@
from opal_security.api.on_call_schedules_api import OnCallSchedulesApi
from opal_security.api.opal_queries_api import OpalQueriesApi
from opal_security.api.owners_api import OwnersApi
+from opal_security.api.paladin_api import PaladinApi
from opal_security.api.requests_api import RequestsApi
from opal_security.api.resources_api import ResourcesApi
from opal_security.api.sessions_api import SessionsApi
diff --git a/opal_security/api/campaigns_api.py b/opal_security/api/campaigns_api.py
new file mode 100644
index 0000000..f857390
--- /dev/null
+++ b/opal_security/api/campaigns_api.py
@@ -0,0 +1,2204 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+import warnings
+from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt
+from typing import Any, Dict, List, Optional, Tuple, Union
+from typing_extensions import Annotated
+
+from datetime import datetime
+from pydantic import Field, StrictStr
+from typing import Optional
+from typing_extensions import Annotated
+from uuid import UUID
+from opal_security.models.campaign import Campaign
+from opal_security.models.campaign_status_enum import CampaignStatusEnum
+from opal_security.models.create_campaign_info import CreateCampaignInfo
+from opal_security.models.paginated_campaigns_list import PaginatedCampaignsList
+from opal_security.models.stop_campaign_request import StopCampaignRequest
+from opal_security.models.update_campaign_info import UpdateCampaignInfo
+
+from opal_security.api_client import ApiClient, RequestSerialized
+from opal_security.api_response import ApiResponse
+from opal_security.rest import RESTResponseType
+
+
+class CampaignsApi:
+ """NOTE: This class is auto generated by OpenAPI Generator
+ Ref: https://openapi-generator.tech
+
+ Do not edit the class manually.
+ """
+
+ def __init__(self, api_client=None) -> None:
+ if api_client is None:
+ api_client = ApiClient.get_default()
+ self.api_client = api_client
+
+
+ @validate_call
+ def create_campaign(
+ self,
+ create_campaign_info: CreateCampaignInfo,
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> Campaign:
+ """create_campaign
+
+ Creates a campaign. Campaign scope only supports direct access edges: `configuration.query.edgeFilter.directOnly` defaults to `true`, is always stored as `true`, and passing `false` returns 400.
+
+ :param create_campaign_info: (required)
+ :type create_campaign_info: CreateCampaignInfo
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._create_campaign_serialize(
+ create_campaign_info=create_campaign_info,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '201': "Campaign",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ ).data
+
+
+ @validate_call
+ def create_campaign_with_http_info(
+ self,
+ create_campaign_info: CreateCampaignInfo,
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> ApiResponse[Campaign]:
+ """create_campaign
+
+ Creates a campaign. Campaign scope only supports direct access edges: `configuration.query.edgeFilter.directOnly` defaults to `true`, is always stored as `true`, and passing `false` returns 400.
+
+ :param create_campaign_info: (required)
+ :type create_campaign_info: CreateCampaignInfo
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._create_campaign_serialize(
+ create_campaign_info=create_campaign_info,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '201': "Campaign",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ )
+
+
+ @validate_call
+ def create_campaign_without_preload_content(
+ self,
+ create_campaign_info: CreateCampaignInfo,
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> RESTResponseType:
+ """create_campaign
+
+ Creates a campaign. Campaign scope only supports direct access edges: `configuration.query.edgeFilter.directOnly` defaults to `true`, is always stored as `true`, and passing `false` returns 400.
+
+ :param create_campaign_info: (required)
+ :type create_campaign_info: CreateCampaignInfo
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._create_campaign_serialize(
+ create_campaign_info=create_campaign_info,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '201': "Campaign",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ return response_data.response
+
+
+ def _create_campaign_serialize(
+ self,
+ create_campaign_info,
+ _request_auth,
+ _content_type,
+ _headers,
+ _host_index,
+ ) -> RequestSerialized:
+
+ _host = None
+
+ _collection_formats: Dict[str, str] = {
+ }
+
+ _path_params: Dict[str, str] = {}
+ _query_params: List[Tuple[str, str]] = []
+ _header_params: Dict[str, Optional[str]] = _headers or {}
+ _form_params: List[Tuple[str, str]] = []
+ _files: Dict[
+ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+ ] = {}
+ _body_params: Optional[bytes] = None
+
+ # process the path parameters
+ # process the query parameters
+ # process the header parameters
+ # process the form parameters
+ # process the body parameter
+ if create_campaign_info is not None:
+ _body_params = create_campaign_info
+
+
+ # set the HTTP header `Accept`
+ if 'Accept' not in _header_params:
+ _header_params['Accept'] = self.api_client.select_header_accept(
+ [
+ 'application/json'
+ ]
+ )
+
+ # set the HTTP header `Content-Type`
+ if _content_type:
+ _header_params['Content-Type'] = _content_type
+ else:
+ _default_content_type = (
+ self.api_client.select_header_content_type(
+ [
+ 'application/json'
+ ]
+ )
+ )
+ if _default_content_type is not None:
+ _header_params['Content-Type'] = _default_content_type
+
+ # authentication setting
+ _auth_settings: List[str] = [
+ 'BearerAuth'
+ ]
+
+ return self.api_client.param_serialize(
+ method='POST',
+ resource_path='/campaigns',
+ path_params=_path_params,
+ query_params=_query_params,
+ header_params=_header_params,
+ body=_body_params,
+ post_params=_form_params,
+ files=_files,
+ auth_settings=_auth_settings,
+ collection_formats=_collection_formats,
+ _host=_host,
+ _request_auth=_request_auth
+ )
+
+
+
+
+ @validate_call
+ def end_campaign(
+ self,
+ campaign_id: Annotated[UUID, Field(description="The ID of the campaign.")],
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> Campaign:
+ """End campaign
+
+ Ends a stopped campaign, setting `ended_at` and `ended_by_user_id`, applying pending access changes, and queuing report generation. Returns 400 unless the campaign is started and stopped and not already ended.
+
+ :param campaign_id: The ID of the campaign. (required)
+ :type campaign_id: UUID
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._end_campaign_serialize(
+ campaign_id=campaign_id,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "Campaign",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ ).data
+
+
+ @validate_call
+ def end_campaign_with_http_info(
+ self,
+ campaign_id: Annotated[UUID, Field(description="The ID of the campaign.")],
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> ApiResponse[Campaign]:
+ """End campaign
+
+ Ends a stopped campaign, setting `ended_at` and `ended_by_user_id`, applying pending access changes, and queuing report generation. Returns 400 unless the campaign is started and stopped and not already ended.
+
+ :param campaign_id: The ID of the campaign. (required)
+ :type campaign_id: UUID
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._end_campaign_serialize(
+ campaign_id=campaign_id,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "Campaign",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ )
+
+
+ @validate_call
+ def end_campaign_without_preload_content(
+ self,
+ campaign_id: Annotated[UUID, Field(description="The ID of the campaign.")],
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> RESTResponseType:
+ """End campaign
+
+ Ends a stopped campaign, setting `ended_at` and `ended_by_user_id`, applying pending access changes, and queuing report generation. Returns 400 unless the campaign is started and stopped and not already ended.
+
+ :param campaign_id: The ID of the campaign. (required)
+ :type campaign_id: UUID
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._end_campaign_serialize(
+ campaign_id=campaign_id,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "Campaign",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ return response_data.response
+
+
+ def _end_campaign_serialize(
+ self,
+ campaign_id,
+ _request_auth,
+ _content_type,
+ _headers,
+ _host_index,
+ ) -> RequestSerialized:
+
+ _host = None
+
+ _collection_formats: Dict[str, str] = {
+ }
+
+ _path_params: Dict[str, str] = {}
+ _query_params: List[Tuple[str, str]] = []
+ _header_params: Dict[str, Optional[str]] = _headers or {}
+ _form_params: List[Tuple[str, str]] = []
+ _files: Dict[
+ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+ ] = {}
+ _body_params: Optional[bytes] = None
+
+ # process the path parameters
+ if campaign_id is not None:
+ _path_params['campaign_id'] = campaign_id
+ # process the query parameters
+ # process the header parameters
+ # process the form parameters
+ # process the body parameter
+
+
+ # set the HTTP header `Accept`
+ if 'Accept' not in _header_params:
+ _header_params['Accept'] = self.api_client.select_header_accept(
+ [
+ 'application/json'
+ ]
+ )
+
+
+ # authentication setting
+ _auth_settings: List[str] = [
+ 'BearerAuth'
+ ]
+
+ return self.api_client.param_serialize(
+ method='POST',
+ resource_path='/campaigns/{campaign_id}/end',
+ path_params=_path_params,
+ query_params=_query_params,
+ header_params=_header_params,
+ body=_body_params,
+ post_params=_form_params,
+ files=_files,
+ auth_settings=_auth_settings,
+ collection_formats=_collection_formats,
+ _host=_host,
+ _request_auth=_request_auth
+ )
+
+
+
+
+ @validate_call
+ def get_campaign(
+ self,
+ campaign_id: Annotated[UUID, Field(description="The ID of the campaign.")],
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> Campaign:
+ """Get campaign by ID
+
+ Returns a `Campaign` object.
+
+ :param campaign_id: The ID of the campaign. (required)
+ :type campaign_id: UUID
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._get_campaign_serialize(
+ campaign_id=campaign_id,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "Campaign",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ ).data
+
+
+ @validate_call
+ def get_campaign_with_http_info(
+ self,
+ campaign_id: Annotated[UUID, Field(description="The ID of the campaign.")],
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> ApiResponse[Campaign]:
+ """Get campaign by ID
+
+ Returns a `Campaign` object.
+
+ :param campaign_id: The ID of the campaign. (required)
+ :type campaign_id: UUID
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._get_campaign_serialize(
+ campaign_id=campaign_id,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "Campaign",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ )
+
+
+ @validate_call
+ def get_campaign_without_preload_content(
+ self,
+ campaign_id: Annotated[UUID, Field(description="The ID of the campaign.")],
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> RESTResponseType:
+ """Get campaign by ID
+
+ Returns a `Campaign` object.
+
+ :param campaign_id: The ID of the campaign. (required)
+ :type campaign_id: UUID
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._get_campaign_serialize(
+ campaign_id=campaign_id,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "Campaign",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ return response_data.response
+
+
+ def _get_campaign_serialize(
+ self,
+ campaign_id,
+ _request_auth,
+ _content_type,
+ _headers,
+ _host_index,
+ ) -> RequestSerialized:
+
+ _host = None
+
+ _collection_formats: Dict[str, str] = {
+ }
+
+ _path_params: Dict[str, str] = {}
+ _query_params: List[Tuple[str, str]] = []
+ _header_params: Dict[str, Optional[str]] = _headers or {}
+ _form_params: List[Tuple[str, str]] = []
+ _files: Dict[
+ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+ ] = {}
+ _body_params: Optional[bytes] = None
+
+ # process the path parameters
+ if campaign_id is not None:
+ _path_params['campaign_id'] = campaign_id
+ # process the query parameters
+ # process the header parameters
+ # process the form parameters
+ # process the body parameter
+
+
+ # set the HTTP header `Accept`
+ if 'Accept' not in _header_params:
+ _header_params['Accept'] = self.api_client.select_header_accept(
+ [
+ 'application/json'
+ ]
+ )
+
+
+ # authentication setting
+ _auth_settings: List[str] = [
+ 'BearerAuth'
+ ]
+
+ return self.api_client.param_serialize(
+ method='GET',
+ resource_path='/campaigns/{campaign_id}',
+ path_params=_path_params,
+ query_params=_query_params,
+ header_params=_header_params,
+ body=_body_params,
+ post_params=_form_params,
+ files=_files,
+ auth_settings=_auth_settings,
+ collection_formats=_collection_formats,
+ _host=_host,
+ _request_auth=_request_auth
+ )
+
+
+
+
+ @validate_call
+ def get_campaigns(
+ self,
+ cursor: Annotated[Optional[StrictStr], Field(description="The pagination cursor value.")] = None,
+ page_size: Annotated[Optional[Annotated[int, Field(le=1000, strict=True)]], Field(description="Number of results to return per page. Default is 200.")] = None,
+ name: Annotated[Optional[StrictStr], Field(description="Campaign name to filter by. Returns campaigns whose names contain this substring (case-insensitive).")] = None,
+ status: Annotated[Optional[CampaignStatusEnum], Field(description="Filter by campaign status. Status is derived from lifecycle timestamps and review progress.")] = None,
+ created_at_after: Annotated[Optional[datetime], Field(description="Include campaigns created after this timestamp (exclusive). ISO 8601 format.")] = None,
+ created_at_before: Annotated[Optional[datetime], Field(description="Include campaigns created before this timestamp (exclusive). ISO 8601 format.")] = None,
+ started_at_after: Annotated[Optional[datetime], Field(description="Include campaigns started after this timestamp (exclusive). ISO 8601 format.")] = None,
+ started_at_before: Annotated[Optional[datetime], Field(description="Include campaigns started before this timestamp (exclusive). ISO 8601 format.")] = None,
+ ended_at_after: Annotated[Optional[datetime], Field(description="Include campaigns ended after this timestamp (exclusive). ISO 8601 format.")] = None,
+ ended_at_before: Annotated[Optional[datetime], Field(description="Include campaigns ended before this timestamp (exclusive). ISO 8601 format.")] = None,
+ stopped_at_after: Annotated[Optional[datetime], Field(description="Include campaigns stopped after this timestamp (exclusive). ISO 8601 format.")] = None,
+ stopped_at_before: Annotated[Optional[datetime], Field(description="Include campaigns stopped before this timestamp (exclusive). ISO 8601 format.")] = None,
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> PaginatedCampaignsList:
+ """get_campaigns
+
+ Returns a list of `Campaign` objects.
+
+ :param cursor: The pagination cursor value.
+ :type cursor: str
+ :param page_size: Number of results to return per page. Default is 200.
+ :type page_size: int
+ :param name: Campaign name to filter by. Returns campaigns whose names contain this substring (case-insensitive).
+ :type name: str
+ :param status: Filter by campaign status. Status is derived from lifecycle timestamps and review progress.
+ :type status: CampaignStatusEnum
+ :param created_at_after: Include campaigns created after this timestamp (exclusive). ISO 8601 format.
+ :type created_at_after: datetime
+ :param created_at_before: Include campaigns created before this timestamp (exclusive). ISO 8601 format.
+ :type created_at_before: datetime
+ :param started_at_after: Include campaigns started after this timestamp (exclusive). ISO 8601 format.
+ :type started_at_after: datetime
+ :param started_at_before: Include campaigns started before this timestamp (exclusive). ISO 8601 format.
+ :type started_at_before: datetime
+ :param ended_at_after: Include campaigns ended after this timestamp (exclusive). ISO 8601 format.
+ :type ended_at_after: datetime
+ :param ended_at_before: Include campaigns ended before this timestamp (exclusive). ISO 8601 format.
+ :type ended_at_before: datetime
+ :param stopped_at_after: Include campaigns stopped after this timestamp (exclusive). ISO 8601 format.
+ :type stopped_at_after: datetime
+ :param stopped_at_before: Include campaigns stopped before this timestamp (exclusive). ISO 8601 format.
+ :type stopped_at_before: datetime
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._get_campaigns_serialize(
+ cursor=cursor,
+ page_size=page_size,
+ name=name,
+ status=status,
+ created_at_after=created_at_after,
+ created_at_before=created_at_before,
+ started_at_after=started_at_after,
+ started_at_before=started_at_before,
+ ended_at_after=ended_at_after,
+ ended_at_before=ended_at_before,
+ stopped_at_after=stopped_at_after,
+ stopped_at_before=stopped_at_before,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "PaginatedCampaignsList",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ ).data
+
+
+ @validate_call
+ def get_campaigns_with_http_info(
+ self,
+ cursor: Annotated[Optional[StrictStr], Field(description="The pagination cursor value.")] = None,
+ page_size: Annotated[Optional[Annotated[int, Field(le=1000, strict=True)]], Field(description="Number of results to return per page. Default is 200.")] = None,
+ name: Annotated[Optional[StrictStr], Field(description="Campaign name to filter by. Returns campaigns whose names contain this substring (case-insensitive).")] = None,
+ status: Annotated[Optional[CampaignStatusEnum], Field(description="Filter by campaign status. Status is derived from lifecycle timestamps and review progress.")] = None,
+ created_at_after: Annotated[Optional[datetime], Field(description="Include campaigns created after this timestamp (exclusive). ISO 8601 format.")] = None,
+ created_at_before: Annotated[Optional[datetime], Field(description="Include campaigns created before this timestamp (exclusive). ISO 8601 format.")] = None,
+ started_at_after: Annotated[Optional[datetime], Field(description="Include campaigns started after this timestamp (exclusive). ISO 8601 format.")] = None,
+ started_at_before: Annotated[Optional[datetime], Field(description="Include campaigns started before this timestamp (exclusive). ISO 8601 format.")] = None,
+ ended_at_after: Annotated[Optional[datetime], Field(description="Include campaigns ended after this timestamp (exclusive). ISO 8601 format.")] = None,
+ ended_at_before: Annotated[Optional[datetime], Field(description="Include campaigns ended before this timestamp (exclusive). ISO 8601 format.")] = None,
+ stopped_at_after: Annotated[Optional[datetime], Field(description="Include campaigns stopped after this timestamp (exclusive). ISO 8601 format.")] = None,
+ stopped_at_before: Annotated[Optional[datetime], Field(description="Include campaigns stopped before this timestamp (exclusive). ISO 8601 format.")] = None,
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> ApiResponse[PaginatedCampaignsList]:
+ """get_campaigns
+
+ Returns a list of `Campaign` objects.
+
+ :param cursor: The pagination cursor value.
+ :type cursor: str
+ :param page_size: Number of results to return per page. Default is 200.
+ :type page_size: int
+ :param name: Campaign name to filter by. Returns campaigns whose names contain this substring (case-insensitive).
+ :type name: str
+ :param status: Filter by campaign status. Status is derived from lifecycle timestamps and review progress.
+ :type status: CampaignStatusEnum
+ :param created_at_after: Include campaigns created after this timestamp (exclusive). ISO 8601 format.
+ :type created_at_after: datetime
+ :param created_at_before: Include campaigns created before this timestamp (exclusive). ISO 8601 format.
+ :type created_at_before: datetime
+ :param started_at_after: Include campaigns started after this timestamp (exclusive). ISO 8601 format.
+ :type started_at_after: datetime
+ :param started_at_before: Include campaigns started before this timestamp (exclusive). ISO 8601 format.
+ :type started_at_before: datetime
+ :param ended_at_after: Include campaigns ended after this timestamp (exclusive). ISO 8601 format.
+ :type ended_at_after: datetime
+ :param ended_at_before: Include campaigns ended before this timestamp (exclusive). ISO 8601 format.
+ :type ended_at_before: datetime
+ :param stopped_at_after: Include campaigns stopped after this timestamp (exclusive). ISO 8601 format.
+ :type stopped_at_after: datetime
+ :param stopped_at_before: Include campaigns stopped before this timestamp (exclusive). ISO 8601 format.
+ :type stopped_at_before: datetime
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._get_campaigns_serialize(
+ cursor=cursor,
+ page_size=page_size,
+ name=name,
+ status=status,
+ created_at_after=created_at_after,
+ created_at_before=created_at_before,
+ started_at_after=started_at_after,
+ started_at_before=started_at_before,
+ ended_at_after=ended_at_after,
+ ended_at_before=ended_at_before,
+ stopped_at_after=stopped_at_after,
+ stopped_at_before=stopped_at_before,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "PaginatedCampaignsList",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ )
+
+
+ @validate_call
+ def get_campaigns_without_preload_content(
+ self,
+ cursor: Annotated[Optional[StrictStr], Field(description="The pagination cursor value.")] = None,
+ page_size: Annotated[Optional[Annotated[int, Field(le=1000, strict=True)]], Field(description="Number of results to return per page. Default is 200.")] = None,
+ name: Annotated[Optional[StrictStr], Field(description="Campaign name to filter by. Returns campaigns whose names contain this substring (case-insensitive).")] = None,
+ status: Annotated[Optional[CampaignStatusEnum], Field(description="Filter by campaign status. Status is derived from lifecycle timestamps and review progress.")] = None,
+ created_at_after: Annotated[Optional[datetime], Field(description="Include campaigns created after this timestamp (exclusive). ISO 8601 format.")] = None,
+ created_at_before: Annotated[Optional[datetime], Field(description="Include campaigns created before this timestamp (exclusive). ISO 8601 format.")] = None,
+ started_at_after: Annotated[Optional[datetime], Field(description="Include campaigns started after this timestamp (exclusive). ISO 8601 format.")] = None,
+ started_at_before: Annotated[Optional[datetime], Field(description="Include campaigns started before this timestamp (exclusive). ISO 8601 format.")] = None,
+ ended_at_after: Annotated[Optional[datetime], Field(description="Include campaigns ended after this timestamp (exclusive). ISO 8601 format.")] = None,
+ ended_at_before: Annotated[Optional[datetime], Field(description="Include campaigns ended before this timestamp (exclusive). ISO 8601 format.")] = None,
+ stopped_at_after: Annotated[Optional[datetime], Field(description="Include campaigns stopped after this timestamp (exclusive). ISO 8601 format.")] = None,
+ stopped_at_before: Annotated[Optional[datetime], Field(description="Include campaigns stopped before this timestamp (exclusive). ISO 8601 format.")] = None,
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> RESTResponseType:
+ """get_campaigns
+
+ Returns a list of `Campaign` objects.
+
+ :param cursor: The pagination cursor value.
+ :type cursor: str
+ :param page_size: Number of results to return per page. Default is 200.
+ :type page_size: int
+ :param name: Campaign name to filter by. Returns campaigns whose names contain this substring (case-insensitive).
+ :type name: str
+ :param status: Filter by campaign status. Status is derived from lifecycle timestamps and review progress.
+ :type status: CampaignStatusEnum
+ :param created_at_after: Include campaigns created after this timestamp (exclusive). ISO 8601 format.
+ :type created_at_after: datetime
+ :param created_at_before: Include campaigns created before this timestamp (exclusive). ISO 8601 format.
+ :type created_at_before: datetime
+ :param started_at_after: Include campaigns started after this timestamp (exclusive). ISO 8601 format.
+ :type started_at_after: datetime
+ :param started_at_before: Include campaigns started before this timestamp (exclusive). ISO 8601 format.
+ :type started_at_before: datetime
+ :param ended_at_after: Include campaigns ended after this timestamp (exclusive). ISO 8601 format.
+ :type ended_at_after: datetime
+ :param ended_at_before: Include campaigns ended before this timestamp (exclusive). ISO 8601 format.
+ :type ended_at_before: datetime
+ :param stopped_at_after: Include campaigns stopped after this timestamp (exclusive). ISO 8601 format.
+ :type stopped_at_after: datetime
+ :param stopped_at_before: Include campaigns stopped before this timestamp (exclusive). ISO 8601 format.
+ :type stopped_at_before: datetime
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._get_campaigns_serialize(
+ cursor=cursor,
+ page_size=page_size,
+ name=name,
+ status=status,
+ created_at_after=created_at_after,
+ created_at_before=created_at_before,
+ started_at_after=started_at_after,
+ started_at_before=started_at_before,
+ ended_at_after=ended_at_after,
+ ended_at_before=ended_at_before,
+ stopped_at_after=stopped_at_after,
+ stopped_at_before=stopped_at_before,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "PaginatedCampaignsList",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ return response_data.response
+
+
+ def _get_campaigns_serialize(
+ self,
+ cursor,
+ page_size,
+ name,
+ status,
+ created_at_after,
+ created_at_before,
+ started_at_after,
+ started_at_before,
+ ended_at_after,
+ ended_at_before,
+ stopped_at_after,
+ stopped_at_before,
+ _request_auth,
+ _content_type,
+ _headers,
+ _host_index,
+ ) -> RequestSerialized:
+
+ _host = None
+
+ _collection_formats: Dict[str, str] = {
+ }
+
+ _path_params: Dict[str, str] = {}
+ _query_params: List[Tuple[str, str]] = []
+ _header_params: Dict[str, Optional[str]] = _headers or {}
+ _form_params: List[Tuple[str, str]] = []
+ _files: Dict[
+ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+ ] = {}
+ _body_params: Optional[bytes] = None
+
+ # process the path parameters
+ # process the query parameters
+ if cursor is not None:
+
+ _query_params.append(('cursor', cursor))
+
+ if page_size is not None:
+
+ _query_params.append(('page_size', page_size))
+
+ if name is not None:
+
+ _query_params.append(('name', name))
+
+ if status is not None:
+
+ _query_params.append(('status', status.value))
+
+ if created_at_after is not None:
+ if isinstance(created_at_after, datetime):
+ _query_params.append(
+ (
+ 'created_at_after',
+ created_at_after.strftime(
+ self.api_client.configuration.datetime_format
+ )
+ )
+ )
+ else:
+ _query_params.append(('created_at_after', created_at_after))
+
+ if created_at_before is not None:
+ if isinstance(created_at_before, datetime):
+ _query_params.append(
+ (
+ 'created_at_before',
+ created_at_before.strftime(
+ self.api_client.configuration.datetime_format
+ )
+ )
+ )
+ else:
+ _query_params.append(('created_at_before', created_at_before))
+
+ if started_at_after is not None:
+ if isinstance(started_at_after, datetime):
+ _query_params.append(
+ (
+ 'started_at_after',
+ started_at_after.strftime(
+ self.api_client.configuration.datetime_format
+ )
+ )
+ )
+ else:
+ _query_params.append(('started_at_after', started_at_after))
+
+ if started_at_before is not None:
+ if isinstance(started_at_before, datetime):
+ _query_params.append(
+ (
+ 'started_at_before',
+ started_at_before.strftime(
+ self.api_client.configuration.datetime_format
+ )
+ )
+ )
+ else:
+ _query_params.append(('started_at_before', started_at_before))
+
+ if ended_at_after is not None:
+ if isinstance(ended_at_after, datetime):
+ _query_params.append(
+ (
+ 'ended_at_after',
+ ended_at_after.strftime(
+ self.api_client.configuration.datetime_format
+ )
+ )
+ )
+ else:
+ _query_params.append(('ended_at_after', ended_at_after))
+
+ if ended_at_before is not None:
+ if isinstance(ended_at_before, datetime):
+ _query_params.append(
+ (
+ 'ended_at_before',
+ ended_at_before.strftime(
+ self.api_client.configuration.datetime_format
+ )
+ )
+ )
+ else:
+ _query_params.append(('ended_at_before', ended_at_before))
+
+ if stopped_at_after is not None:
+ if isinstance(stopped_at_after, datetime):
+ _query_params.append(
+ (
+ 'stopped_at_after',
+ stopped_at_after.strftime(
+ self.api_client.configuration.datetime_format
+ )
+ )
+ )
+ else:
+ _query_params.append(('stopped_at_after', stopped_at_after))
+
+ if stopped_at_before is not None:
+ if isinstance(stopped_at_before, datetime):
+ _query_params.append(
+ (
+ 'stopped_at_before',
+ stopped_at_before.strftime(
+ self.api_client.configuration.datetime_format
+ )
+ )
+ )
+ else:
+ _query_params.append(('stopped_at_before', stopped_at_before))
+
+ # process the header parameters
+ # process the form parameters
+ # process the body parameter
+
+
+ # set the HTTP header `Accept`
+ if 'Accept' not in _header_params:
+ _header_params['Accept'] = self.api_client.select_header_accept(
+ [
+ 'application/json'
+ ]
+ )
+
+
+ # authentication setting
+ _auth_settings: List[str] = [
+ 'BearerAuth'
+ ]
+
+ return self.api_client.param_serialize(
+ method='GET',
+ resource_path='/campaigns',
+ path_params=_path_params,
+ query_params=_query_params,
+ header_params=_header_params,
+ body=_body_params,
+ post_params=_form_params,
+ files=_files,
+ auth_settings=_auth_settings,
+ collection_formats=_collection_formats,
+ _host=_host,
+ _request_auth=_request_auth
+ )
+
+
+
+
+ @validate_call
+ def start_campaign(
+ self,
+ campaign_id: Annotated[UUID, Field(description="The ID of the campaign.")],
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> Campaign:
+ """Start campaign
+
+ Starts a draft campaign immediately, setting `started_at` and `started_by_user_id`. Returns 400 if the campaign is not in draft state, or if it is a recurring template (`is_template: true`) — templates spawn draft campaigns on their schedule and cannot be started directly.
+
+ :param campaign_id: The ID of the campaign. (required)
+ :type campaign_id: UUID
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._start_campaign_serialize(
+ campaign_id=campaign_id,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "Campaign",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ ).data
+
+
+ @validate_call
+ def start_campaign_with_http_info(
+ self,
+ campaign_id: Annotated[UUID, Field(description="The ID of the campaign.")],
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> ApiResponse[Campaign]:
+ """Start campaign
+
+ Starts a draft campaign immediately, setting `started_at` and `started_by_user_id`. Returns 400 if the campaign is not in draft state, or if it is a recurring template (`is_template: true`) — templates spawn draft campaigns on their schedule and cannot be started directly.
+
+ :param campaign_id: The ID of the campaign. (required)
+ :type campaign_id: UUID
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._start_campaign_serialize(
+ campaign_id=campaign_id,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "Campaign",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ )
+
+
+ @validate_call
+ def start_campaign_without_preload_content(
+ self,
+ campaign_id: Annotated[UUID, Field(description="The ID of the campaign.")],
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> RESTResponseType:
+ """Start campaign
+
+ Starts a draft campaign immediately, setting `started_at` and `started_by_user_id`. Returns 400 if the campaign is not in draft state, or if it is a recurring template (`is_template: true`) — templates spawn draft campaigns on their schedule and cannot be started directly.
+
+ :param campaign_id: The ID of the campaign. (required)
+ :type campaign_id: UUID
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._start_campaign_serialize(
+ campaign_id=campaign_id,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "Campaign",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ return response_data.response
+
+
+ def _start_campaign_serialize(
+ self,
+ campaign_id,
+ _request_auth,
+ _content_type,
+ _headers,
+ _host_index,
+ ) -> RequestSerialized:
+
+ _host = None
+
+ _collection_formats: Dict[str, str] = {
+ }
+
+ _path_params: Dict[str, str] = {}
+ _query_params: List[Tuple[str, str]] = []
+ _header_params: Dict[str, Optional[str]] = _headers or {}
+ _form_params: List[Tuple[str, str]] = []
+ _files: Dict[
+ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+ ] = {}
+ _body_params: Optional[bytes] = None
+
+ # process the path parameters
+ if campaign_id is not None:
+ _path_params['campaign_id'] = campaign_id
+ # process the query parameters
+ # process the header parameters
+ # process the form parameters
+ # process the body parameter
+
+
+ # set the HTTP header `Accept`
+ if 'Accept' not in _header_params:
+ _header_params['Accept'] = self.api_client.select_header_accept(
+ [
+ 'application/json'
+ ]
+ )
+
+
+ # authentication setting
+ _auth_settings: List[str] = [
+ 'BearerAuth'
+ ]
+
+ return self.api_client.param_serialize(
+ method='POST',
+ resource_path='/campaigns/{campaign_id}/start',
+ path_params=_path_params,
+ query_params=_query_params,
+ header_params=_header_params,
+ body=_body_params,
+ post_params=_form_params,
+ files=_files,
+ auth_settings=_auth_settings,
+ collection_formats=_collection_formats,
+ _host=_host,
+ _request_auth=_request_auth
+ )
+
+
+
+
+ @validate_call
+ def stop_campaign(
+ self,
+ campaign_id: Annotated[UUID, Field(description="The ID of the campaign.")],
+ stop_campaign_request: Optional[StopCampaignRequest] = None,
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> Campaign:
+ """Stop campaign
+
+ Stops an ongoing campaign immediately, setting `stopped_at` and `stopped_by_user_id`. Returns 400 if the campaign has not started or has already stopped.
+
+ :param campaign_id: The ID of the campaign. (required)
+ :type campaign_id: UUID
+ :param stop_campaign_request:
+ :type stop_campaign_request: StopCampaignRequest
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._stop_campaign_serialize(
+ campaign_id=campaign_id,
+ stop_campaign_request=stop_campaign_request,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "Campaign",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ ).data
+
+
+ @validate_call
+ def stop_campaign_with_http_info(
+ self,
+ campaign_id: Annotated[UUID, Field(description="The ID of the campaign.")],
+ stop_campaign_request: Optional[StopCampaignRequest] = None,
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> ApiResponse[Campaign]:
+ """Stop campaign
+
+ Stops an ongoing campaign immediately, setting `stopped_at` and `stopped_by_user_id`. Returns 400 if the campaign has not started or has already stopped.
+
+ :param campaign_id: The ID of the campaign. (required)
+ :type campaign_id: UUID
+ :param stop_campaign_request:
+ :type stop_campaign_request: StopCampaignRequest
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._stop_campaign_serialize(
+ campaign_id=campaign_id,
+ stop_campaign_request=stop_campaign_request,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "Campaign",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ )
+
+
+ @validate_call
+ def stop_campaign_without_preload_content(
+ self,
+ campaign_id: Annotated[UUID, Field(description="The ID of the campaign.")],
+ stop_campaign_request: Optional[StopCampaignRequest] = None,
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> RESTResponseType:
+ """Stop campaign
+
+ Stops an ongoing campaign immediately, setting `stopped_at` and `stopped_by_user_id`. Returns 400 if the campaign has not started or has already stopped.
+
+ :param campaign_id: The ID of the campaign. (required)
+ :type campaign_id: UUID
+ :param stop_campaign_request:
+ :type stop_campaign_request: StopCampaignRequest
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._stop_campaign_serialize(
+ campaign_id=campaign_id,
+ stop_campaign_request=stop_campaign_request,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "Campaign",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ return response_data.response
+
+
+ def _stop_campaign_serialize(
+ self,
+ campaign_id,
+ stop_campaign_request,
+ _request_auth,
+ _content_type,
+ _headers,
+ _host_index,
+ ) -> RequestSerialized:
+
+ _host = None
+
+ _collection_formats: Dict[str, str] = {
+ }
+
+ _path_params: Dict[str, str] = {}
+ _query_params: List[Tuple[str, str]] = []
+ _header_params: Dict[str, Optional[str]] = _headers or {}
+ _form_params: List[Tuple[str, str]] = []
+ _files: Dict[
+ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+ ] = {}
+ _body_params: Optional[bytes] = None
+
+ # process the path parameters
+ if campaign_id is not None:
+ _path_params['campaign_id'] = campaign_id
+ # process the query parameters
+ # process the header parameters
+ # process the form parameters
+ # process the body parameter
+ if stop_campaign_request is not None:
+ _body_params = stop_campaign_request
+
+
+ # set the HTTP header `Accept`
+ if 'Accept' not in _header_params:
+ _header_params['Accept'] = self.api_client.select_header_accept(
+ [
+ 'application/json'
+ ]
+ )
+
+ # set the HTTP header `Content-Type`
+ if _content_type:
+ _header_params['Content-Type'] = _content_type
+ else:
+ _default_content_type = (
+ self.api_client.select_header_content_type(
+ [
+ 'application/json'
+ ]
+ )
+ )
+ if _default_content_type is not None:
+ _header_params['Content-Type'] = _default_content_type
+
+ # authentication setting
+ _auth_settings: List[str] = [
+ 'BearerAuth'
+ ]
+
+ return self.api_client.param_serialize(
+ method='POST',
+ resource_path='/campaigns/{campaign_id}/stop',
+ path_params=_path_params,
+ query_params=_query_params,
+ header_params=_header_params,
+ body=_body_params,
+ post_params=_form_params,
+ files=_files,
+ auth_settings=_auth_settings,
+ collection_formats=_collection_formats,
+ _host=_host,
+ _request_auth=_request_auth
+ )
+
+
+
+
+ @validate_call
+ def update_campaign(
+ self,
+ campaign_id: Annotated[UUID, Field(description="The ID of the campaign.")],
+ update_campaign_info: UpdateCampaignInfo,
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> Campaign:
+ """Update campaign
+
+ Partially updates a campaign. Omitted fields are left unchanged. `configuration.query` and `configuration.reviewer_assignment_policy` cannot be updated after create; including either field returns 400. `configuration.cron_expression` and `configuration.recurring_duration_days` may only be set on template campaigns; setting them on a one-off campaign returns 400. `configuration.is_template` is immutable and not accepted on update. Configuration updates on a stopped or ended (non-template) campaign return 400. Name-only updates are still allowed.
+
+ :param campaign_id: The ID of the campaign. (required)
+ :type campaign_id: UUID
+ :param update_campaign_info: (required)
+ :type update_campaign_info: UpdateCampaignInfo
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._update_campaign_serialize(
+ campaign_id=campaign_id,
+ update_campaign_info=update_campaign_info,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "Campaign",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ ).data
+
+
+ @validate_call
+ def update_campaign_with_http_info(
+ self,
+ campaign_id: Annotated[UUID, Field(description="The ID of the campaign.")],
+ update_campaign_info: UpdateCampaignInfo,
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> ApiResponse[Campaign]:
+ """Update campaign
+
+ Partially updates a campaign. Omitted fields are left unchanged. `configuration.query` and `configuration.reviewer_assignment_policy` cannot be updated after create; including either field returns 400. `configuration.cron_expression` and `configuration.recurring_duration_days` may only be set on template campaigns; setting them on a one-off campaign returns 400. `configuration.is_template` is immutable and not accepted on update. Configuration updates on a stopped or ended (non-template) campaign return 400. Name-only updates are still allowed.
+
+ :param campaign_id: The ID of the campaign. (required)
+ :type campaign_id: UUID
+ :param update_campaign_info: (required)
+ :type update_campaign_info: UpdateCampaignInfo
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._update_campaign_serialize(
+ campaign_id=campaign_id,
+ update_campaign_info=update_campaign_info,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "Campaign",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ )
+
+
+ @validate_call
+ def update_campaign_without_preload_content(
+ self,
+ campaign_id: Annotated[UUID, Field(description="The ID of the campaign.")],
+ update_campaign_info: UpdateCampaignInfo,
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> RESTResponseType:
+ """Update campaign
+
+ Partially updates a campaign. Omitted fields are left unchanged. `configuration.query` and `configuration.reviewer_assignment_policy` cannot be updated after create; including either field returns 400. `configuration.cron_expression` and `configuration.recurring_duration_days` may only be set on template campaigns; setting them on a one-off campaign returns 400. `configuration.is_template` is immutable and not accepted on update. Configuration updates on a stopped or ended (non-template) campaign return 400. Name-only updates are still allowed.
+
+ :param campaign_id: The ID of the campaign. (required)
+ :type campaign_id: UUID
+ :param update_campaign_info: (required)
+ :type update_campaign_info: UpdateCampaignInfo
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._update_campaign_serialize(
+ campaign_id=campaign_id,
+ update_campaign_info=update_campaign_info,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "Campaign",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ return response_data.response
+
+
+ def _update_campaign_serialize(
+ self,
+ campaign_id,
+ update_campaign_info,
+ _request_auth,
+ _content_type,
+ _headers,
+ _host_index,
+ ) -> RequestSerialized:
+
+ _host = None
+
+ _collection_formats: Dict[str, str] = {
+ }
+
+ _path_params: Dict[str, str] = {}
+ _query_params: List[Tuple[str, str]] = []
+ _header_params: Dict[str, Optional[str]] = _headers or {}
+ _form_params: List[Tuple[str, str]] = []
+ _files: Dict[
+ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+ ] = {}
+ _body_params: Optional[bytes] = None
+
+ # process the path parameters
+ if campaign_id is not None:
+ _path_params['campaign_id'] = campaign_id
+ # process the query parameters
+ # process the header parameters
+ # process the form parameters
+ # process the body parameter
+ if update_campaign_info is not None:
+ _body_params = update_campaign_info
+
+
+ # set the HTTP header `Accept`
+ if 'Accept' not in _header_params:
+ _header_params['Accept'] = self.api_client.select_header_accept(
+ [
+ 'application/json'
+ ]
+ )
+
+ # set the HTTP header `Content-Type`
+ if _content_type:
+ _header_params['Content-Type'] = _content_type
+ else:
+ _default_content_type = (
+ self.api_client.select_header_content_type(
+ [
+ 'application/json'
+ ]
+ )
+ )
+ if _default_content_type is not None:
+ _header_params['Content-Type'] = _default_content_type
+
+ # authentication setting
+ _auth_settings: List[str] = [
+ 'BearerAuth'
+ ]
+
+ return self.api_client.param_serialize(
+ method='PUT',
+ resource_path='/campaigns/{campaign_id}',
+ path_params=_path_params,
+ query_params=_query_params,
+ header_params=_header_params,
+ body=_body_params,
+ post_params=_form_params,
+ files=_files,
+ auth_settings=_auth_settings,
+ collection_formats=_collection_formats,
+ _host=_host,
+ _request_auth=_request_auth
+ )
+
+
diff --git a/opal_security/api/groups_api.py b/opal_security/api/groups_api.py
index 37436ce..7b91076 100644
--- a/opal_security/api/groups_api.py
+++ b/opal_security/api/groups_api.py
@@ -4218,7 +4218,7 @@ def get_group_users(
self,
group_id: Annotated[UUID, Field(description="The ID of the group.")],
cursor: Annotated[Optional[StrictStr], Field(description="The pagination cursor value.")] = None,
- page_size: Annotated[Optional[Annotated[int, Field(le=1000, strict=True)]], Field(description="Number of results to return per page. Default is 200.")] = None,
+ page_size: Annotated[Optional[Annotated[int, Field(le=1000, strict=True)]], Field(description="Number of results to return per page, up to 1000. When set (or when a cursor is provided), the response contains a single page of results and a `next` cursor; the default page size is 200. When both page_size and cursor are omitted, the entire group membership is returned in one response with no `next` cursor. For large groups, prefer setting page_size and following `next`.")] = None,
_request_timeout: Union[
None,
Annotated[StrictFloat, Field(gt=0)],
@@ -4240,7 +4240,7 @@ def get_group_users(
:type group_id: UUID
:param cursor: The pagination cursor value.
:type cursor: str
- :param page_size: Number of results to return per page. Default is 200.
+ :param page_size: Number of results to return per page, up to 1000. When set (or when a cursor is provided), the response contains a single page of results and a `next` cursor; the default page size is 200. When both page_size and cursor are omitted, the entire group membership is returned in one response with no `next` cursor. For large groups, prefer setting page_size and following `next`.
:type page_size: int
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
@@ -4293,7 +4293,7 @@ def get_group_users_with_http_info(
self,
group_id: Annotated[UUID, Field(description="The ID of the group.")],
cursor: Annotated[Optional[StrictStr], Field(description="The pagination cursor value.")] = None,
- page_size: Annotated[Optional[Annotated[int, Field(le=1000, strict=True)]], Field(description="Number of results to return per page. Default is 200.")] = None,
+ page_size: Annotated[Optional[Annotated[int, Field(le=1000, strict=True)]], Field(description="Number of results to return per page, up to 1000. When set (or when a cursor is provided), the response contains a single page of results and a `next` cursor; the default page size is 200. When both page_size and cursor are omitted, the entire group membership is returned in one response with no `next` cursor. For large groups, prefer setting page_size and following `next`.")] = None,
_request_timeout: Union[
None,
Annotated[StrictFloat, Field(gt=0)],
@@ -4315,7 +4315,7 @@ def get_group_users_with_http_info(
:type group_id: UUID
:param cursor: The pagination cursor value.
:type cursor: str
- :param page_size: Number of results to return per page. Default is 200.
+ :param page_size: Number of results to return per page, up to 1000. When set (or when a cursor is provided), the response contains a single page of results and a `next` cursor; the default page size is 200. When both page_size and cursor are omitted, the entire group membership is returned in one response with no `next` cursor. For large groups, prefer setting page_size and following `next`.
:type page_size: int
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
@@ -4368,7 +4368,7 @@ def get_group_users_without_preload_content(
self,
group_id: Annotated[UUID, Field(description="The ID of the group.")],
cursor: Annotated[Optional[StrictStr], Field(description="The pagination cursor value.")] = None,
- page_size: Annotated[Optional[Annotated[int, Field(le=1000, strict=True)]], Field(description="Number of results to return per page. Default is 200.")] = None,
+ page_size: Annotated[Optional[Annotated[int, Field(le=1000, strict=True)]], Field(description="Number of results to return per page, up to 1000. When set (or when a cursor is provided), the response contains a single page of results and a `next` cursor; the default page size is 200. When both page_size and cursor are omitted, the entire group membership is returned in one response with no `next` cursor. For large groups, prefer setting page_size and following `next`.")] = None,
_request_timeout: Union[
None,
Annotated[StrictFloat, Field(gt=0)],
@@ -4390,7 +4390,7 @@ def get_group_users_without_preload_content(
:type group_id: UUID
:param cursor: The pagination cursor value.
:type cursor: str
- :param page_size: Number of results to return per page. Default is 200.
+ :param page_size: Number of results to return per page, up to 1000. When set (or when a cursor is provided), the response contains a single page of results and a `next` cursor; the default page size is 200. When both page_size and cursor are omitted, the entire group membership is returned in one response with no `next` cursor. For large groups, prefer setting page_size and following `next`.
:type page_size: int
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
diff --git a/opal_security/api/opal_queries_api.py b/opal_security/api/opal_queries_api.py
index e5bb1df..29b1299 100644
--- a/opal_security/api/opal_queries_api.py
+++ b/opal_security/api/opal_queries_api.py
@@ -17,8 +17,8 @@
from typing import Any, Dict, List, Optional, Tuple, Union
from typing_extensions import Annotated
-from opal_security.models.opal_node_query import OpalNodeQuery
-from opal_security.models.opal_node_query_results import OpalNodeQueryResults
+from opal_security.models.opal_query_results import OpalQueryResults
+from opal_security.models.run_opal_query_request import RunOpalQueryRequest
from opal_security.api_client import ApiClient, RequestSerialized
from opal_security.api_response import ApiResponse
@@ -41,7 +41,7 @@ def __init__(self, api_client=None) -> None:
@validate_call
def run_opal_query(
self,
- body: OpalNodeQuery,
+ run_opal_query_request: RunOpalQueryRequest,
_request_timeout: Union[
None,
Annotated[StrictFloat, Field(gt=0)],
@@ -54,13 +54,13 @@ def run_opal_query(
_content_type: Optional[StrictStr] = None,
_headers: Optional[Dict[StrictStr, Any]] = None,
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
- ) -> OpalNodeQueryResults:
+ ) -> OpalQueryResults:
"""Run an ad-hoc OpalQuery
- Runs an ad-hoc OpalQuery and returns the results. Currently supports NODE queries (users, resources, groups). This endpoint is only available to our OpalQuery beta group. Please contact Opal support if you'd like to be added to the beta.
+ Runs an ad-hoc OpalQuery and returns the results. Supports NODE queries (users, resources, groups) and ACCESS_PATH queries (principal-to-entitlement access edges). This endpoint is only available to our OpalQuery beta group. Please contact Opal support if you'd like to be added to the beta.
- :param body: (required)
- :type body: OpalNodeQuery
+ :param run_opal_query_request: (required)
+ :type run_opal_query_request: RunOpalQueryRequest
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
timeout. It can also be a pair (tuple) of
@@ -84,7 +84,7 @@ def run_opal_query(
""" # noqa: E501
_param = self._run_opal_query_serialize(
- body=body,
+ run_opal_query_request=run_opal_query_request,
_request_auth=_request_auth,
_content_type=_content_type,
_headers=_headers,
@@ -92,7 +92,7 @@ def run_opal_query(
)
_response_types_map: Dict[str, Optional[str]] = {
- '200': "OpalNodeQueryResults",
+ '200': "OpalQueryResults",
}
response_data = self.api_client.call_api(
*_param,
@@ -108,7 +108,7 @@ def run_opal_query(
@validate_call
def run_opal_query_with_http_info(
self,
- body: OpalNodeQuery,
+ run_opal_query_request: RunOpalQueryRequest,
_request_timeout: Union[
None,
Annotated[StrictFloat, Field(gt=0)],
@@ -121,13 +121,13 @@ def run_opal_query_with_http_info(
_content_type: Optional[StrictStr] = None,
_headers: Optional[Dict[StrictStr, Any]] = None,
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
- ) -> ApiResponse[OpalNodeQueryResults]:
+ ) -> ApiResponse[OpalQueryResults]:
"""Run an ad-hoc OpalQuery
- Runs an ad-hoc OpalQuery and returns the results. Currently supports NODE queries (users, resources, groups). This endpoint is only available to our OpalQuery beta group. Please contact Opal support if you'd like to be added to the beta.
+ Runs an ad-hoc OpalQuery and returns the results. Supports NODE queries (users, resources, groups) and ACCESS_PATH queries (principal-to-entitlement access edges). This endpoint is only available to our OpalQuery beta group. Please contact Opal support if you'd like to be added to the beta.
- :param body: (required)
- :type body: OpalNodeQuery
+ :param run_opal_query_request: (required)
+ :type run_opal_query_request: RunOpalQueryRequest
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
timeout. It can also be a pair (tuple) of
@@ -151,7 +151,7 @@ def run_opal_query_with_http_info(
""" # noqa: E501
_param = self._run_opal_query_serialize(
- body=body,
+ run_opal_query_request=run_opal_query_request,
_request_auth=_request_auth,
_content_type=_content_type,
_headers=_headers,
@@ -159,7 +159,7 @@ def run_opal_query_with_http_info(
)
_response_types_map: Dict[str, Optional[str]] = {
- '200': "OpalNodeQueryResults",
+ '200': "OpalQueryResults",
}
response_data = self.api_client.call_api(
*_param,
@@ -175,7 +175,7 @@ def run_opal_query_with_http_info(
@validate_call
def run_opal_query_without_preload_content(
self,
- body: OpalNodeQuery,
+ run_opal_query_request: RunOpalQueryRequest,
_request_timeout: Union[
None,
Annotated[StrictFloat, Field(gt=0)],
@@ -191,10 +191,10 @@ def run_opal_query_without_preload_content(
) -> RESTResponseType:
"""Run an ad-hoc OpalQuery
- Runs an ad-hoc OpalQuery and returns the results. Currently supports NODE queries (users, resources, groups). This endpoint is only available to our OpalQuery beta group. Please contact Opal support if you'd like to be added to the beta.
+ Runs an ad-hoc OpalQuery and returns the results. Supports NODE queries (users, resources, groups) and ACCESS_PATH queries (principal-to-entitlement access edges). This endpoint is only available to our OpalQuery beta group. Please contact Opal support if you'd like to be added to the beta.
- :param body: (required)
- :type body: OpalNodeQuery
+ :param run_opal_query_request: (required)
+ :type run_opal_query_request: RunOpalQueryRequest
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
timeout. It can also be a pair (tuple) of
@@ -218,7 +218,7 @@ def run_opal_query_without_preload_content(
""" # noqa: E501
_param = self._run_opal_query_serialize(
- body=body,
+ run_opal_query_request=run_opal_query_request,
_request_auth=_request_auth,
_content_type=_content_type,
_headers=_headers,
@@ -226,7 +226,7 @@ def run_opal_query_without_preload_content(
)
_response_types_map: Dict[str, Optional[str]] = {
- '200': "OpalNodeQueryResults",
+ '200': "OpalQueryResults",
}
response_data = self.api_client.call_api(
*_param,
@@ -237,7 +237,7 @@ def run_opal_query_without_preload_content(
def _run_opal_query_serialize(
self,
- body,
+ run_opal_query_request,
_request_auth,
_content_type,
_headers,
@@ -263,8 +263,8 @@ def _run_opal_query_serialize(
# process the header parameters
# process the form parameters
# process the body parameter
- if body is not None:
- _body_params = body
+ if run_opal_query_request is not None:
+ _body_params = run_opal_query_request
# set the HTTP header `Accept`
diff --git a/opal_security/api/paladin_api.py b/opal_security/api/paladin_api.py
new file mode 100644
index 0000000..1f19c69
--- /dev/null
+++ b/opal_security/api/paladin_api.py
@@ -0,0 +1,563 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+import warnings
+from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt
+from typing import Any, Dict, List, Optional, Tuple, Union
+from typing_extensions import Annotated
+
+from pydantic import Field, StrictStr
+from typing_extensions import Annotated
+from uuid import UUID
+from opal_security.models.paladin import Paladin
+from opal_security.models.paladin_list import PaladinList
+
+from opal_security.api_client import ApiClient, RequestSerialized
+from opal_security.api_response import ApiResponse
+from opal_security.rest import RESTResponseType
+
+
+class PaladinApi:
+ """NOTE: This class is auto generated by OpenAPI Generator
+ Ref: https://openapi-generator.tech
+
+ Do not edit the class manually.
+ """
+
+ def __init__(self, api_client=None) -> None:
+ if api_client is None:
+ api_client = ApiClient.get_default()
+ self.api_client = api_client
+
+
+ @validate_call
+ def get_paladin(
+ self,
+ paladin_id: Annotated[UUID, Field(description="The ID of the Paladin.")],
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> Paladin:
+ """Get Paladin by ID
+
+ Returns a `Paladin` object.
+
+ :param paladin_id: The ID of the Paladin. (required)
+ :type paladin_id: UUID
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._get_paladin_serialize(
+ paladin_id=paladin_id,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "Paladin",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ ).data
+
+
+ @validate_call
+ def get_paladin_with_http_info(
+ self,
+ paladin_id: Annotated[UUID, Field(description="The ID of the Paladin.")],
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> ApiResponse[Paladin]:
+ """Get Paladin by ID
+
+ Returns a `Paladin` object.
+
+ :param paladin_id: The ID of the Paladin. (required)
+ :type paladin_id: UUID
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._get_paladin_serialize(
+ paladin_id=paladin_id,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "Paladin",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ )
+
+
+ @validate_call
+ def get_paladin_without_preload_content(
+ self,
+ paladin_id: Annotated[UUID, Field(description="The ID of the Paladin.")],
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> RESTResponseType:
+ """Get Paladin by ID
+
+ Returns a `Paladin` object.
+
+ :param paladin_id: The ID of the Paladin. (required)
+ :type paladin_id: UUID
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._get_paladin_serialize(
+ paladin_id=paladin_id,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "Paladin",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ return response_data.response
+
+
+ def _get_paladin_serialize(
+ self,
+ paladin_id,
+ _request_auth,
+ _content_type,
+ _headers,
+ _host_index,
+ ) -> RequestSerialized:
+
+ _host = None
+
+ _collection_formats: Dict[str, str] = {
+ }
+
+ _path_params: Dict[str, str] = {}
+ _query_params: List[Tuple[str, str]] = []
+ _header_params: Dict[str, Optional[str]] = _headers or {}
+ _form_params: List[Tuple[str, str]] = []
+ _files: Dict[
+ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+ ] = {}
+ _body_params: Optional[bytes] = None
+
+ # process the path parameters
+ if paladin_id is not None:
+ _path_params['paladin_id'] = paladin_id
+ # process the query parameters
+ # process the header parameters
+ # process the form parameters
+ # process the body parameter
+
+
+ # set the HTTP header `Accept`
+ if 'Accept' not in _header_params:
+ _header_params['Accept'] = self.api_client.select_header_accept(
+ [
+ 'application/json'
+ ]
+ )
+
+
+ # authentication setting
+ _auth_settings: List[str] = [
+ 'BearerAuth'
+ ]
+
+ return self.api_client.param_serialize(
+ method='GET',
+ resource_path='/paladin/{paladin_id}',
+ path_params=_path_params,
+ query_params=_query_params,
+ header_params=_header_params,
+ body=_body_params,
+ post_params=_form_params,
+ files=_files,
+ auth_settings=_auth_settings,
+ collection_formats=_collection_formats,
+ _host=_host,
+ _request_auth=_request_auth
+ )
+
+
+
+
+ @validate_call
+ def get_paladin_from_name(
+ self,
+ paladin_name: Annotated[StrictStr, Field(description="The name of the Paladin.")],
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> PaladinList:
+ """Get Paladins by name
+
+ Returns all Paladins whose name exactly matches the given name. Names are not unique, so the result is a list and may be empty.
+
+ :param paladin_name: The name of the Paladin. (required)
+ :type paladin_name: str
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._get_paladin_from_name_serialize(
+ paladin_name=paladin_name,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "PaladinList",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ ).data
+
+
+ @validate_call
+ def get_paladin_from_name_with_http_info(
+ self,
+ paladin_name: Annotated[StrictStr, Field(description="The name of the Paladin.")],
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> ApiResponse[PaladinList]:
+ """Get Paladins by name
+
+ Returns all Paladins whose name exactly matches the given name. Names are not unique, so the result is a list and may be empty.
+
+ :param paladin_name: The name of the Paladin. (required)
+ :type paladin_name: str
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._get_paladin_from_name_serialize(
+ paladin_name=paladin_name,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "PaladinList",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ )
+
+
+ @validate_call
+ def get_paladin_from_name_without_preload_content(
+ self,
+ paladin_name: Annotated[StrictStr, Field(description="The name of the Paladin.")],
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> RESTResponseType:
+ """Get Paladins by name
+
+ Returns all Paladins whose name exactly matches the given name. Names are not unique, so the result is a list and may be empty.
+
+ :param paladin_name: The name of the Paladin. (required)
+ :type paladin_name: str
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._get_paladin_from_name_serialize(
+ paladin_name=paladin_name,
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "PaladinList",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ return response_data.response
+
+
+ def _get_paladin_from_name_serialize(
+ self,
+ paladin_name,
+ _request_auth,
+ _content_type,
+ _headers,
+ _host_index,
+ ) -> RequestSerialized:
+
+ _host = None
+
+ _collection_formats: Dict[str, str] = {
+ }
+
+ _path_params: Dict[str, str] = {}
+ _query_params: List[Tuple[str, str]] = []
+ _header_params: Dict[str, Optional[str]] = _headers or {}
+ _form_params: List[Tuple[str, str]] = []
+ _files: Dict[
+ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+ ] = {}
+ _body_params: Optional[bytes] = None
+
+ # process the path parameters
+ if paladin_name is not None:
+ _path_params['paladin_name'] = paladin_name
+ # process the query parameters
+ # process the header parameters
+ # process the form parameters
+ # process the body parameter
+
+
+ # set the HTTP header `Accept`
+ if 'Accept' not in _header_params:
+ _header_params['Accept'] = self.api_client.select_header_accept(
+ [
+ 'application/json'
+ ]
+ )
+
+
+ # authentication setting
+ _auth_settings: List[str] = [
+ 'BearerAuth'
+ ]
+
+ return self.api_client.param_serialize(
+ method='GET',
+ resource_path='/paladin/name/{paladin_name}',
+ path_params=_path_params,
+ query_params=_query_params,
+ header_params=_header_params,
+ body=_body_params,
+ post_params=_form_params,
+ files=_files,
+ auth_settings=_auth_settings,
+ collection_formats=_collection_formats,
+ _host=_host,
+ _request_auth=_request_auth
+ )
+
+
diff --git a/opal_security/api/uars_api.py b/opal_security/api/uars_api.py
index f3f0df1..7f804ed 100644
--- a/opal_security/api/uars_api.py
+++ b/opal_security/api/uars_api.py
@@ -60,9 +60,9 @@ def create_uar(
_headers: Optional[Dict[StrictStr, Any]] = None,
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
) -> UAR:
- """create_uar
+ """(Deprecated) create_uar
- Starts a User Access Review.
+ Starts a User Access Review. Deprecated in favor of `POST /campaigns`.
:param create_uar_info: The settings of the UAR. (required)
:type create_uar_info: CreateUARInfo
@@ -87,6 +87,7 @@ def create_uar(
:type _host_index: int, optional
:return: Returns the result object.
""" # noqa: E501
+ warnings.warn("POST /uar is deprecated.", DeprecationWarning)
_param = self._create_uar_serialize(
create_uar_info=create_uar_info,
@@ -127,9 +128,9 @@ def create_uar_with_http_info(
_headers: Optional[Dict[StrictStr, Any]] = None,
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
) -> ApiResponse[UAR]:
- """create_uar
+ """(Deprecated) create_uar
- Starts a User Access Review.
+ Starts a User Access Review. Deprecated in favor of `POST /campaigns`.
:param create_uar_info: The settings of the UAR. (required)
:type create_uar_info: CreateUARInfo
@@ -154,6 +155,7 @@ def create_uar_with_http_info(
:type _host_index: int, optional
:return: Returns the result object.
""" # noqa: E501
+ warnings.warn("POST /uar is deprecated.", DeprecationWarning)
_param = self._create_uar_serialize(
create_uar_info=create_uar_info,
@@ -194,9 +196,9 @@ def create_uar_without_preload_content(
_headers: Optional[Dict[StrictStr, Any]] = None,
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
) -> RESTResponseType:
- """create_uar
+ """(Deprecated) create_uar
- Starts a User Access Review.
+ Starts a User Access Review. Deprecated in favor of `POST /campaigns`.
:param create_uar_info: The settings of the UAR. (required)
:type create_uar_info: CreateUARInfo
@@ -221,6 +223,7 @@ def create_uar_without_preload_content(
:type _host_index: int, optional
:return: Returns the result object.
""" # noqa: E501
+ warnings.warn("POST /uar is deprecated.", DeprecationWarning)
_param = self._create_uar_serialize(
create_uar_info=create_uar_info,
@@ -334,9 +337,9 @@ def get_uar(
_headers: Optional[Dict[StrictStr, Any]] = None,
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
) -> UAR:
- """get_uar
+ """(Deprecated) get_uar
- Retrieves a specific UAR.
+ Retrieves a specific UAR. Deprecated in favor of `GET /campaigns/{campaign_id}`.
:param uar_id: The ID of the UAR. (required)
:type uar_id: UUID
@@ -361,6 +364,7 @@ def get_uar(
:type _host_index: int, optional
:return: Returns the result object.
""" # noqa: E501
+ warnings.warn("GET /uar/{uar_id} is deprecated.", DeprecationWarning)
_param = self._get_uar_serialize(
uar_id=uar_id,
@@ -401,9 +405,9 @@ def get_uar_with_http_info(
_headers: Optional[Dict[StrictStr, Any]] = None,
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
) -> ApiResponse[UAR]:
- """get_uar
+ """(Deprecated) get_uar
- Retrieves a specific UAR.
+ Retrieves a specific UAR. Deprecated in favor of `GET /campaigns/{campaign_id}`.
:param uar_id: The ID of the UAR. (required)
:type uar_id: UUID
@@ -428,6 +432,7 @@ def get_uar_with_http_info(
:type _host_index: int, optional
:return: Returns the result object.
""" # noqa: E501
+ warnings.warn("GET /uar/{uar_id} is deprecated.", DeprecationWarning)
_param = self._get_uar_serialize(
uar_id=uar_id,
@@ -468,9 +473,9 @@ def get_uar_without_preload_content(
_headers: Optional[Dict[StrictStr, Any]] = None,
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
) -> RESTResponseType:
- """get_uar
+ """(Deprecated) get_uar
- Retrieves a specific UAR.
+ Retrieves a specific UAR. Deprecated in favor of `GET /campaigns/{campaign_id}`.
:param uar_id: The ID of the UAR. (required)
:type uar_id: UUID
@@ -495,6 +500,7 @@ def get_uar_without_preload_content(
:type _host_index: int, optional
:return: Returns the result object.
""" # noqa: E501
+ warnings.warn("GET /uar/{uar_id} is deprecated.", DeprecationWarning)
_param = self._get_uar_serialize(
uar_id=uar_id,
@@ -596,9 +602,9 @@ def get_uars(
_headers: Optional[Dict[StrictStr, Any]] = None,
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
) -> PaginatedUARsList:
- """get_uars
+ """(Deprecated) get_uars
- Returns a list of `UAR` objects.
+ Returns a list of `UAR` objects. Deprecated in favor of `GET /campaigns`.
:param cursor: The pagination cursor value.
:type cursor: str
@@ -625,6 +631,7 @@ def get_uars(
:type _host_index: int, optional
:return: Returns the result object.
""" # noqa: E501
+ warnings.warn("GET /uars is deprecated.", DeprecationWarning)
_param = self._get_uars_serialize(
cursor=cursor,
@@ -667,9 +674,9 @@ def get_uars_with_http_info(
_headers: Optional[Dict[StrictStr, Any]] = None,
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
) -> ApiResponse[PaginatedUARsList]:
- """get_uars
+ """(Deprecated) get_uars
- Returns a list of `UAR` objects.
+ Returns a list of `UAR` objects. Deprecated in favor of `GET /campaigns`.
:param cursor: The pagination cursor value.
:type cursor: str
@@ -696,6 +703,7 @@ def get_uars_with_http_info(
:type _host_index: int, optional
:return: Returns the result object.
""" # noqa: E501
+ warnings.warn("GET /uars is deprecated.", DeprecationWarning)
_param = self._get_uars_serialize(
cursor=cursor,
@@ -738,9 +746,9 @@ def get_uars_without_preload_content(
_headers: Optional[Dict[StrictStr, Any]] = None,
_host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
) -> RESTResponseType:
- """get_uars
+ """(Deprecated) get_uars
- Returns a list of `UAR` objects.
+ Returns a list of `UAR` objects. Deprecated in favor of `GET /campaigns`.
:param cursor: The pagination cursor value.
:type cursor: str
@@ -767,6 +775,7 @@ def get_uars_without_preload_content(
:type _host_index: int, optional
:return: Returns the result object.
""" # noqa: E501
+ warnings.warn("GET /uars is deprecated.", DeprecationWarning)
_param = self._get_uars_serialize(
cursor=cursor,
diff --git a/opal_security/api/users_api.py b/opal_security/api/users_api.py
index 9a27db4..a76b109 100644
--- a/opal_security/api/users_api.py
+++ b/opal_security/api/users_api.py
@@ -640,6 +640,252 @@ def _get_user_tags_serialize(
+ @validate_call
+ def get_user_whoami(
+ self,
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> User:
+ """get_user_whoami
+
+ Returns the user that the provided API token authenticates as.
+
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._get_user_whoami_serialize(
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "User",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ ).data
+
+
+ @validate_call
+ def get_user_whoami_with_http_info(
+ self,
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> ApiResponse[User]:
+ """get_user_whoami
+
+ Returns the user that the provided API token authenticates as.
+
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._get_user_whoami_serialize(
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "User",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ response_data.read()
+ return self.api_client.response_deserialize(
+ response_data=response_data,
+ response_types_map=_response_types_map,
+ )
+
+
+ @validate_call
+ def get_user_whoami_without_preload_content(
+ self,
+ _request_timeout: Union[
+ None,
+ Annotated[StrictFloat, Field(gt=0)],
+ Tuple[
+ Annotated[StrictFloat, Field(gt=0)],
+ Annotated[StrictFloat, Field(gt=0)]
+ ]
+ ] = None,
+ _request_auth: Optional[Dict[StrictStr, Any]] = None,
+ _content_type: Optional[StrictStr] = None,
+ _headers: Optional[Dict[StrictStr, Any]] = None,
+ _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0,
+ ) -> RESTResponseType:
+ """get_user_whoami
+
+ Returns the user that the provided API token authenticates as.
+
+ :param _request_timeout: timeout setting for this request. If one
+ number provided, it will be total request
+ timeout. It can also be a pair (tuple) of
+ (connection, read) timeouts.
+ :type _request_timeout: int, tuple(int, int), optional
+ :param _request_auth: set to override the auth_settings for an a single
+ request; this effectively ignores the
+ authentication in the spec for a single request.
+ :type _request_auth: dict, optional
+ :param _content_type: force content-type for the request.
+ :type _content_type: str, Optional
+ :param _headers: set to override the headers for a single
+ request; this effectively ignores the headers
+ in the spec for a single request.
+ :type _headers: dict, optional
+ :param _host_index: set to override the host_index for a single
+ request; this effectively ignores the host_index
+ in the spec for a single request.
+ :type _host_index: int, optional
+ :return: Returns the result object.
+ """ # noqa: E501
+
+ _param = self._get_user_whoami_serialize(
+ _request_auth=_request_auth,
+ _content_type=_content_type,
+ _headers=_headers,
+ _host_index=_host_index
+ )
+
+ _response_types_map: Dict[str, Optional[str]] = {
+ '200': "User",
+ }
+ response_data = self.api_client.call_api(
+ *_param,
+ _request_timeout=_request_timeout
+ )
+ return response_data.response
+
+
+ def _get_user_whoami_serialize(
+ self,
+ _request_auth,
+ _content_type,
+ _headers,
+ _host_index,
+ ) -> RequestSerialized:
+
+ _host = None
+
+ _collection_formats: Dict[str, str] = {
+ }
+
+ _path_params: Dict[str, str] = {}
+ _query_params: List[Tuple[str, str]] = []
+ _header_params: Dict[str, Optional[str]] = _headers or {}
+ _form_params: List[Tuple[str, str]] = []
+ _files: Dict[
+ str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]]
+ ] = {}
+ _body_params: Optional[bytes] = None
+
+ # process the path parameters
+ # process the query parameters
+ # process the header parameters
+ # process the form parameters
+ # process the body parameter
+
+
+ # set the HTTP header `Accept`
+ if 'Accept' not in _header_params:
+ _header_params['Accept'] = self.api_client.select_header_accept(
+ [
+ 'application/json'
+ ]
+ )
+
+
+ # authentication setting
+ _auth_settings: List[str] = [
+ 'BearerAuth'
+ ]
+
+ return self.api_client.param_serialize(
+ method='GET',
+ resource_path='/users/whoami',
+ path_params=_path_params,
+ query_params=_query_params,
+ header_params=_header_params,
+ body=_body_params,
+ post_params=_form_params,
+ files=_files,
+ auth_settings=_auth_settings,
+ collection_formats=_collection_formats,
+ _host=_host,
+ _request_auth=_request_auth
+ )
+
+
+
+
@validate_call
def get_users(
self,
diff --git a/opal_security/models/__init__.py b/opal_security/models/__init__.py
index e39bbb8..d4ace63 100644
--- a/opal_security/models/__init__.py
+++ b/opal_security/models/__init__.py
@@ -39,9 +39,16 @@
from opal_security.models.bundle import Bundle
from opal_security.models.bundle_group import BundleGroup
from opal_security.models.bundle_resource import BundleResource
+from opal_security.models.campaign import Campaign
+from opal_security.models.campaign_configuration import CampaignConfiguration
+from opal_security.models.campaign_group_asset_visibility_policy_enum import CampaignGroupAssetVisibilityPolicyEnum
+from opal_security.models.campaign_revoke_on_enum import CampaignRevokeOnEnum
+from opal_security.models.campaign_status_enum import CampaignStatusEnum
from opal_security.models.condition import Condition
from opal_security.models.configuration_template import ConfigurationTemplate
from opal_security.models.create_bundle_info import CreateBundleInfo
+from opal_security.models.create_campaign_configuration_info import CreateCampaignConfigurationInfo
+from opal_security.models.create_campaign_info import CreateCampaignInfo
from opal_security.models.create_configuration_template_info import CreateConfigurationTemplateInfo
from opal_security.models.create_delegation_request import CreateDelegationRequest
from opal_security.models.create_event_stream_info import CreateEventStreamInfo
@@ -65,6 +72,7 @@
from opal_security.models.create_uar_info import CreateUARInfo
from opal_security.models.delegation import Delegation
from opal_security.models.deny_request_request import DenyRequestRequest
+from opal_security.models.entity_admin_filter import EntityAdminFilter
from opal_security.models.entity_item_type_enum import EntityItemTypeEnum
from opal_security.models.entity_name_filter import EntityNameFilter
from opal_security.models.entity_tag_filter import EntityTagFilter
@@ -105,6 +113,7 @@
from opal_security.models.group_remote_info_rootly_on_call_schedule import GroupRemoteInfoRootlyOnCallSchedule
from opal_security.models.group_remote_info_slack_user_group import GroupRemoteInfoSlackUserGroup
from opal_security.models.group_remote_info_snowflake_role import GroupRemoteInfoSnowflakeRole
+from opal_security.models.group_remote_info_tableau_group import GroupRemoteInfoTableauGroup
from opal_security.models.group_remote_info_tailscale_group import GroupRemoteInfoTailscaleGroup
from opal_security.models.group_remote_info_twingate_group import GroupRemoteInfoTwingateGroup
from opal_security.models.group_remote_info_twingate_group_synced import GroupRemoteInfoTwingateGroupSynced
@@ -119,6 +128,7 @@
from opal_security.models.group_with_access_level import GroupWithAccessLevel
from opal_security.models.idp_group_mapping import IdpGroupMapping
from opal_security.models.idp_group_mapping_list import IdpGroupMappingList
+from opal_security.models.idp_status_filter import IdpStatusFilter
from opal_security.models.message_channel import MessageChannel
from opal_security.models.message_channel_id_list import MessageChannelIDList
from opal_security.models.message_channel_list import MessageChannelList
@@ -127,11 +137,18 @@
from opal_security.models.on_call_schedule_id_list import OnCallScheduleIDList
from opal_security.models.on_call_schedule_list import OnCallScheduleList
from opal_security.models.on_call_schedule_provider_enum import OnCallScheduleProviderEnum
+from opal_security.models.opal_access_path_edge_filter import OpalAccessPathEdgeFilter
+from opal_security.models.opal_access_path_query import OpalAccessPathQuery
+from opal_security.models.opal_access_path_query_body import OpalAccessPathQueryBody
+from opal_security.models.opal_access_path_query_results import OpalAccessPathQueryResults
+from opal_security.models.opal_access_path_result_edge import OpalAccessPathResultEdge
+from opal_security.models.opal_access_path_result_node import OpalAccessPathResultNode
from opal_security.models.opal_node_query import OpalNodeQuery
from opal_security.models.opal_node_query_body import OpalNodeQueryBody
from opal_security.models.opal_node_query_results import OpalNodeQueryResults
from opal_security.models.opal_query_result_edge import OpalQueryResultEdge
from opal_security.models.opal_query_result_node import OpalQueryResultNode
+from opal_security.models.opal_query_results import OpalQueryResults
from opal_security.models.owner import Owner
from opal_security.models.page_info import PageInfo
from opal_security.models.paginated_access_rules_list import PaginatedAccessRulesList
@@ -139,6 +156,7 @@
from opal_security.models.paginated_bundle_group_list import PaginatedBundleGroupList
from opal_security.models.paginated_bundle_list import PaginatedBundleList
from opal_security.models.paginated_bundle_resource_list import PaginatedBundleResourceList
+from opal_security.models.paginated_campaigns_list import PaginatedCampaignsList
from opal_security.models.paginated_configuration_template_list import PaginatedConfigurationTemplateList
from opal_security.models.paginated_delegations_list import PaginatedDelegationsList
from opal_security.models.paginated_event_list import PaginatedEventList
@@ -151,6 +169,8 @@
from opal_security.models.paginated_tokens_list import PaginatedTokensList
from opal_security.models.paginated_uars_list import PaginatedUARsList
from opal_security.models.paginated_users_list import PaginatedUsersList
+from opal_security.models.paladin import Paladin
+from opal_security.models.paladin_list import PaladinList
from opal_security.models.propagation_status import PropagationStatus
from opal_security.models.propagation_status_enum import PropagationStatusEnum
from opal_security.models.rds_engine_enum import RDSEngineEnum
@@ -178,6 +198,8 @@
from opal_security.models.resource_access_user_list import ResourceAccessUserList
from opal_security.models.resource_nhi import ResourceNHI
from opal_security.models.resource_remote_info import ResourceRemoteInfo
+from opal_security.models.resource_remote_info_alicloud_ecs_instance import ResourceRemoteInfoAlicloudEcsInstance
+from opal_security.models.resource_remote_info_alicloud_ram_role import ResourceRemoteInfoAlicloudRamRole
from opal_security.models.resource_remote_info_anthropic_workspace import ResourceRemoteInfoAnthropicWorkspace
from opal_security.models.resource_remote_info_aws_account import ResourceRemoteInfoAwsAccount
from opal_security.models.resource_remote_info_aws_ec2_instance import ResourceRemoteInfoAwsEc2Instance
@@ -265,10 +287,12 @@
from opal_security.models.rule_clauses import RuleClauses
from opal_security.models.rule_conjunction import RuleConjunction
from opal_security.models.rule_disjunction import RuleDisjunction
+from opal_security.models.run_opal_query_request import RunOpalQueryRequest
from opal_security.models.scoped_role_permission import ScopedRolePermission
from opal_security.models.scoped_role_permission_list import ScopedRolePermissionList
from opal_security.models.session import Session
from opal_security.models.sessions_list import SessionsList
+from opal_security.models.stop_campaign_request import StopCampaignRequest
from opal_security.models.string_match_type import StringMatchType
from opal_security.models.sub_event import SubEvent
from opal_security.models.sync_error import SyncError
@@ -286,6 +310,8 @@
from opal_security.models.uar_reviewer_assignment_policy_enum import UARReviewerAssignmentPolicyEnum
from opal_security.models.uar_scope import UARScope
from opal_security.models.update_access_rule_info import UpdateAccessRuleInfo
+from opal_security.models.update_campaign_configuration_info import UpdateCampaignConfigurationInfo
+from opal_security.models.update_campaign_info import UpdateCampaignInfo
from opal_security.models.update_configuration_template_info import UpdateConfigurationTemplateInfo
from opal_security.models.update_event_stream_info import UpdateEventStreamInfo
from opal_security.models.update_group_binding_info import UpdateGroupBindingInfo
diff --git a/opal_security/models/access_entity_filters.py b/opal_security/models/access_entity_filters.py
index 95f78e5..5402e05 100644
--- a/opal_security/models/access_entity_filters.py
+++ b/opal_security/models/access_entity_filters.py
@@ -21,9 +21,11 @@
from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator
from typing import Any, ClassVar, Dict, List, Optional
from uuid import UUID
+from opal_security.models.entity_admin_filter import EntityAdminFilter
from opal_security.models.entity_item_type_enum import EntityItemTypeEnum
from opal_security.models.entity_name_filter import EntityNameFilter
from opal_security.models.entity_tag_filter import EntityTagFilter
+from opal_security.models.idp_status_filter import IdpStatusFilter
from typing import Optional, Set
from typing_extensions import Self
@@ -35,6 +37,8 @@ class AccessEntityFilters(BaseModel):
entity_item_types: Optional[List[EntityItemTypeEnum]] = Field(default=None, description="Filter by entity item types.", alias="entityItemTypes")
entity_name: Optional[EntityNameFilter] = Field(default=None, alias="entityName")
entity_tag: Optional[EntityTagFilter] = Field(default=None, alias="entityTag")
+ hr_idp_status: Optional[IdpStatusFilter] = Field(default=None, alias="hrIdpStatus")
+ entity_admin_owner: Optional[EntityAdminFilter] = Field(default=None, alias="entityAdminOwner")
entity_ids: Optional[List[UUID]] = Field(default=None, description="Filter by specific entity UUIDs.", alias="entityIDs")
imported_from_app: Optional[List[UUID]] = Field(default=None, description="Filter by app IDs from which returned nodes will be imported from.", alias="importedFromApp")
role_remote_ids: Optional[List[StrictStr]] = Field(default=None, description="Filter by role remote IDs. Can only be applied within a hasAccessTo clause.", alias="roleRemoteIds")
@@ -43,7 +47,7 @@ class AccessEntityFilters(BaseModel):
any_of: Optional[List[AccessEntityFilters]] = Field(default=None, description="A list of nested filters where at least one must match (logical OR). Each item has the same shape as this object. ", alias="anyOf")
var_not: Optional[Dict[str, Any]] = Field(default=None, description="Excludes entities matching the embedded filter (logical NOT). Pass a filter object with the same shape as this one — typically a single scalar field, like `{not: {entityTypes: [\"RESOURCE\"]}}` to exclude resources. ", alias="not")
additional_properties: Dict[str, Any] = {}
- __properties: ClassVar[List[str]] = ["entityTypes", "entityItemTypes", "entityName", "entityTag", "entityIDs", "importedFromApp", "roleRemoteIds", "roleNames", "allOf", "anyOf", "not"]
+ __properties: ClassVar[List[str]] = ["entityTypes", "entityItemTypes", "entityName", "entityTag", "hrIdpStatus", "entityAdminOwner", "entityIDs", "importedFromApp", "roleRemoteIds", "roleNames", "allOf", "anyOf", "not"]
@field_validator('entity_types')
def entity_types_validate_enum(cls, value):
@@ -103,6 +107,12 @@ def to_dict(self) -> Dict[str, Any]:
# override the default output from pydantic by calling `to_dict()` of entity_tag
if self.entity_tag:
_dict['entityTag'] = self.entity_tag.to_dict()
+ # override the default output from pydantic by calling `to_dict()` of hr_idp_status
+ if self.hr_idp_status:
+ _dict['hrIdpStatus'] = self.hr_idp_status.to_dict()
+ # override the default output from pydantic by calling `to_dict()` of entity_admin_owner
+ if self.entity_admin_owner:
+ _dict['entityAdminOwner'] = self.entity_admin_owner.to_dict()
# override the default output from pydantic by calling `to_dict()` of each item in all_of (list)
_items = []
if self.all_of:
@@ -138,6 +148,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"entityItemTypes": obj.get("entityItemTypes"),
"entityName": EntityNameFilter.from_dict(obj["entityName"]) if obj.get("entityName") is not None else None,
"entityTag": EntityTagFilter.from_dict(obj["entityTag"]) if obj.get("entityTag") is not None else None,
+ "hrIdpStatus": IdpStatusFilter.from_dict(obj["hrIdpStatus"]) if obj.get("hrIdpStatus") is not None else None,
+ "entityAdminOwner": EntityAdminFilter.from_dict(obj["entityAdminOwner"]) if obj.get("entityAdminOwner") is not None else None,
"entityIDs": obj.get("entityIDs"),
"importedFromApp": obj.get("importedFromApp"),
"roleRemoteIds": obj.get("roleRemoteIds"),
diff --git a/opal_security/models/app_type_enum.py b/opal_security/models/app_type_enum.py
index 7031cd2..fcd0708 100644
--- a/opal_security/models/app_type_enum.py
+++ b/opal_security/models/app_type_enum.py
@@ -39,6 +39,7 @@ class AppTypeEnum(str, Enum):
CUSTOM_CONNECTOR = 'CUSTOM_CONNECTOR'
DATABRICKS = 'DATABRICKS'
DATASTAX_ASTRA = 'DATASTAX_ASTRA'
+ ALICLOUD = 'ALICLOUD'
DEVIN = 'DEVIN'
DUO = 'DUO'
GCP = 'GCP'
@@ -68,6 +69,7 @@ class AppTypeEnum(str, Enum):
SALESFORCE = 'SALESFORCE'
SNOWFLAKE = 'SNOWFLAKE'
SLACK = 'SLACK'
+ TABLEAU = 'TABLEAU'
TAILSCALE = 'TAILSCALE'
TELEPORT = 'TELEPORT'
TWINGATE = 'TWINGATE'
diff --git a/opal_security/models/campaign.py b/opal_security/models/campaign.py
new file mode 100644
index 0000000..6052422
--- /dev/null
+++ b/opal_security/models/campaign.py
@@ -0,0 +1,134 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from datetime import datetime
+from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr
+from typing import Any, ClassVar, Dict, List, Optional
+from uuid import UUID
+from opal_security.models.campaign_configuration import CampaignConfiguration
+from opal_security.models.campaign_status_enum import CampaignStatusEnum
+from typing import Optional, Set
+from typing_extensions import Self
+
+class Campaign(BaseModel):
+ """
+ An access review campaign.
+ """ # noqa: E501
+ campaign_id: UUID = Field(description="The ID of the campaign.")
+ name: StrictStr = Field(description="The name of the campaign.")
+ status: CampaignStatusEnum
+ is_template: StrictBool = Field(description="Whether this campaign is a recurring schedule template. Templates spawn draft campaigns on schedule rather than being reviewed directly.")
+ created_at: datetime = Field(description="The creation time of the campaign.")
+ updated_at: datetime = Field(description="The last updated time of the campaign.")
+ created_by_user_id: UUID = Field(description="The ID of the user who created the campaign.")
+ configuration: Optional[CampaignConfiguration] = Field(default=None, description="The campaign's configuration, if set.")
+ started_at: Optional[datetime] = Field(default=None, description="The time the campaign was started, if started.")
+ started_by_user_id: Optional[UUID] = Field(default=None, description="The ID of the user who started the campaign, if started.")
+ stopped_at: Optional[datetime] = Field(default=None, description="The time the campaign was manually stopped, if stopped.")
+ stopped_by_user_id: Optional[UUID] = Field(default=None, description="The ID of the user who stopped the campaign, if stopped.")
+ ended_at: Optional[datetime] = Field(default=None, description="The time the campaign reached its scheduled end, if ended.")
+ ended_by_user_id: Optional[UUID] = Field(default=None, description="The ID of the user who ended the campaign, if ended.")
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["campaign_id", "name", "status", "is_template", "created_at", "updated_at", "created_by_user_id", "configuration", "started_at", "started_by_user_id", "stopped_at", "stopped_by_user_id", "ended_at", "ended_by_user_id"]
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of Campaign from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # override the default output from pydantic by calling `to_dict()` of configuration
+ if self.configuration:
+ _dict['configuration'] = self.configuration.to_dict()
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of Campaign from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "campaign_id": obj.get("campaign_id"),
+ "name": obj.get("name"),
+ "status": obj.get("status"),
+ "is_template": obj.get("is_template"),
+ "created_at": obj.get("created_at"),
+ "updated_at": obj.get("updated_at"),
+ "created_by_user_id": obj.get("created_by_user_id"),
+ "configuration": CampaignConfiguration.from_dict(obj["configuration"]) if obj.get("configuration") is not None else None,
+ "started_at": obj.get("started_at"),
+ "started_by_user_id": obj.get("started_by_user_id"),
+ "stopped_at": obj.get("stopped_at"),
+ "stopped_by_user_id": obj.get("stopped_by_user_id"),
+ "ended_at": obj.get("ended_at"),
+ "ended_by_user_id": obj.get("ended_by_user_id")
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/campaign_configuration.py b/opal_security/models/campaign_configuration.py
new file mode 100644
index 0000000..11a319b
--- /dev/null
+++ b/opal_security/models/campaign_configuration.py
@@ -0,0 +1,154 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from datetime import datetime
+from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr
+from typing import Any, ClassVar, Dict, List, Optional
+from uuid import UUID
+from opal_security.models.campaign_group_asset_visibility_policy_enum import CampaignGroupAssetVisibilityPolicyEnum
+from opal_security.models.campaign_revoke_on_enum import CampaignRevokeOnEnum
+from opal_security.models.opal_access_path_query_body import OpalAccessPathQueryBody
+from opal_security.models.uar_reviewer_assignment_policy_enum import UARReviewerAssignmentPolicyEnum
+from typing import Optional, Set
+from typing_extensions import Self
+
+class CampaignConfiguration(BaseModel):
+ """
+ Configuration for an access review campaign.
+ """ # noqa: E501
+ configuration_id: UUID = Field(description="The ID of the campaign configuration.")
+ created_at: datetime = Field(description="The creation time of the configuration.")
+ updated_at: datetime = Field(description="The last updated time of the configuration.")
+ query: Optional[OpalAccessPathQueryBody] = Field(default=None, description="Access-path query defining the scope of access to review. Uses the same principalFilter / entitlementFilter shape as ACCESS_PATH OpalQuery.")
+ reviewer_assignment_policy: UARReviewerAssignmentPolicyEnum
+ allow_self_review: StrictBool = Field(description="Whether reviewers can review their own access.")
+ send_reviewer_assignment_notification: StrictBool = Field(description="Whether to notify reviewers upon assignment.")
+ allow_reviewer_reassignment: StrictBool = Field(description="Whether reviewers may reassign their reviews to another user.")
+ start_date: Optional[datetime] = Field(default=None, description="Scheduled start date of the campaign.")
+ end_date: Optional[datetime] = Field(default=None, description="Scheduled end date of the campaign.")
+ timezone: StrictStr = Field(description="IANA timezone used to interpret campaign deadlines (e.g. America/Los_Angeles).")
+ revoke_on: CampaignRevokeOnEnum
+ reminder_schedule: Optional[List[StrictInt]] = Field(default=None, description="Days before end date to send reminder notifications.")
+ reminder_include_manager: StrictBool = Field(description="Whether to include the reviewer's manager in reminders.")
+ require_reason_on_denial: StrictBool = Field(description="Whether reviewers must provide a reason when denying (revoking) access.")
+ hide_ai_suggestions: StrictBool = Field(description="Whether AI suggestions are hidden from reviewers.")
+ custom_start_message: Optional[StrictStr] = Field(default=None, description="Optional custom message included when notifying reviewers that the campaign started.")
+ group_asset_visibility_policy: CampaignGroupAssetVisibilityPolicyEnum
+ is_template: StrictBool = Field(description="Whether this configuration is a recurring schedule template.")
+ cron_expression: Optional[StrictStr] = Field(default=None, description="Cron expression driving the recurring schedule. Null for one-off campaigns.")
+ next_scheduled_run: Optional[datetime] = Field(default=None, description="Next time a draft will be generated from this template.")
+ last_scheduled_run: Optional[datetime] = Field(default=None, description="Most recent time a draft was generated from this template.")
+ recurring_duration_days: Optional[StrictInt] = Field(default=None, description="Deadline window in days applied to each draft generated from this template.")
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["configuration_id", "created_at", "updated_at", "query", "reviewer_assignment_policy", "allow_self_review", "send_reviewer_assignment_notification", "allow_reviewer_reassignment", "start_date", "end_date", "timezone", "revoke_on", "reminder_schedule", "reminder_include_manager", "require_reason_on_denial", "hide_ai_suggestions", "custom_start_message", "group_asset_visibility_policy", "is_template", "cron_expression", "next_scheduled_run", "last_scheduled_run", "recurring_duration_days"]
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of CampaignConfiguration from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # override the default output from pydantic by calling `to_dict()` of query
+ if self.query:
+ _dict['query'] = self.query.to_dict()
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of CampaignConfiguration from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "configuration_id": obj.get("configuration_id"),
+ "created_at": obj.get("created_at"),
+ "updated_at": obj.get("updated_at"),
+ "query": OpalAccessPathQueryBody.from_dict(obj["query"]) if obj.get("query") is not None else None,
+ "reviewer_assignment_policy": obj.get("reviewer_assignment_policy"),
+ "allow_self_review": obj.get("allow_self_review"),
+ "send_reviewer_assignment_notification": obj.get("send_reviewer_assignment_notification"),
+ "allow_reviewer_reassignment": obj.get("allow_reviewer_reassignment"),
+ "start_date": obj.get("start_date"),
+ "end_date": obj.get("end_date"),
+ "timezone": obj.get("timezone"),
+ "revoke_on": obj.get("revoke_on"),
+ "reminder_schedule": obj.get("reminder_schedule"),
+ "reminder_include_manager": obj.get("reminder_include_manager"),
+ "require_reason_on_denial": obj.get("require_reason_on_denial"),
+ "hide_ai_suggestions": obj.get("hide_ai_suggestions"),
+ "custom_start_message": obj.get("custom_start_message"),
+ "group_asset_visibility_policy": obj.get("group_asset_visibility_policy"),
+ "is_template": obj.get("is_template"),
+ "cron_expression": obj.get("cron_expression"),
+ "next_scheduled_run": obj.get("next_scheduled_run"),
+ "last_scheduled_run": obj.get("last_scheduled_run"),
+ "recurring_duration_days": obj.get("recurring_duration_days")
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/campaign_group_asset_visibility_policy_enum.py b/opal_security/models/campaign_group_asset_visibility_policy_enum.py
new file mode 100644
index 0000000..68deed0
--- /dev/null
+++ b/opal_security/models/campaign_group_asset_visibility_policy_enum.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import json
+from enum import Enum
+from typing_extensions import Self
+
+
+class CampaignGroupAssetVisibilityPolicyEnum(str, Enum):
+ """
+ Controls what group assets reviewers can see during the campaign.
+ """
+
+ """
+ allowed enum values
+ """
+ STRICT = 'STRICT'
+ VIEW_VISIBLE_AND_ASSIGNED = 'VIEW_VISIBLE_AND_ASSIGNED'
+ VIEW_ALL = 'VIEW_ALL'
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Self:
+ """Create an instance of CampaignGroupAssetVisibilityPolicyEnum from a JSON string"""
+ return cls(json.loads(json_str))
+
+
diff --git a/opal_security/models/campaign_revoke_on_enum.py b/opal_security/models/campaign_revoke_on_enum.py
new file mode 100644
index 0000000..0c9273c
--- /dev/null
+++ b/opal_security/models/campaign_revoke_on_enum.py
@@ -0,0 +1,39 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import json
+from enum import Enum
+from typing_extensions import Self
+
+
+class CampaignRevokeOnEnum(str, Enum):
+ """
+ When access decisions take effect during a campaign.
+ """
+
+ """
+ allowed enum values
+ """
+ ACTION = 'ACTION'
+ END = 'END'
+ NONE = 'NONE'
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Self:
+ """Create an instance of CampaignRevokeOnEnum from a JSON string"""
+ return cls(json.loads(json_str))
+
+
diff --git a/opal_security/models/campaign_status_enum.py b/opal_security/models/campaign_status_enum.py
new file mode 100644
index 0000000..c3ce7a6
--- /dev/null
+++ b/opal_security/models/campaign_status_enum.py
@@ -0,0 +1,41 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import json
+from enum import Enum
+from typing_extensions import Self
+
+
+class CampaignStatusEnum(str, Enum):
+ """
+ The current status of a campaign.
+ """
+
+ """
+ allowed enum values
+ """
+ DRAFT = 'DRAFT'
+ ONGOING = 'ONGOING'
+ COMPLETED = 'COMPLETED'
+ STOPPED = 'STOPPED'
+ ENDED = 'ENDED'
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Self:
+ """Create an instance of CampaignStatusEnum from a JSON string"""
+ return cls(json.loads(json_str))
+
+
diff --git a/opal_security/models/create_campaign_configuration_info.py b/opal_security/models/create_campaign_configuration_info.py
new file mode 100644
index 0000000..1530dd9
--- /dev/null
+++ b/opal_security/models/create_campaign_configuration_info.py
@@ -0,0 +1,146 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from datetime import datetime
+from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr
+from typing import Any, ClassVar, Dict, List, Optional
+from uuid import UUID
+from opal_security.models.campaign_group_asset_visibility_policy_enum import CampaignGroupAssetVisibilityPolicyEnum
+from opal_security.models.campaign_revoke_on_enum import CampaignRevokeOnEnum
+from opal_security.models.opal_access_path_query_body import OpalAccessPathQueryBody
+from opal_security.models.uar_reviewer_assignment_policy_enum import UARReviewerAssignmentPolicyEnum
+from typing import Optional, Set
+from typing_extensions import Self
+
+class CreateCampaignConfigurationInfo(BaseModel):
+ """
+ Configuration to apply when creating a campaign. `query` is required; other omitted fields use defaults.
+ """ # noqa: E501
+ query: OpalAccessPathQueryBody = Field(description="Access-path query defining the scope of access to review. Required. Uses the same principalFilter / entitlementFilter shape as ACCESS_PATH OpalQuery. Must include at least one of principalFilter or entitlementFilter. Campaign scope only supports direct access edges: `edgeFilter.directOnly` defaults to `true`, is always stored as `true`, and passing `false` returns 400. ")
+ reviewer_assignment_policy: Optional[UARReviewerAssignmentPolicyEnum] = None
+ allow_self_review: Optional[StrictBool] = Field(default=None, description="Whether reviewers can review their own access.")
+ send_reviewer_assignment_notification: Optional[StrictBool] = Field(default=None, description="Whether to notify reviewers upon assignment.")
+ allow_reviewer_reassignment: Optional[StrictBool] = Field(default=None, description="Whether reviewers may reassign their reviews to another user.")
+ start_date: Optional[datetime] = Field(default=None, description="Scheduled start date of the campaign.")
+ end_date: Optional[datetime] = Field(default=None, description="Scheduled end date of the campaign.")
+ timezone: Optional[StrictStr] = Field(default=None, description="IANA timezone used to interpret campaign deadlines (e.g. America/Los_Angeles).")
+ revoke_on: Optional[CampaignRevokeOnEnum] = None
+ reminder_schedule: Optional[List[StrictInt]] = Field(default=None, description="Days before end date to send reminder notifications.")
+ reminder_include_manager: Optional[StrictBool] = Field(default=None, description="Whether to include the reviewer's manager in reminders.")
+ require_reason_on_denial: Optional[StrictBool] = Field(default=None, description="Whether reviewers must provide a reason when denying (revoking) access.")
+ hide_ai_suggestions: Optional[StrictBool] = Field(default=None, description="Whether AI suggestions are hidden from reviewers.")
+ custom_start_message: Optional[StrictStr] = Field(default=None, description="Optional custom message included when notifying reviewers that the campaign started.")
+ group_asset_visibility_policy: Optional[CampaignGroupAssetVisibilityPolicyEnum] = None
+ is_template: Optional[StrictBool] = Field(default=None, description="Whether this configuration is a recurring schedule template.")
+ cron_expression: Optional[StrictStr] = Field(default=None, description="Cron expression driving the recurring schedule. Null for one-off campaigns.")
+ recurring_duration_days: Optional[StrictInt] = Field(default=None, description="Deadline window in days applied to each draft generated from this template.")
+ excluded_role_assignment_ids: Optional[List[UUID]] = Field(default=None, description="Role assignment IDs to exclude from the campaign scope during population.")
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["query", "reviewer_assignment_policy", "allow_self_review", "send_reviewer_assignment_notification", "allow_reviewer_reassignment", "start_date", "end_date", "timezone", "revoke_on", "reminder_schedule", "reminder_include_manager", "require_reason_on_denial", "hide_ai_suggestions", "custom_start_message", "group_asset_visibility_policy", "is_template", "cron_expression", "recurring_duration_days", "excluded_role_assignment_ids"]
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of CreateCampaignConfigurationInfo from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # override the default output from pydantic by calling `to_dict()` of query
+ if self.query:
+ _dict['query'] = self.query.to_dict()
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of CreateCampaignConfigurationInfo from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "query": OpalAccessPathQueryBody.from_dict(obj["query"]) if obj.get("query") is not None else None,
+ "reviewer_assignment_policy": obj.get("reviewer_assignment_policy"),
+ "allow_self_review": obj.get("allow_self_review"),
+ "send_reviewer_assignment_notification": obj.get("send_reviewer_assignment_notification"),
+ "allow_reviewer_reassignment": obj.get("allow_reviewer_reassignment"),
+ "start_date": obj.get("start_date"),
+ "end_date": obj.get("end_date"),
+ "timezone": obj.get("timezone"),
+ "revoke_on": obj.get("revoke_on"),
+ "reminder_schedule": obj.get("reminder_schedule"),
+ "reminder_include_manager": obj.get("reminder_include_manager"),
+ "require_reason_on_denial": obj.get("require_reason_on_denial"),
+ "hide_ai_suggestions": obj.get("hide_ai_suggestions"),
+ "custom_start_message": obj.get("custom_start_message"),
+ "group_asset_visibility_policy": obj.get("group_asset_visibility_policy"),
+ "is_template": obj.get("is_template"),
+ "cron_expression": obj.get("cron_expression"),
+ "recurring_duration_days": obj.get("recurring_duration_days"),
+ "excluded_role_assignment_ids": obj.get("excluded_role_assignment_ids")
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/create_campaign_info.py b/opal_security/models/create_campaign_info.py
new file mode 100644
index 0000000..ac3bc43
--- /dev/null
+++ b/opal_security/models/create_campaign_info.py
@@ -0,0 +1,107 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing import Any, ClassVar, Dict, List
+from opal_security.models.create_campaign_configuration_info import CreateCampaignConfigurationInfo
+from typing import Optional, Set
+from typing_extensions import Self
+
+class CreateCampaignInfo(BaseModel):
+ """
+ # CreateCampaignInfo Object ### Description The `CreateCampaignInfo` object is used to create a campaign. ### Usage Example Use in the `POST Campaigns` endpoint.
+ """ # noqa: E501
+ name: StrictStr = Field(description="The name of the campaign.")
+ configuration: CreateCampaignConfigurationInfo = Field(description="Configuration for the campaign. Required; must include a query. Other omitted fields use defaults.")
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["name", "configuration"]
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of CreateCampaignInfo from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # override the default output from pydantic by calling `to_dict()` of configuration
+ if self.configuration:
+ _dict['configuration'] = self.configuration.to_dict()
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of CreateCampaignInfo from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "name": obj.get("name"),
+ "configuration": CreateCampaignConfigurationInfo.from_dict(obj["configuration"]) if obj.get("configuration") is not None else None
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/create_group_info.py b/opal_security/models/create_group_info.py
index cd7480a..afdf1af 100644
--- a/opal_security/models/create_group_info.py
+++ b/opal_security/models/create_group_info.py
@@ -18,7 +18,7 @@
import re # noqa: F401
import json
-from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from typing_extensions import Annotated
from uuid import UUID
@@ -41,8 +41,10 @@ class CreateGroupInfo(BaseModel):
metadata: Optional[StrictStr] = Field(default=None, description="Deprecated - use remote_info instead. JSON metadata about the remote group. Include only for items linked to remote systems. See [this guide](https://docs.opal.dev/reference/end-system-objects) for details on how to specify this field. The required format is dependent on group_type and should have the following schema: ```json { \"$schema\": \"http://json-schema.org/draft-04/schema#\", \"title\": \"Group Metadata\", \"properties\": { \"ad_group\": { \"properties\": { \"object_guid\": { \"type\": \"string\" } }, \"required\": [\"object_guid\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"Active Directory Group\" }, \"duo_group\": { \"properties\": { \"group_id\": { \"type\": \"string\" } }, \"required\": [\"group_id\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"Duo Group\" }, \"git_hub_team\": { \"properties\": { \"org_name\": { \"type\": \"string\" }, \"team_slug\": { \"type\": \"string\" } }, \"required\": [\"org_name\", \"team_slug\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"GitHub Team\" }, \"google_groups_group\": { \"properties\": { \"group_id\": { \"type\": \"string\" } }, \"required\": [\"group_id\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"Google Groups Group\" }, \"ldap_group\": { \"properties\": { \"group_uid\": { \"type\": \"string\" } }, \"required\": [\"group_uid\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"LDAP Group\" }, \"okta_directory_group\": { \"properties\": { \"group_id\": { \"type\": \"string\" } }, \"required\": [\"group_id\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"Okta Directory Group\" } }, \"additionalProperties\": false, \"minProperties\": 1, \"maxProperties\": 1, \"type\": \"object\" } ```")
custom_request_notification: Optional[Annotated[str, Field(strict=True, max_length=800)]] = Field(default=None, description="Custom request notification sent upon request approval.")
risk_sensitivity_override: Optional[RiskSensitivityEnum] = None
+ match_remote_name: Optional[StrictBool] = Field(default=None, description="A bool representing whether or not the group's name should be synced from the end system. When true, the name is overwritten with the remote name on each sync, so a `name` provided together with this field set to true will be replaced at the next sync. Defaults to false.")
+ match_remote_description: Optional[StrictBool] = Field(default=None, description="A bool representing whether or not the group's description should be synced from the end system. When true, the description is overwritten with the remote description on each sync, so a `description` provided together with this field set to true will be replaced at the next sync. Defaults to false.")
additional_properties: Dict[str, Any] = {}
- __properties: ClassVar[List[str]] = ["name", "description", "group_type", "app_id", "remote_info", "remote_group_id", "metadata", "custom_request_notification", "risk_sensitivity_override"]
+ __properties: ClassVar[List[str]] = ["name", "description", "group_type", "app_id", "remote_info", "remote_group_id", "metadata", "custom_request_notification", "risk_sensitivity_override", "match_remote_name", "match_remote_description"]
model_config = ConfigDict(
populate_by_name=True,
@@ -113,7 +115,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"remote_group_id": obj.get("remote_group_id"),
"metadata": obj.get("metadata"),
"custom_request_notification": obj.get("custom_request_notification"),
- "risk_sensitivity_override": obj.get("risk_sensitivity_override")
+ "risk_sensitivity_override": obj.get("risk_sensitivity_override"),
+ "match_remote_name": obj.get("match_remote_name"),
+ "match_remote_description": obj.get("match_remote_description")
})
# store additional fields in additional_properties
for _key in obj.keys():
diff --git a/opal_security/models/create_resource_info.py b/opal_security/models/create_resource_info.py
index 4d8c535..16654bb 100644
--- a/opal_security/models/create_resource_info.py
+++ b/opal_security/models/create_resource_info.py
@@ -18,7 +18,7 @@
import re # noqa: F401
import json
-from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr
from typing import Any, ClassVar, Dict, List, Optional
from typing_extensions import Annotated
from uuid import UUID
@@ -41,8 +41,10 @@ class CreateResourceInfo(BaseModel):
metadata: Optional[StrictStr] = Field(default=None, description="Deprecated - use remote_info instead. JSON metadata about the remote resource. Include only for items linked to remote systems. See [this guide](https://docs.opal.dev/reference/end-system-objects) for details on how to specify this field. The required format is dependent on resource_type and should have the following schema: ```json { \"$schema\": \"http://json-schema.org/draft-04/schema#\", \"title\": \"Resource Metadata\", \"properties\": { \"aws_ec2_instance\": { \"properties\": { \"instance_id\": { \"type\": \"string\" }, \"region\": { \"type\": \"string\" } }, \"required\": [\"instance_id\", \"region\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"AWS EC2 Instance\" }, \"aws_eks_cluster\": { \"properties\": { \"cluster_name\": { \"type\": \"string\" }, \"cluster_region\": { \"type\": \"string\" }, \"cluster_arn\": { \"type\": \"string\" } }, \"required\": [\"cluster_name\", \"cluster_region\", \"cluster_arn\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"AWS EKS Cluster\" }, \"aws_rds_instance\": { \"properties\": { \"instance_id\": { \"type\": \"string\" }, \"engine\": { \"type\": \"string\" }, \"region\": { \"type\": \"string\" }, \"resource_id\": { \"type\": \"string\" }, \"database_name\": { \"type\": \"string\" } }, \"required\": [ \"instance_id\", \"engine\", \"region\", \"resource_id\", \"database_name\" ], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"AWS RDS Instance\" }, \"aws_role\": { \"properties\": { \"arn\": { \"type\": \"string\" }, \"name\": { \"type\": \"string\" } }, \"required\": [\"arn\", \"name\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"AWS Role\" }, \"gcp_bucket\": { \"properties\": { \"bucket_id\": { \"type\": \"string\" } }, \"required\": [\"bucket_id\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"GCP Bucket\" }, \"gcp_compute_instance\": { \"properties\": { \"instance_id\": { \"type\": \"string\" }, \"project_id\": { \"type\": \"string\" }, \"zone\": { \"type\": \"string\" } }, \"required\": [\"instance_id\", \"project_id\", \"zone\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"GCP Compute Instance\" }, \"gcp_folder\": { \"properties\": { \"folder_id\": { \"type\": \"string\" } }, \"required\": [\"folder_id\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"GCP Folder\" }, \"gcp_gke_cluster\": { \"properties\": { \"cluster_name\": { \"type\": \"string\" } }, \"required\": [\"cluster_name\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"GCP GKE Cluster\" }, \"gcp_project\": { \"properties\": { \"project_id\": { \"type\": \"string\" } }, \"required\": [\"project_id\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"GCP Project\" }, \"gcp_sql_instance\": { \"properties\": { \"instance_id\": { \"type\": \"string\" }, \"project_id\": { \"type\": \"string\" } }, \"required\": [\"instance_id\", \"project_id\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"GCP SQL Instance\" }, \"git_hub_repo\": { \"properties\": { \"org_name\": { \"type\": \"string\" }, \"repo_name\": { \"type\": \"string\" } }, \"required\": [\"org_name\", \"repo_name\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"GitHub Repo\" }, \"okta_directory_app\": { \"properties\": { \"app_id\": { \"type\": \"string\" }, \"logo_url\": { \"type\": \"string\" } }, \"required\": [\"app_id\", \"logo_url\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"Okta Directory App\" }, \"okta_directory_role\": { \"properties\": { \"role_type\": { \"type\": \"string\" }, \"role_id\": { \"type\": \"string\" } }, \"required\": [\"role_type\", \"role_id\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"Okta Directory Role\" }, \"salesforce_profile\": { \"properties\": { \"user_license\": { \"type\": \"string\" } }, \"required\": [\"user_license\"], \"additionalProperties\": false, \"type\": \"object\", \"title\": \"Salesforce Profile\" } }, \"additionalProperties\": false, \"minProperties\": 1, \"maxProperties\": 1, \"type\": \"object\" } ```")
custom_request_notification: Optional[Annotated[str, Field(strict=True, max_length=800)]] = Field(default=None, description="Custom request notification sent upon request approval.")
risk_sensitivity_override: Optional[RiskSensitivityEnum] = None
+ match_remote_name: Optional[StrictBool] = Field(default=None, description="A bool representing whether or not the resource's name should be synced from the end system. When true, the name is overwritten with the remote name on each sync, so a `name` provided together with this field set to true will be replaced at the next sync. Defaults to false.")
+ match_remote_description: Optional[StrictBool] = Field(default=None, description="A bool representing whether or not the resource's description should be synced from the end system. When true, the description is overwritten with the remote description on each sync, so a `description` provided together with this field set to true will be replaced at the next sync. Defaults to false.")
additional_properties: Dict[str, Any] = {}
- __properties: ClassVar[List[str]] = ["name", "description", "resource_type", "app_id", "remote_info", "remote_resource_id", "metadata", "custom_request_notification", "risk_sensitivity_override"]
+ __properties: ClassVar[List[str]] = ["name", "description", "resource_type", "app_id", "remote_info", "remote_resource_id", "metadata", "custom_request_notification", "risk_sensitivity_override", "match_remote_name", "match_remote_description"]
model_config = ConfigDict(
populate_by_name=True,
@@ -113,7 +115,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"remote_resource_id": obj.get("remote_resource_id"),
"metadata": obj.get("metadata"),
"custom_request_notification": obj.get("custom_request_notification"),
- "risk_sensitivity_override": obj.get("risk_sensitivity_override")
+ "risk_sensitivity_override": obj.get("risk_sensitivity_override"),
+ "match_remote_name": obj.get("match_remote_name"),
+ "match_remote_description": obj.get("match_remote_description")
})
# store additional fields in additional_properties
for _key in obj.keys():
diff --git a/opal_security/models/entity_admin_filter.py b/opal_security/models/entity_admin_filter.py
new file mode 100644
index 0000000..17d291f
--- /dev/null
+++ b/opal_security/models/entity_admin_filter.py
@@ -0,0 +1,104 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from pydantic import BaseModel, ConfigDict, Field, StrictBool
+from typing import Any, ClassVar, Dict, List, Optional
+from uuid import UUID
+from typing import Optional, Set
+from typing_extensions import Self
+
+class EntityAdminFilter(BaseModel):
+ """
+ Filters GROUP and RESOURCE entities by their admin owner. USER entities never match, in either polarity. `not` inverts the match within the resource/group domain (self-negating, like IdpStatusFilter): omit it (or false) to include entities owned by the given owners, set it true to exclude them.
+ """ # noqa: E501
+ owner_ids: List[UUID] = Field(description="The owner (group) UUIDs to match entities against.", alias="ownerIDs")
+ var_not: Optional[StrictBool] = Field(default=None, description="Invert the match — return resources/groups NOT owned by the given owners.", alias="not")
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["ownerIDs", "not"]
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of EntityAdminFilter from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of EntityAdminFilter from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "ownerIDs": obj.get("ownerIDs"),
+ "not": obj.get("not")
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/group.py b/opal_security/models/group.py
index 9e734d1..7e79bb4 100644
--- a/opal_security/models/group.py
+++ b/opal_security/models/group.py
@@ -62,9 +62,11 @@ class Group(BaseModel):
custom_request_notification: Optional[Annotated[str, Field(strict=True, max_length=800)]] = Field(default=None, description="Custom request notification sent to the requester when the request is approved.")
risk_sensitivity: Optional[RiskSensitivityEnum] = Field(default=None, description="The risk sensitivity level for the group. When an override is set, this field will match that.")
risk_sensitivity_override: Optional[RiskSensitivityEnum] = None
+ match_remote_name: Optional[StrictBool] = Field(default=None, description="A bool representing whether or not the group's name is synced from the end system. When true, the name is overwritten with the remote name on each sync. Defaults to false.")
+ match_remote_description: Optional[StrictBool] = Field(default=None, description="A bool representing whether or not the group's description is synced from the end system. When true, the description is overwritten with the remote description on each sync. Defaults to false.")
last_successful_sync: Optional[SyncTask] = Field(default=None, description="Information about the last successful sync of this group.")
additional_properties: Dict[str, Any] = {}
- __properties: ClassVar[List[str]] = ["group_id", "app_id", "name", "description", "admin_owner_id", "group_leader_user_ids", "remote_id", "remote_name", "group_type", "max_duration", "recommended_duration", "extensions_duration_in_minutes", "require_manager_approval", "require_support_ticket", "require_mfa_to_approve", "require_mfa_to_request", "auto_approval", "request_template_id", "configuration_template_id", "group_binding_id", "is_requestable", "request_configurations", "request_configuration_list", "metadata", "remote_info", "custom_request_notification", "risk_sensitivity", "risk_sensitivity_override", "last_successful_sync"]
+ __properties: ClassVar[List[str]] = ["group_id", "app_id", "name", "description", "admin_owner_id", "group_leader_user_ids", "remote_id", "remote_name", "group_type", "max_duration", "recommended_duration", "extensions_duration_in_minutes", "require_manager_approval", "require_support_ticket", "require_mfa_to_approve", "require_mfa_to_request", "auto_approval", "request_template_id", "configuration_template_id", "group_binding_id", "is_requestable", "request_configurations", "request_configuration_list", "metadata", "remote_info", "custom_request_notification", "risk_sensitivity", "risk_sensitivity_override", "match_remote_name", "match_remote_description", "last_successful_sync"]
model_config = ConfigDict(
populate_by_name=True,
@@ -176,6 +178,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"custom_request_notification": obj.get("custom_request_notification"),
"risk_sensitivity": obj.get("risk_sensitivity"),
"risk_sensitivity_override": obj.get("risk_sensitivity_override"),
+ "match_remote_name": obj.get("match_remote_name"),
+ "match_remote_description": obj.get("match_remote_description"),
"last_successful_sync": SyncTask.from_dict(obj["last_successful_sync"]) if obj.get("last_successful_sync") is not None else None
})
# store additional fields in additional_properties
diff --git a/opal_security/models/group_remote_info.py b/opal_security/models/group_remote_info.py
index 253a55c..f869383 100644
--- a/opal_security/models/group_remote_info.py
+++ b/opal_security/models/group_remote_info.py
@@ -43,6 +43,7 @@
from opal_security.models.group_remote_info_rootly_on_call_schedule import GroupRemoteInfoRootlyOnCallSchedule
from opal_security.models.group_remote_info_slack_user_group import GroupRemoteInfoSlackUserGroup
from opal_security.models.group_remote_info_snowflake_role import GroupRemoteInfoSnowflakeRole
+from opal_security.models.group_remote_info_tableau_group import GroupRemoteInfoTableauGroup
from opal_security.models.group_remote_info_tailscale_group import GroupRemoteInfoTailscaleGroup
from opal_security.models.group_remote_info_twingate_group import GroupRemoteInfoTwingateGroup
from opal_security.models.group_remote_info_twingate_group_synced import GroupRemoteInfoTwingateGroupSynced
@@ -85,8 +86,9 @@ class GroupRemoteInfo(BaseModel):
slack_user_group: Optional[GroupRemoteInfoSlackUserGroup] = None
zendesk_organization: Optional[GroupRemoteInfoZendeskOrganization] = None
hubspot_team: Optional[GroupRemoteInfoHubspotTeam] = None
+ tableau_group: Optional[GroupRemoteInfoTableauGroup] = None
additional_properties: Dict[str, Any] = {}
- __properties: ClassVar[List[str]] = ["active_directory_group", "tailscale_group", "twingate_group", "twingate_group_synced", "aws_sso_group", "databricks_account_group", "connector_group", "github_team", "github_enterprise_team", "gitlab_group", "google_group", "ldap_group", "okta_group", "duo_group", "azure_ad_security_group", "azure_ad_microsoft_365_group", "snowflake_role", "okta_group_rule", "workday_user_security_group", "pagerduty_on_call_schedule", "incidentio_on_call_schedule", "rootly_on_call_schedule", "devin_group", "clickhouse_role", "grafana_team", "zendesk_group", "slack_user_group", "zendesk_organization", "hubspot_team"]
+ __properties: ClassVar[List[str]] = ["active_directory_group", "tailscale_group", "twingate_group", "twingate_group_synced", "aws_sso_group", "databricks_account_group", "connector_group", "github_team", "github_enterprise_team", "gitlab_group", "google_group", "ldap_group", "okta_group", "duo_group", "azure_ad_security_group", "azure_ad_microsoft_365_group", "snowflake_role", "okta_group_rule", "workday_user_security_group", "pagerduty_on_call_schedule", "incidentio_on_call_schedule", "rootly_on_call_schedule", "devin_group", "clickhouse_role", "grafana_team", "zendesk_group", "slack_user_group", "zendesk_organization", "hubspot_team", "tableau_group"]
model_config = ConfigDict(
populate_by_name=True,
@@ -216,6 +218,9 @@ def to_dict(self) -> Dict[str, Any]:
# override the default output from pydantic by calling `to_dict()` of hubspot_team
if self.hubspot_team:
_dict['hubspot_team'] = self.hubspot_team.to_dict()
+ # override the default output from pydantic by calling `to_dict()` of tableau_group
+ if self.tableau_group:
+ _dict['tableau_group'] = self.tableau_group.to_dict()
# puts key-value pairs in additional_properties in the top level
if self.additional_properties is not None:
for _key, _value in self.additional_properties.items():
@@ -261,7 +266,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"zendesk_group": GroupRemoteInfoZendeskGroup.from_dict(obj["zendesk_group"]) if obj.get("zendesk_group") is not None else None,
"slack_user_group": GroupRemoteInfoSlackUserGroup.from_dict(obj["slack_user_group"]) if obj.get("slack_user_group") is not None else None,
"zendesk_organization": GroupRemoteInfoZendeskOrganization.from_dict(obj["zendesk_organization"]) if obj.get("zendesk_organization") is not None else None,
- "hubspot_team": GroupRemoteInfoHubspotTeam.from_dict(obj["hubspot_team"]) if obj.get("hubspot_team") is not None else None
+ "hubspot_team": GroupRemoteInfoHubspotTeam.from_dict(obj["hubspot_team"]) if obj.get("hubspot_team") is not None else None,
+ "tableau_group": GroupRemoteInfoTableauGroup.from_dict(obj["tableau_group"]) if obj.get("tableau_group") is not None else None
})
# store additional fields in additional_properties
for _key in obj.keys():
diff --git a/opal_security/models/group_remote_info_tableau_group.py b/opal_security/models/group_remote_info_tableau_group.py
new file mode 100644
index 0000000..cd3dd5f
--- /dev/null
+++ b/opal_security/models/group_remote_info_tableau_group.py
@@ -0,0 +1,101 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing import Any, ClassVar, Dict, List
+from typing import Optional, Set
+from typing_extensions import Self
+
+class GroupRemoteInfoTableauGroup(BaseModel):
+ """
+ Remote info for Tableau group.
+ """ # noqa: E501
+ group_id: StrictStr = Field(description="The ID of the Tableau group.")
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["group_id"]
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of GroupRemoteInfoTableauGroup from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of GroupRemoteInfoTableauGroup from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "group_id": obj.get("group_id")
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/group_type_enum.py b/opal_security/models/group_type_enum.py
index 64a2bc4..ad70286 100644
--- a/opal_security/models/group_type_enum.py
+++ b/opal_security/models/group_type_enum.py
@@ -59,6 +59,7 @@ class GroupTypeEnum(str, Enum):
ZENDESK_GROUP = 'ZENDESK_GROUP'
ZENDESK_ORGANIZATION = 'ZENDESK_ORGANIZATION'
HUBSPOT_TEAM = 'HUBSPOT_TEAM'
+ TABLEAU_GROUP = 'TABLEAU_GROUP'
@classmethod
def from_json(cls, json_str: str) -> Self:
diff --git a/opal_security/models/idp_status_filter.py b/opal_security/models/idp_status_filter.py
new file mode 100644
index 0000000..bf62123
--- /dev/null
+++ b/opal_security/models/idp_status_filter.py
@@ -0,0 +1,104 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from pydantic import BaseModel, ConfigDict, Field, StrictBool
+from typing import Any, ClassVar, Dict, List, Optional
+from opal_security.models.user_hr_idp_status_enum import UserHrIdpStatusEnum
+from typing import Optional, Set
+from typing_extensions import Self
+
+class IdpStatusFilter(BaseModel):
+ """
+ Filters USER entities by their HR/IDP lifecycle status. Only applies to USER entities; GROUP and RESOURCE entities never match, in either polarity. `statuses` combine with OR. `not` inverts the match within the user domain (e.g. \"IDP status is NOT active\"), so it still returns only users rather than sweeping in groups/resources.
+ """ # noqa: E501
+ statuses: Optional[List[UserHrIdpStatusEnum]] = Field(default=None, description="Match users whose HR/IDP status is one of these values.")
+ var_not: Optional[StrictBool] = Field(default=None, description="Invert the match within the user domain (e.g. \"IDP status is NOT active\").", alias="not")
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["statuses", "not"]
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of IdpStatusFilter from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of IdpStatusFilter from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "statuses": obj.get("statuses"),
+ "not": obj.get("not")
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/opal_access_path_edge_filter.py b/opal_security/models/opal_access_path_edge_filter.py
new file mode 100644
index 0000000..65ad889
--- /dev/null
+++ b/opal_security/models/opal_access_path_edge_filter.py
@@ -0,0 +1,113 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr, field_validator
+from typing import Any, ClassVar, Dict, List, Optional
+from typing import Optional, Set
+from typing_extensions import Self
+
+class OpalAccessPathEdgeFilter(BaseModel):
+ """
+ Constraints on the access path edges themselves.
+ """ # noqa: E501
+ direct_only: Optional[StrictBool] = Field(default=None, description="When true, only return direct (depth-1) principal-to-entitlement edges.", alias="directOnly")
+ access_duration_type: Optional[StrictStr] = Field(default=None, description="Constrain results by whether the terminal access expires.", alias="accessDurationType")
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["directOnly", "accessDurationType"]
+
+ @field_validator('access_duration_type')
+ def access_duration_type_validate_enum(cls, value):
+ """Validates the enum"""
+ if value is None:
+ return value
+
+ if value not in set(['EXPIRING_ONLY', 'PERMANENT_ONLY']):
+ raise ValueError("must be one of enum values ('EXPIRING_ONLY', 'PERMANENT_ONLY')")
+ return value
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of OpalAccessPathEdgeFilter from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of OpalAccessPathEdgeFilter from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "directOnly": obj.get("directOnly"),
+ "accessDurationType": obj.get("accessDurationType")
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/opal_access_path_query.py b/opal_security/models/opal_access_path_query.py
new file mode 100644
index 0000000..ff3c9fd
--- /dev/null
+++ b/opal_security/models/opal_access_path_query.py
@@ -0,0 +1,120 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr, field_validator
+from typing import Any, ClassVar, Dict, List, Optional
+from opal_security.models.opal_access_path_query_body import OpalAccessPathQueryBody
+from typing import Optional, Set
+from typing_extensions import Self
+
+class OpalAccessPathQuery(BaseModel):
+ """
+ Request body for an ACCESS_PATH-type OpalQuery. Returns principal-to- entitlement access paths matching the given edge filters.
+ """ # noqa: E501
+ type: StrictStr
+ query: Optional[OpalAccessPathQueryBody] = None
+ first: Optional[StrictInt] = Field(default=None, description="Maximum number of results to return. Defaults to 200.")
+ after: Optional[StrictStr] = Field(default=None, description="Opaque cursor from a previous ACCESS_PATH response to fetch the next page of results.")
+ include_count: Optional[StrictBool] = Field(default=None, description="When true, populate totalCount in the response. Defaults to false.", alias="includeCount")
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["type", "query", "first", "after", "includeCount"]
+
+ @field_validator('type')
+ def type_validate_enum(cls, value):
+ """Validates the enum"""
+ if value not in set(['ACCESS_PATH']):
+ raise ValueError("must be one of enum values ('ACCESS_PATH')")
+ return value
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of OpalAccessPathQuery from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # override the default output from pydantic by calling `to_dict()` of query
+ if self.query:
+ _dict['query'] = self.query.to_dict()
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of OpalAccessPathQuery from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "type": obj.get("type"),
+ "query": OpalAccessPathQueryBody.from_dict(obj["query"]) if obj.get("query") is not None else None,
+ "first": obj.get("first"),
+ "after": obj.get("after"),
+ "includeCount": obj.get("includeCount")
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/opal_access_path_query_body.py b/opal_security/models/opal_access_path_query_body.py
new file mode 100644
index 0000000..bac79b4
--- /dev/null
+++ b/opal_security/models/opal_access_path_query_body.py
@@ -0,0 +1,131 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing import Any, ClassVar, Dict, List, Optional
+from opal_security.models.access_entity_filters import AccessEntityFilters
+from opal_security.models.access_relationship_filters import AccessRelationshipFilters
+from opal_security.models.opal_access_path_edge_filter import OpalAccessPathEdgeFilter
+from typing import Optional, Set
+from typing_extensions import Self
+
+class OpalAccessPathQueryBody(BaseModel):
+ """
+ Edge-query filters for an ACCESS_PATH OpalQuery. At least one of principalFilter or entitlementFilter is required.
+ """ # noqa: E501
+ principal_filter: Optional[AccessEntityFilters] = Field(default=None, alias="principalFilter")
+ entitlement_filter: Optional[AccessEntityFilters] = Field(default=None, alias="entitlementFilter")
+ principal_access_filters: Optional[AccessRelationshipFilters] = Field(default=None, description="Advanced access filter on the principal side of each path. Restricts results to principals that additionally satisfy these access-edge constraints: `hasAccessTo` keeps only principals that also have access to a matching entity; `isAccessibleBy` keeps only principals that are also accessible by a matching entity. Only takes effect when `principalFilter` is also supplied (it refines that filter); on its own it has no effect. ", alias="principalAccessFilters")
+ entitlement_access_filters: Optional[AccessRelationshipFilters] = Field(default=None, description="Advanced access filter on the entitlement side of each path. Restricts results to entitlements that additionally satisfy these access-edge constraints: `hasAccessTo` keeps only entitlements that also have access to a matching entity; `isAccessibleBy` keeps only entitlements that are also accessible by a matching entity. Only takes effect when `entitlementFilter` is also supplied (it refines that filter); on its own it has no effect. ", alias="entitlementAccessFilters")
+ access_level_remote_ids: Optional[List[StrictStr]] = Field(default=None, description="Filter by access-level remote IDs on the terminal edge.", alias="accessLevelRemoteIds")
+ access_level_names: Optional[List[StrictStr]] = Field(default=None, description="Filter by access-level display names on the terminal edge.", alias="accessLevelNames")
+ edge_filter: Optional[OpalAccessPathEdgeFilter] = Field(default=None, alias="edgeFilter")
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["principalFilter", "entitlementFilter", "principalAccessFilters", "entitlementAccessFilters", "accessLevelRemoteIds", "accessLevelNames", "edgeFilter"]
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of OpalAccessPathQueryBody from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # override the default output from pydantic by calling `to_dict()` of principal_filter
+ if self.principal_filter:
+ _dict['principalFilter'] = self.principal_filter.to_dict()
+ # override the default output from pydantic by calling `to_dict()` of entitlement_filter
+ if self.entitlement_filter:
+ _dict['entitlementFilter'] = self.entitlement_filter.to_dict()
+ # override the default output from pydantic by calling `to_dict()` of principal_access_filters
+ if self.principal_access_filters:
+ _dict['principalAccessFilters'] = self.principal_access_filters.to_dict()
+ # override the default output from pydantic by calling `to_dict()` of entitlement_access_filters
+ if self.entitlement_access_filters:
+ _dict['entitlementAccessFilters'] = self.entitlement_access_filters.to_dict()
+ # override the default output from pydantic by calling `to_dict()` of edge_filter
+ if self.edge_filter:
+ _dict['edgeFilter'] = self.edge_filter.to_dict()
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of OpalAccessPathQueryBody from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "principalFilter": AccessEntityFilters.from_dict(obj["principalFilter"]) if obj.get("principalFilter") is not None else None,
+ "entitlementFilter": AccessEntityFilters.from_dict(obj["entitlementFilter"]) if obj.get("entitlementFilter") is not None else None,
+ "principalAccessFilters": AccessRelationshipFilters.from_dict(obj["principalAccessFilters"]) if obj.get("principalAccessFilters") is not None else None,
+ "entitlementAccessFilters": AccessRelationshipFilters.from_dict(obj["entitlementAccessFilters"]) if obj.get("entitlementAccessFilters") is not None else None,
+ "accessLevelRemoteIds": obj.get("accessLevelRemoteIds"),
+ "accessLevelNames": obj.get("accessLevelNames"),
+ "edgeFilter": OpalAccessPathEdgeFilter.from_dict(obj["edgeFilter"]) if obj.get("edgeFilter") is not None else None
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/opal_access_path_query_results.py b/opal_security/models/opal_access_path_query_results.py
new file mode 100644
index 0000000..4eb2e52
--- /dev/null
+++ b/opal_security/models/opal_access_path_query_results.py
@@ -0,0 +1,126 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr, field_validator
+from typing import Any, ClassVar, Dict, List, Optional
+from opal_security.models.opal_access_path_result_edge import OpalAccessPathResultEdge
+from opal_security.models.page_info import PageInfo
+from typing import Optional, Set
+from typing_extensions import Self
+
+class OpalAccessPathQueryResults(BaseModel):
+ """
+ Paginated results of an ACCESS_PATH-type OpalQuery — one edge per matched principal-to-entitlement access path.
+ """ # noqa: E501
+ type: StrictStr
+ edges: List[OpalAccessPathResultEdge] = Field(description="List of matched access paths.")
+ page_info: PageInfo = Field(alias="pageInfo")
+ total_count: Optional[StrictInt] = Field(default=None, description="Exact total number of matching paths when includeCount was true on the request; otherwise null.", alias="totalCount")
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["type", "edges", "pageInfo", "totalCount"]
+
+ @field_validator('type')
+ def type_validate_enum(cls, value):
+ """Validates the enum"""
+ if value not in set(['ACCESS_PATH']):
+ raise ValueError("must be one of enum values ('ACCESS_PATH')")
+ return value
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of OpalAccessPathQueryResults from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # override the default output from pydantic by calling `to_dict()` of each item in edges (list)
+ _items = []
+ if self.edges:
+ for _item_edges in self.edges:
+ if _item_edges:
+ _items.append(_item_edges.to_dict())
+ _dict['edges'] = _items
+ # override the default output from pydantic by calling `to_dict()` of page_info
+ if self.page_info:
+ _dict['pageInfo'] = self.page_info.to_dict()
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of OpalAccessPathQueryResults from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "type": obj.get("type"),
+ "edges": [OpalAccessPathResultEdge.from_dict(_item) for _item in obj["edges"]] if obj.get("edges") is not None else None,
+ "pageInfo": PageInfo.from_dict(obj["pageInfo"]) if obj.get("pageInfo") is not None else None,
+ "totalCount": obj.get("totalCount")
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/opal_access_path_result_edge.py b/opal_security/models/opal_access_path_result_edge.py
new file mode 100644
index 0000000..311dd6c
--- /dev/null
+++ b/opal_security/models/opal_access_path_result_edge.py
@@ -0,0 +1,107 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing import Any, ClassVar, Dict, List
+from opal_security.models.opal_access_path_result_node import OpalAccessPathResultNode
+from typing import Optional, Set
+from typing_extensions import Self
+
+class OpalAccessPathResultEdge(BaseModel):
+ """
+ A single ACCESS_PATH result edge containing the matched path and its pagination cursor.
+ """ # noqa: E501
+ node: OpalAccessPathResultNode
+ cursor: StrictStr = Field(description="Opaque cursor for this path, used for pagination.")
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["node", "cursor"]
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of OpalAccessPathResultEdge from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # override the default output from pydantic by calling `to_dict()` of node
+ if self.node:
+ _dict['node'] = self.node.to_dict()
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of OpalAccessPathResultEdge from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "node": OpalAccessPathResultNode.from_dict(obj["node"]) if obj.get("node") is not None else None,
+ "cursor": obj.get("cursor")
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/opal_access_path_result_node.py b/opal_security/models/opal_access_path_result_node.py
new file mode 100644
index 0000000..1136282
--- /dev/null
+++ b/opal_security/models/opal_access_path_result_node.py
@@ -0,0 +1,115 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from datetime import datetime
+from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr
+from typing import Any, ClassVar, Dict, List, Optional
+from uuid import UUID
+from typing import Optional, Set
+from typing_extensions import Self
+
+class OpalAccessPathResultNode(BaseModel):
+ """
+ A matched access path from an ACCESS_PATH OpalQuery.
+ """ # noqa: E501
+ principal_id: UUID = Field(description="The principal entity ID.", alias="principalId")
+ entitlement_id: UUID = Field(description="The entitlement entity ID.", alias="entitlementId")
+ access_level_remote_id: Optional[StrictStr] = Field(default=None, description="Remote ID of the terminal access level.", alias="accessLevelRemoteId")
+ access_level_name: Optional[StrictStr] = Field(default=None, description="Display name of the terminal access level.", alias="accessLevelName")
+ expiration: Optional[datetime] = Field(default=None, description="Expiration of the terminal access, if any.")
+ depth: StrictInt = Field(description="Number of hops from principal to entitlement (path length - 1).")
+ path: List[UUID] = Field(description="Entity IDs along the path from principal to entitlement.")
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["principalId", "entitlementId", "accessLevelRemoteId", "accessLevelName", "expiration", "depth", "path"]
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of OpalAccessPathResultNode from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of OpalAccessPathResultNode from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "principalId": obj.get("principalId"),
+ "entitlementId": obj.get("entitlementId"),
+ "accessLevelRemoteId": obj.get("accessLevelRemoteId"),
+ "accessLevelName": obj.get("accessLevelName"),
+ "expiration": obj.get("expiration"),
+ "depth": obj.get("depth"),
+ "path": obj.get("path")
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/opal_query_results.py b/opal_security/models/opal_query_results.py
new file mode 100644
index 0000000..9f78fc7
--- /dev/null
+++ b/opal_security/models/opal_query_results.py
@@ -0,0 +1,141 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import json
+import pprint
+from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator
+from typing import Any, List, Optional
+from opal_security.models.opal_access_path_query_results import OpalAccessPathQueryResults
+from opal_security.models.opal_node_query_results import OpalNodeQueryResults
+from pydantic import StrictStr, Field
+from typing import Union, List, Set, Optional, Dict
+from typing_extensions import Literal, Self
+
+OPALQUERYRESULTS_ONE_OF_SCHEMAS = ["OpalAccessPathQueryResults", "OpalNodeQueryResults"]
+
+class OpalQueryResults(BaseModel):
+ """
+ Paginated results of an OpalQuery. The `type` field discriminates which result schema applies and mirrors the `type` field on the request.
+ """
+ # data type: OpalNodeQueryResults
+ oneof_schema_1_validator: Optional[OpalNodeQueryResults] = None
+ # data type: OpalAccessPathQueryResults
+ oneof_schema_2_validator: Optional[OpalAccessPathQueryResults] = None
+ actual_instance: Optional[Union[OpalAccessPathQueryResults, OpalNodeQueryResults]] = None
+ one_of_schemas: Set[str] = { "OpalAccessPathQueryResults", "OpalNodeQueryResults" }
+
+ model_config = ConfigDict(
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ discriminator_value_class_map: Dict[str, str] = {
+ }
+
+ def __init__(self, *args, **kwargs) -> None:
+ if args:
+ if len(args) > 1:
+ raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`")
+ if kwargs:
+ raise ValueError("If a position argument is used, keyword arguments cannot be used.")
+ super().__init__(actual_instance=args[0])
+ else:
+ super().__init__(**kwargs)
+
+ @field_validator('actual_instance')
+ def actual_instance_must_validate_oneof(cls, v):
+ instance = OpalQueryResults.model_construct()
+ error_messages = []
+ match = 0
+ # validate data type: OpalNodeQueryResults
+ if not isinstance(v, OpalNodeQueryResults):
+ error_messages.append(f"Error! Input type `{type(v)}` is not `OpalNodeQueryResults`")
+ else:
+ match += 1
+ # validate data type: OpalAccessPathQueryResults
+ if not isinstance(v, OpalAccessPathQueryResults):
+ error_messages.append(f"Error! Input type `{type(v)}` is not `OpalAccessPathQueryResults`")
+ else:
+ match += 1
+ if match > 1:
+ # more than 1 match
+ raise ValueError("Multiple matches found when setting `actual_instance` in OpalQueryResults with oneOf schemas: OpalAccessPathQueryResults, OpalNodeQueryResults. Details: " + ", ".join(error_messages))
+ elif match == 0:
+ # no match
+ raise ValueError("No match found when setting `actual_instance` in OpalQueryResults with oneOf schemas: OpalAccessPathQueryResults, OpalNodeQueryResults. Details: " + ", ".join(error_messages))
+ else:
+ return v
+
+ @classmethod
+ def from_dict(cls, obj: Union[str, Dict[str, Any]]) -> Self:
+ return cls.from_json(json.dumps(obj))
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Self:
+ """Returns the object represented by the json string"""
+ instance = cls.model_construct()
+ error_messages = []
+ match = 0
+
+ # deserialize data into OpalNodeQueryResults
+ try:
+ instance.actual_instance = OpalNodeQueryResults.from_json(json_str)
+ match += 1
+ except (ValidationError, ValueError) as e:
+ error_messages.append(str(e))
+ # deserialize data into OpalAccessPathQueryResults
+ try:
+ instance.actual_instance = OpalAccessPathQueryResults.from_json(json_str)
+ match += 1
+ except (ValidationError, ValueError) as e:
+ error_messages.append(str(e))
+
+ if match > 1:
+ # more than 1 match
+ raise ValueError("Multiple matches found when deserializing the JSON string into OpalQueryResults with oneOf schemas: OpalAccessPathQueryResults, OpalNodeQueryResults. Details: " + ", ".join(error_messages))
+ elif match == 0:
+ # no match
+ raise ValueError("No match found when deserializing the JSON string into OpalQueryResults with oneOf schemas: OpalAccessPathQueryResults, OpalNodeQueryResults. Details: " + ", ".join(error_messages))
+ else:
+ return instance
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the actual instance"""
+ if self.actual_instance is None:
+ return "null"
+
+ if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json):
+ return self.actual_instance.to_json()
+ else:
+ return json.dumps(self.actual_instance)
+
+ def to_dict(self) -> Optional[Union[Dict[str, Any], OpalAccessPathQueryResults, OpalNodeQueryResults]]:
+ """Returns the dict representation of the actual instance"""
+ if self.actual_instance is None:
+ return None
+
+ if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict):
+ return self.actual_instance.to_dict()
+ else:
+ # primitive type
+ return self.actual_instance
+
+ def to_str(self) -> str:
+ """Returns the string representation of the actual instance"""
+ return pprint.pformat(self.model_dump())
+
+
diff --git a/opal_security/models/paginated_campaigns_list.py b/opal_security/models/paginated_campaigns_list.py
new file mode 100644
index 0000000..6bbb552
--- /dev/null
+++ b/opal_security/models/paginated_campaigns_list.py
@@ -0,0 +1,113 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing import Any, ClassVar, Dict, List, Optional
+from opal_security.models.campaign import Campaign
+from typing import Optional, Set
+from typing_extensions import Self
+
+class PaginatedCampaignsList(BaseModel):
+ """
+ A list of campaigns.
+ """ # noqa: E501
+ next: Optional[StrictStr] = Field(default=None, description="The cursor with which to continue pagination if additional result pages exist.")
+ previous: Optional[StrictStr] = Field(default=None, description="The cursor used to obtain the current result page.")
+ results: List[Campaign]
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["next", "previous", "results"]
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of PaginatedCampaignsList from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # override the default output from pydantic by calling `to_dict()` of each item in results (list)
+ _items = []
+ if self.results:
+ for _item_results in self.results:
+ if _item_results:
+ _items.append(_item_results.to_dict())
+ _dict['results'] = _items
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of PaginatedCampaignsList from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "next": obj.get("next"),
+ "previous": obj.get("previous"),
+ "results": [Campaign.from_dict(_item) for _item in obj["results"]] if obj.get("results") is not None else None
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/paladin.py b/opal_security/models/paladin.py
new file mode 100644
index 0000000..a273550
--- /dev/null
+++ b/opal_security/models/paladin.py
@@ -0,0 +1,104 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing import Any, ClassVar, Dict, List
+from uuid import UUID
+from typing import Optional, Set
+from typing_extensions import Self
+
+class Paladin(BaseModel):
+ """
+ # Paladin Object ### Description The `Paladin` object represents a Paladin, Opal's AI access-request reviewer.
+ """ # noqa: E501
+ paladin_id: UUID = Field(description="The ID of the Paladin. Use this value as a reviewer in a request configuration's service_user_ids.")
+ name: StrictStr = Field(description="The name of the Paladin.")
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["paladin_id", "name"]
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of Paladin from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of Paladin from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "paladin_id": obj.get("paladin_id"),
+ "name": obj.get("name")
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/paladin_list.py b/opal_security/models/paladin_list.py
new file mode 100644
index 0000000..ade820b
--- /dev/null
+++ b/opal_security/models/paladin_list.py
@@ -0,0 +1,109 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from pydantic import BaseModel, ConfigDict
+from typing import Any, ClassVar, Dict, List
+from opal_security.models.paladin import Paladin
+from typing import Optional, Set
+from typing_extensions import Self
+
+class PaladinList(BaseModel):
+ """
+ # PaladinList Object ### Description A list of `Paladin` objects.
+ """ # noqa: E501
+ results: List[Paladin]
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["results"]
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of PaladinList from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # override the default output from pydantic by calling `to_dict()` of each item in results (list)
+ _items = []
+ if self.results:
+ for _item_results in self.results:
+ if _item_results:
+ _items.append(_item_results.to_dict())
+ _dict['results'] = _items
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of PaladinList from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "results": [Paladin.from_dict(_item) for _item in obj["results"]] if obj.get("results") is not None else None
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/propagation_status_enum.py b/opal_security/models/propagation_status_enum.py
index 0a98d55..db9bba6 100644
--- a/opal_security/models/propagation_status_enum.py
+++ b/opal_security/models/propagation_status_enum.py
@@ -48,6 +48,7 @@ class PropagationStatusEnum(str, Enum):
ERR_DRY_RUN_MODE_ENABLED = 'ERR_DRY_RUN_MODE_ENABLED'
ERR_HR_IDP_PROVIDER_NOT_LINKED = 'ERR_HR_IDP_PROVIDER_NOT_LINKED'
ERR_REMOTE_UNRECOVERABLE_ERROR = 'ERR_REMOTE_UNRECOVERABLE_ERROR'
+ ERR_REMOTE_TICKET_NOT_FOUND = 'ERR_REMOTE_TICKET_NOT_FOUND'
@classmethod
def from_json(cls, json_str: str) -> Self:
diff --git a/opal_security/models/resource.py b/opal_security/models/resource.py
index a717453..80db2fa 100644
--- a/opal_security/models/resource.py
+++ b/opal_security/models/resource.py
@@ -66,9 +66,11 @@ class Resource(BaseModel):
remote_info: Optional[ResourceRemoteInfo] = None
ancestor_resource_ids: Optional[List[UUID]] = Field(default=None, description="List of resource IDs that are ancestors of this resource.")
descendant_resource_ids: Optional[List[UUID]] = Field(default=None, description="List of resource IDs that are descendants of this resource.")
+ match_remote_name: Optional[StrictBool] = Field(default=None, description="A bool representing whether or not the resource's name is synced from the end system. When true, the name is overwritten with the remote name on each sync. Defaults to false.")
+ match_remote_description: Optional[StrictBool] = Field(default=None, description="A bool representing whether or not the resource's description is synced from the end system. When true, the description is overwritten with the remote description on each sync. Defaults to false.")
last_successful_sync: Optional[SyncTask] = Field(default=None, description="Information about the last successful sync of this resource.")
additional_properties: Dict[str, Any] = {}
- __properties: ClassVar[List[str]] = ["resource_id", "app_id", "name", "description", "admin_owner_id", "remote_resource_id", "remote_resource_name", "resource_type", "max_duration", "recommended_duration", "extensions_duration_in_minutes", "require_manager_approval", "require_support_ticket", "require_mfa_to_approve", "require_mfa_to_request", "require_mfa_to_connect", "auto_approval", "request_template_id", "is_requestable", "parent_resource_id", "configuration_template_id", "request_configurations", "request_configuration_list", "ticket_propagation", "custom_request_notification", "risk_sensitivity", "risk_sensitivity_override", "metadata", "remote_info", "ancestor_resource_ids", "descendant_resource_ids", "last_successful_sync"]
+ __properties: ClassVar[List[str]] = ["resource_id", "app_id", "name", "description", "admin_owner_id", "remote_resource_id", "remote_resource_name", "resource_type", "max_duration", "recommended_duration", "extensions_duration_in_minutes", "require_manager_approval", "require_support_ticket", "require_mfa_to_approve", "require_mfa_to_request", "require_mfa_to_connect", "auto_approval", "request_template_id", "is_requestable", "parent_resource_id", "configuration_template_id", "request_configurations", "request_configuration_list", "ticket_propagation", "custom_request_notification", "risk_sensitivity", "risk_sensitivity_override", "metadata", "remote_info", "ancestor_resource_ids", "descendant_resource_ids", "match_remote_name", "match_remote_description", "last_successful_sync"]
model_config = ConfigDict(
populate_by_name=True,
@@ -186,6 +188,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"remote_info": ResourceRemoteInfo.from_dict(obj["remote_info"]) if obj.get("remote_info") is not None else None,
"ancestor_resource_ids": obj.get("ancestor_resource_ids"),
"descendant_resource_ids": obj.get("descendant_resource_ids"),
+ "match_remote_name": obj.get("match_remote_name"),
+ "match_remote_description": obj.get("match_remote_description"),
"last_successful_sync": SyncTask.from_dict(obj["last_successful_sync"]) if obj.get("last_successful_sync") is not None else None
})
# store additional fields in additional_properties
diff --git a/opal_security/models/resource_remote_info.py b/opal_security/models/resource_remote_info.py
index 02523eb..65238de 100644
--- a/opal_security/models/resource_remote_info.py
+++ b/opal_security/models/resource_remote_info.py
@@ -20,6 +20,8 @@
from pydantic import BaseModel, ConfigDict
from typing import Any, ClassVar, Dict, List, Optional
+from opal_security.models.resource_remote_info_alicloud_ecs_instance import ResourceRemoteInfoAlicloudEcsInstance
+from opal_security.models.resource_remote_info_alicloud_ram_role import ResourceRemoteInfoAlicloudRamRole
from opal_security.models.resource_remote_info_anthropic_workspace import ResourceRemoteInfoAnthropicWorkspace
from opal_security.models.resource_remote_info_aws_account import ResourceRemoteInfoAwsAccount
from opal_security.models.resource_remote_info_aws_ec2_instance import ResourceRemoteInfoAwsEc2Instance
@@ -171,8 +173,10 @@ class ResourceRemoteInfo(BaseModel):
grafana_role: Optional[ResourceRemoteInfoGrafanaRole] = None
zendesk_role: Optional[ResourceRemoteInfoZendeskRole] = None
hubspot_role: Optional[ResourceRemoteInfoHubspotRole] = None
+ alicloud_ram_role: Optional[ResourceRemoteInfoAlicloudRamRole] = None
+ alicloud_ecs_instance: Optional[ResourceRemoteInfoAlicloudEcsInstance] = None
additional_properties: Dict[str, Any] = {}
- __properties: ClassVar[List[str]] = ["databricks_account_service_principal", "azure_subscription", "azure_resource_group", "azure_management_group", "azure_virtual_machine", "azure_storage_account", "azure_storage_container", "azure_sql_server", "azure_sql_database", "azure_sql_managed_instance", "azure_sql_managed_database", "azure_user_assigned_managed_identity", "azure_enterprise_app", "azure_entra_id_role", "aws_organizational_unit", "aws_account", "aws_permission_set", "aws_iam_role", "aws_ec2_instance", "aws_rds_cluster", "aws_rds_instance", "aws_eks_cluster", "custom_connector", "gcp_organization", "gcp_bucket", "gcp_compute_instance", "gcp_big_query_dataset", "gcp_big_query_table", "gcp_folder", "gcp_gke_cluster", "gcp_project", "gcp_sql_instance", "gcp_service_account", "google_workspace_role", "github_repo", "github_org_role", "github_org", "github_enterprise_role", "gitlab_project", "okta_app", "okta_standard_role", "okta_custom_role", "snowflake_database", "snowflake_schema", "snowflake_table", "ilevel_advanced_role", "tailscale_ssh", "twingate_resource", "pagerduty_role", "workday_role", "salesforce_permission_set", "salesforce_profile", "salesforce_role", "teleport_role", "datastax_astra_role", "coupa_role", "cursor_organization", "openai_platform_project", "openai_platform_service_account", "anthropic_workspace", "oracle_fusion_role", "devin_organization", "devin_role", "netsuite_role", "datadog_role", "clickhouse_database", "clickhouse_table", "grafana_folder", "grafana_dashboard", "grafana_role", "zendesk_role", "hubspot_role"]
+ __properties: ClassVar[List[str]] = ["databricks_account_service_principal", "azure_subscription", "azure_resource_group", "azure_management_group", "azure_virtual_machine", "azure_storage_account", "azure_storage_container", "azure_sql_server", "azure_sql_database", "azure_sql_managed_instance", "azure_sql_managed_database", "azure_user_assigned_managed_identity", "azure_enterprise_app", "azure_entra_id_role", "aws_organizational_unit", "aws_account", "aws_permission_set", "aws_iam_role", "aws_ec2_instance", "aws_rds_cluster", "aws_rds_instance", "aws_eks_cluster", "custom_connector", "gcp_organization", "gcp_bucket", "gcp_compute_instance", "gcp_big_query_dataset", "gcp_big_query_table", "gcp_folder", "gcp_gke_cluster", "gcp_project", "gcp_sql_instance", "gcp_service_account", "google_workspace_role", "github_repo", "github_org_role", "github_org", "github_enterprise_role", "gitlab_project", "okta_app", "okta_standard_role", "okta_custom_role", "snowflake_database", "snowflake_schema", "snowflake_table", "ilevel_advanced_role", "tailscale_ssh", "twingate_resource", "pagerduty_role", "workday_role", "salesforce_permission_set", "salesforce_profile", "salesforce_role", "teleport_role", "datastax_astra_role", "coupa_role", "cursor_organization", "openai_platform_project", "openai_platform_service_account", "anthropic_workspace", "oracle_fusion_role", "devin_organization", "devin_role", "netsuite_role", "datadog_role", "clickhouse_database", "clickhouse_table", "grafana_folder", "grafana_dashboard", "grafana_role", "zendesk_role", "hubspot_role", "alicloud_ram_role", "alicloud_ecs_instance"]
model_config = ConfigDict(
populate_by_name=True,
@@ -431,6 +435,12 @@ def to_dict(self) -> Dict[str, Any]:
# override the default output from pydantic by calling `to_dict()` of hubspot_role
if self.hubspot_role:
_dict['hubspot_role'] = self.hubspot_role.to_dict()
+ # override the default output from pydantic by calling `to_dict()` of alicloud_ram_role
+ if self.alicloud_ram_role:
+ _dict['alicloud_ram_role'] = self.alicloud_ram_role.to_dict()
+ # override the default output from pydantic by calling `to_dict()` of alicloud_ecs_instance
+ if self.alicloud_ecs_instance:
+ _dict['alicloud_ecs_instance'] = self.alicloud_ecs_instance.to_dict()
# puts key-value pairs in additional_properties in the top level
if self.additional_properties is not None:
for _key, _value in self.additional_properties.items():
@@ -519,7 +529,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"grafana_dashboard": ResourceRemoteInfoGrafanaDashboard.from_dict(obj["grafana_dashboard"]) if obj.get("grafana_dashboard") is not None else None,
"grafana_role": ResourceRemoteInfoGrafanaRole.from_dict(obj["grafana_role"]) if obj.get("grafana_role") is not None else None,
"zendesk_role": ResourceRemoteInfoZendeskRole.from_dict(obj["zendesk_role"]) if obj.get("zendesk_role") is not None else None,
- "hubspot_role": ResourceRemoteInfoHubspotRole.from_dict(obj["hubspot_role"]) if obj.get("hubspot_role") is not None else None
+ "hubspot_role": ResourceRemoteInfoHubspotRole.from_dict(obj["hubspot_role"]) if obj.get("hubspot_role") is not None else None,
+ "alicloud_ram_role": ResourceRemoteInfoAlicloudRamRole.from_dict(obj["alicloud_ram_role"]) if obj.get("alicloud_ram_role") is not None else None,
+ "alicloud_ecs_instance": ResourceRemoteInfoAlicloudEcsInstance.from_dict(obj["alicloud_ecs_instance"]) if obj.get("alicloud_ecs_instance") is not None else None
})
# store additional fields in additional_properties
for _key in obj.keys():
diff --git a/opal_security/models/resource_remote_info_alicloud_ecs_instance.py b/opal_security/models/resource_remote_info_alicloud_ecs_instance.py
new file mode 100644
index 0000000..9dfe5f2
--- /dev/null
+++ b/opal_security/models/resource_remote_info_alicloud_ecs_instance.py
@@ -0,0 +1,101 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing import Any, ClassVar, Dict, List
+from typing import Optional, Set
+from typing_extensions import Self
+
+class ResourceRemoteInfoAlicloudEcsInstance(BaseModel):
+ """
+ Remote info for AliCloud ECS instance.
+ """ # noqa: E501
+ instance_id: StrictStr = Field(description="The ID of the ECS instance.")
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["instance_id"]
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of ResourceRemoteInfoAlicloudEcsInstance from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of ResourceRemoteInfoAlicloudEcsInstance from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "instance_id": obj.get("instance_id")
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/resource_remote_info_alicloud_ram_role.py b/opal_security/models/resource_remote_info_alicloud_ram_role.py
new file mode 100644
index 0000000..65b263d
--- /dev/null
+++ b/opal_security/models/resource_remote_info_alicloud_ram_role.py
@@ -0,0 +1,101 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing import Any, ClassVar, Dict, List
+from typing import Optional, Set
+from typing_extensions import Self
+
+class ResourceRemoteInfoAlicloudRamRole(BaseModel):
+ """
+ Remote info for AliCloud RAM role.
+ """ # noqa: E501
+ role_arn: StrictStr = Field(description="The ARN of the AliCloud RAM role.")
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["role_arn"]
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of ResourceRemoteInfoAlicloudRamRole from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of ResourceRemoteInfoAlicloudRamRole from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "role_arn": obj.get("role_arn")
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/resource_type_enum.py b/opal_security/models/resource_type_enum.py
index f95a03a..c3a6656 100644
--- a/opal_security/models/resource_type_enum.py
+++ b/opal_security/models/resource_type_enum.py
@@ -113,6 +113,8 @@ class ResourceTypeEnum(str, Enum):
TWINGATE_RESOURCE = 'TWINGATE_RESOURCE'
ZENDESK_ROLE = 'ZENDESK_ROLE'
HUBSPOT_ROLE = 'HUBSPOT_ROLE'
+ ALICLOUD_RAM_ROLE = 'ALICLOUD_RAM_ROLE'
+ ALICLOUD_ECS_INSTANCE = 'ALICLOUD_ECS_INSTANCE'
@classmethod
def from_json(cls, json_str: str) -> Self:
diff --git a/opal_security/models/run_opal_query_request.py b/opal_security/models/run_opal_query_request.py
new file mode 100644
index 0000000..207f4c7
--- /dev/null
+++ b/opal_security/models/run_opal_query_request.py
@@ -0,0 +1,141 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import json
+import pprint
+from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator
+from typing import Any, List, Optional
+from opal_security.models.opal_access_path_query import OpalAccessPathQuery
+from opal_security.models.opal_node_query import OpalNodeQuery
+from pydantic import StrictStr, Field
+from typing import Union, List, Set, Optional, Dict
+from typing_extensions import Literal, Self
+
+RUNOPALQUERYREQUEST_ONE_OF_SCHEMAS = ["OpalAccessPathQuery", "OpalNodeQuery"]
+
+class RunOpalQueryRequest(BaseModel):
+ """
+ Request body for running an ad-hoc OpalQuery. The `type` field determines which query schema applies.
+ """
+ # data type: OpalNodeQuery
+ oneof_schema_1_validator: Optional[OpalNodeQuery] = None
+ # data type: OpalAccessPathQuery
+ oneof_schema_2_validator: Optional[OpalAccessPathQuery] = None
+ actual_instance: Optional[Union[OpalAccessPathQuery, OpalNodeQuery]] = None
+ one_of_schemas: Set[str] = { "OpalAccessPathQuery", "OpalNodeQuery" }
+
+ model_config = ConfigDict(
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ discriminator_value_class_map: Dict[str, str] = {
+ }
+
+ def __init__(self, *args, **kwargs) -> None:
+ if args:
+ if len(args) > 1:
+ raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`")
+ if kwargs:
+ raise ValueError("If a position argument is used, keyword arguments cannot be used.")
+ super().__init__(actual_instance=args[0])
+ else:
+ super().__init__(**kwargs)
+
+ @field_validator('actual_instance')
+ def actual_instance_must_validate_oneof(cls, v):
+ instance = RunOpalQueryRequest.model_construct()
+ error_messages = []
+ match = 0
+ # validate data type: OpalNodeQuery
+ if not isinstance(v, OpalNodeQuery):
+ error_messages.append(f"Error! Input type `{type(v)}` is not `OpalNodeQuery`")
+ else:
+ match += 1
+ # validate data type: OpalAccessPathQuery
+ if not isinstance(v, OpalAccessPathQuery):
+ error_messages.append(f"Error! Input type `{type(v)}` is not `OpalAccessPathQuery`")
+ else:
+ match += 1
+ if match > 1:
+ # more than 1 match
+ raise ValueError("Multiple matches found when setting `actual_instance` in RunOpalQueryRequest with oneOf schemas: OpalAccessPathQuery, OpalNodeQuery. Details: " + ", ".join(error_messages))
+ elif match == 0:
+ # no match
+ raise ValueError("No match found when setting `actual_instance` in RunOpalQueryRequest with oneOf schemas: OpalAccessPathQuery, OpalNodeQuery. Details: " + ", ".join(error_messages))
+ else:
+ return v
+
+ @classmethod
+ def from_dict(cls, obj: Union[str, Dict[str, Any]]) -> Self:
+ return cls.from_json(json.dumps(obj))
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Self:
+ """Returns the object represented by the json string"""
+ instance = cls.model_construct()
+ error_messages = []
+ match = 0
+
+ # deserialize data into OpalNodeQuery
+ try:
+ instance.actual_instance = OpalNodeQuery.from_json(json_str)
+ match += 1
+ except (ValidationError, ValueError) as e:
+ error_messages.append(str(e))
+ # deserialize data into OpalAccessPathQuery
+ try:
+ instance.actual_instance = OpalAccessPathQuery.from_json(json_str)
+ match += 1
+ except (ValidationError, ValueError) as e:
+ error_messages.append(str(e))
+
+ if match > 1:
+ # more than 1 match
+ raise ValueError("Multiple matches found when deserializing the JSON string into RunOpalQueryRequest with oneOf schemas: OpalAccessPathQuery, OpalNodeQuery. Details: " + ", ".join(error_messages))
+ elif match == 0:
+ # no match
+ raise ValueError("No match found when deserializing the JSON string into RunOpalQueryRequest with oneOf schemas: OpalAccessPathQuery, OpalNodeQuery. Details: " + ", ".join(error_messages))
+ else:
+ return instance
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the actual instance"""
+ if self.actual_instance is None:
+ return "null"
+
+ if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json):
+ return self.actual_instance.to_json()
+ else:
+ return json.dumps(self.actual_instance)
+
+ def to_dict(self) -> Optional[Union[Dict[str, Any], OpalAccessPathQuery, OpalNodeQuery]]:
+ """Returns the dict representation of the actual instance"""
+ if self.actual_instance is None:
+ return None
+
+ if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict):
+ return self.actual_instance.to_dict()
+ else:
+ # primitive type
+ return self.actual_instance
+
+ def to_str(self) -> str:
+ """Returns the string representation of the actual instance"""
+ return pprint.pformat(self.model_dump())
+
+
diff --git a/opal_security/models/stop_campaign_request.py b/opal_security/models/stop_campaign_request.py
new file mode 100644
index 0000000..e1e97f0
--- /dev/null
+++ b/opal_security/models/stop_campaign_request.py
@@ -0,0 +1,101 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from pydantic import BaseModel, ConfigDict, Field, StrictBool
+from typing import Any, ClassVar, Dict, List, Optional
+from typing import Optional, Set
+from typing_extensions import Self
+
+class StopCampaignRequest(BaseModel):
+ """
+ StopCampaignRequest
+ """ # noqa: E501
+ revoke_unreviewed: Optional[StrictBool] = Field(default=False, description="Revoke all unreviewed access grants. Access grants with no reviewer decision will be immediately revoked.")
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["revoke_unreviewed"]
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of StopCampaignRequest from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of StopCampaignRequest from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "revoke_unreviewed": obj.get("revoke_unreviewed") if obj.get("revoke_unreviewed") is not None else False
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/update_campaign_configuration_info.py b/opal_security/models/update_campaign_configuration_info.py
new file mode 100644
index 0000000..ff36870
--- /dev/null
+++ b/opal_security/models/update_campaign_configuration_info.py
@@ -0,0 +1,132 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from datetime import datetime
+from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr
+from typing import Any, ClassVar, Dict, List, Optional
+from opal_security.models.campaign_group_asset_visibility_policy_enum import CampaignGroupAssetVisibilityPolicyEnum
+from opal_security.models.campaign_revoke_on_enum import CampaignRevokeOnEnum
+from typing import Optional, Set
+from typing_extensions import Self
+
+class UpdateCampaignConfigurationInfo(BaseModel):
+ """
+ Configuration fields to update on a campaign. All fields are optional; omitted fields are left unchanged. `query` and `reviewer_assignment_policy` are set at create time and cannot be updated here; including either field returns 400. `cron_expression` and `recurring_duration_days` may only be set when the campaign is a template; setting them on a one-off campaign returns 400. `is_template` is immutable and not accepted on update.
+ """ # noqa: E501
+ allow_self_review: Optional[StrictBool] = Field(default=None, description="Whether reviewers can review their own access.")
+ send_reviewer_assignment_notification: Optional[StrictBool] = Field(default=None, description="Whether to notify reviewers upon assignment.")
+ allow_reviewer_reassignment: Optional[StrictBool] = Field(default=None, description="Whether reviewers may reassign their reviews to another user.")
+ start_date: Optional[datetime] = Field(default=None, description="Scheduled start date of the campaign. May only be updated while the campaign has not started (started_at is null). When set, the date's calendar day in the campaign timezone must be at least tomorrow. ")
+ end_date: Optional[datetime] = Field(default=None, description="Scheduled end date of the campaign. When set, the date's calendar day in the campaign timezone must be at least tomorrow. ")
+ timezone: Optional[StrictStr] = Field(default=None, description="IANA timezone used to interpret campaign deadlines (e.g. America/Los_Angeles).")
+ revoke_on: Optional[CampaignRevokeOnEnum] = None
+ reminder_schedule: Optional[List[StrictInt]] = Field(default=None, description="Days before end date to send reminder notifications.")
+ reminder_include_manager: Optional[StrictBool] = Field(default=None, description="Whether to include the reviewer's manager in reminders.")
+ require_reason_on_denial: Optional[StrictBool] = Field(default=None, description="Whether reviewers must provide a reason when denying (revoking) access.")
+ hide_ai_suggestions: Optional[StrictBool] = Field(default=None, description="Whether AI suggestions are hidden from reviewers.")
+ custom_start_message: Optional[StrictStr] = Field(default=None, description="Optional custom message included when notifying reviewers that the campaign started.")
+ group_asset_visibility_policy: Optional[CampaignGroupAssetVisibilityPolicyEnum] = None
+ cron_expression: Optional[StrictStr] = Field(default=None, description="Cron expression driving the recurring schedule. Only valid on template campaigns. Pass an empty string to clear the active months (next_scheduled_run is cleared); the campaign remains a template.")
+ recurring_duration_days: Optional[StrictInt] = Field(default=None, description="Deadline window in days applied to each draft generated from this template. Only valid on template campaigns.")
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["allow_self_review", "send_reviewer_assignment_notification", "allow_reviewer_reassignment", "start_date", "end_date", "timezone", "revoke_on", "reminder_schedule", "reminder_include_manager", "require_reason_on_denial", "hide_ai_suggestions", "custom_start_message", "group_asset_visibility_policy", "cron_expression", "recurring_duration_days"]
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of UpdateCampaignConfigurationInfo from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of UpdateCampaignConfigurationInfo from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "allow_self_review": obj.get("allow_self_review"),
+ "send_reviewer_assignment_notification": obj.get("send_reviewer_assignment_notification"),
+ "allow_reviewer_reassignment": obj.get("allow_reviewer_reassignment"),
+ "start_date": obj.get("start_date"),
+ "end_date": obj.get("end_date"),
+ "timezone": obj.get("timezone"),
+ "revoke_on": obj.get("revoke_on"),
+ "reminder_schedule": obj.get("reminder_schedule"),
+ "reminder_include_manager": obj.get("reminder_include_manager"),
+ "require_reason_on_denial": obj.get("require_reason_on_denial"),
+ "hide_ai_suggestions": obj.get("hide_ai_suggestions"),
+ "custom_start_message": obj.get("custom_start_message"),
+ "group_asset_visibility_policy": obj.get("group_asset_visibility_policy"),
+ "cron_expression": obj.get("cron_expression"),
+ "recurring_duration_days": obj.get("recurring_duration_days")
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/update_campaign_info.py b/opal_security/models/update_campaign_info.py
new file mode 100644
index 0000000..ceff325
--- /dev/null
+++ b/opal_security/models/update_campaign_info.py
@@ -0,0 +1,107 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+from __future__ import annotations
+import pprint
+import re # noqa: F401
+import json
+
+from pydantic import BaseModel, ConfigDict, Field, StrictStr
+from typing import Any, ClassVar, Dict, List, Optional
+from opal_security.models.update_campaign_configuration_info import UpdateCampaignConfigurationInfo
+from typing import Optional, Set
+from typing_extensions import Self
+
+class UpdateCampaignInfo(BaseModel):
+ """
+ # UpdateCampaignInfo Object ### Description The `UpdateCampaignInfo` object is used to partially update a campaign. Omitted fields are left unchanged. ### Usage Example Use in the `PUT Campaign` endpoint.
+ """ # noqa: E501
+ name: Optional[StrictStr] = Field(default=None, description="The name of the campaign.")
+ configuration: Optional[UpdateCampaignConfigurationInfo] = Field(default=None, description="Configuration fields to create or update.")
+ additional_properties: Dict[str, Any] = {}
+ __properties: ClassVar[List[str]] = ["name", "configuration"]
+
+ model_config = ConfigDict(
+ populate_by_name=True,
+ validate_assignment=True,
+ protected_namespaces=(),
+ )
+
+
+ def to_str(self) -> str:
+ """Returns the string representation of the model using alias"""
+ return pprint.pformat(self.model_dump(by_alias=True))
+
+ def to_json(self) -> str:
+ """Returns the JSON representation of the model using alias"""
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
+ return json.dumps(self.to_dict())
+
+ @classmethod
+ def from_json(cls, json_str: str) -> Optional[Self]:
+ """Create an instance of UpdateCampaignInfo from a JSON string"""
+ return cls.from_dict(json.loads(json_str))
+
+ def to_dict(self) -> Dict[str, Any]:
+ """Return the dictionary representation of the model using alias.
+
+ This has the following differences from calling pydantic's
+ `self.model_dump(by_alias=True)`:
+
+ * `None` is only added to the output dict for nullable fields that
+ were set at model initialization. Other fields with value `None`
+ are ignored.
+ * Fields in `self.additional_properties` are added to the output dict.
+ """
+ excluded_fields: Set[str] = set([
+ "additional_properties",
+ ])
+
+ _dict = self.model_dump(
+ by_alias=True,
+ exclude=excluded_fields,
+ exclude_none=True,
+ )
+ # override the default output from pydantic by calling `to_dict()` of configuration
+ if self.configuration:
+ _dict['configuration'] = self.configuration.to_dict()
+ # puts key-value pairs in additional_properties in the top level
+ if self.additional_properties is not None:
+ for _key, _value in self.additional_properties.items():
+ _dict[_key] = _value
+
+ return _dict
+
+ @classmethod
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
+ """Create an instance of UpdateCampaignInfo from a dict"""
+ if obj is None:
+ return None
+
+ if not isinstance(obj, dict):
+ return cls.model_validate(obj)
+
+ _obj = cls.model_validate({
+ "name": obj.get("name"),
+ "configuration": UpdateCampaignConfigurationInfo.from_dict(obj["configuration"]) if obj.get("configuration") is not None else None
+ })
+ # store additional fields in additional_properties
+ for _key in obj.keys():
+ if _key not in cls.__properties:
+ _obj.additional_properties[_key] = obj.get(_key)
+
+ return _obj
+
+
diff --git a/opal_security/models/update_group_info.py b/opal_security/models/update_group_info.py
index 3893c1f..53b926b 100644
--- a/opal_security/models/update_group_info.py
+++ b/opal_security/models/update_group_info.py
@@ -53,8 +53,10 @@ class UpdateGroupInfo(BaseModel):
request_configuration_list: Optional[CreateRequestConfigurationInfoList] = Field(default=None, description="The request configuration list of the configuration template. If not provided, the default request configuration will be used. Deprecated in favor of `request_configurations`.")
custom_request_notification: Optional[Annotated[str, Field(strict=True, max_length=800)]] = Field(default=None, description="Custom request notification sent to the requester when the request is approved.")
risk_sensitivity_override: Optional[RiskSensitivityEnum] = None
+ match_remote_name: Optional[StrictBool] = Field(default=None, description="A bool representing whether or not the group's name should be synced from the end system. When true, the name is overwritten with the remote name on each sync, so a `name` provided together with this field set to true will be replaced at the next sync. If not provided, the current value is left unchanged.")
+ match_remote_description: Optional[StrictBool] = Field(default=None, description="A bool representing whether or not the group's description should be synced from the end system. When true, the description is overwritten with the remote description on each sync, so a `description` provided together with this field set to true will be replaced at the next sync. If not provided, the current value is left unchanged.")
additional_properties: Dict[str, Any] = {}
- __properties: ClassVar[List[str]] = ["group_id", "name", "description", "admin_owner_id", "max_duration", "recommended_duration", "require_manager_approval", "require_support_ticket", "folder_id", "require_mfa_to_approve", "require_mfa_to_request", "auto_approval", "configuration_template_id", "request_template_id", "is_requestable", "group_leader_user_ids", "extensions_duration_in_minutes", "request_configurations", "request_configuration_list", "custom_request_notification", "risk_sensitivity_override"]
+ __properties: ClassVar[List[str]] = ["group_id", "name", "description", "admin_owner_id", "max_duration", "recommended_duration", "require_manager_approval", "require_support_ticket", "folder_id", "require_mfa_to_approve", "require_mfa_to_request", "auto_approval", "configuration_template_id", "request_template_id", "is_requestable", "group_leader_user_ids", "extensions_duration_in_minutes", "request_configurations", "request_configuration_list", "custom_request_notification", "risk_sensitivity_override", "match_remote_name", "match_remote_description"]
model_config = ConfigDict(
populate_by_name=True,
@@ -144,7 +146,9 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"request_configurations": [RequestConfiguration.from_dict(_item) for _item in obj["request_configurations"]] if obj.get("request_configurations") is not None else None,
"request_configuration_list": CreateRequestConfigurationInfoList.from_dict(obj["request_configuration_list"]) if obj.get("request_configuration_list") is not None else None,
"custom_request_notification": obj.get("custom_request_notification"),
- "risk_sensitivity_override": obj.get("risk_sensitivity_override")
+ "risk_sensitivity_override": obj.get("risk_sensitivity_override"),
+ "match_remote_name": obj.get("match_remote_name"),
+ "match_remote_description": obj.get("match_remote_description")
})
# store additional fields in additional_properties
for _key in obj.keys():
diff --git a/opal_security/models/update_resource_info.py b/opal_security/models/update_resource_info.py
index 6c46b86..f0a28a0 100644
--- a/opal_security/models/update_resource_info.py
+++ b/opal_security/models/update_resource_info.py
@@ -49,6 +49,8 @@ class UpdateResourceInfo(BaseModel):
ticket_propagation: Optional[TicketPropagationConfiguration] = None
custom_request_notification: Optional[Annotated[str, Field(strict=True, max_length=800)]] = Field(default=None, description="Custom request notification sent upon request approval.")
risk_sensitivity_override: Optional[RiskSensitivityEnum] = None
+ match_remote_name: Optional[StrictBool] = Field(default=None, description="A bool representing whether or not the resource's name should be synced from the end system. When true, the name is overwritten with the remote name on each sync, so a `name` provided together with this field set to true will be replaced at the next sync. If not provided, the current value is left unchanged.")
+ match_remote_description: Optional[StrictBool] = Field(default=None, description="A bool representing whether or not the resource's description should be synced from the end system. When true, the description is overwritten with the remote description on each sync, so a `description` provided together with this field set to true will be replaced at the next sync. If not provided, the current value is left unchanged.")
configuration_template_id: Optional[UUID] = Field(default=None, description="The ID of the associated configuration template.")
request_template_id: Optional[UUID] = Field(default=None, description="The ID of the associated request template. Deprecated in favor of `request_configurations`.")
is_requestable: Optional[StrictBool] = Field(default=None, description="A bool representing whether or not to allow access requests to this resource. Deprecated in favor of `request_configurations`.")
@@ -57,7 +59,7 @@ class UpdateResourceInfo(BaseModel):
request_configurations: Optional[List[RequestConfiguration]] = Field(default=None, description="A list of configurations for requests to this resource. If not provided, the default request configuration will be used.")
request_configuration_list: Optional[CreateRequestConfigurationInfoList] = Field(default=None, description="A list of configurations for requests to this resource. If not provided, the default request configuration will be used. Deprecated in favor of `request_configurations`.")
additional_properties: Dict[str, Any] = {}
- __properties: ClassVar[List[str]] = ["resource_id", "name", "description", "admin_owner_id", "max_duration", "recommended_duration", "require_manager_approval", "require_support_ticket", "folder_id", "require_mfa_to_approve", "require_mfa_to_request", "require_mfa_to_connect", "auto_approval", "ticket_propagation", "custom_request_notification", "risk_sensitivity_override", "configuration_template_id", "request_template_id", "is_requestable", "extensions_duration_in_minutes", "parent_resource_id", "request_configurations", "request_configuration_list"]
+ __properties: ClassVar[List[str]] = ["resource_id", "name", "description", "admin_owner_id", "max_duration", "recommended_duration", "require_manager_approval", "require_support_ticket", "folder_id", "require_mfa_to_approve", "require_mfa_to_request", "require_mfa_to_connect", "auto_approval", "ticket_propagation", "custom_request_notification", "risk_sensitivity_override", "match_remote_name", "match_remote_description", "configuration_template_id", "request_template_id", "is_requestable", "extensions_duration_in_minutes", "parent_resource_id", "request_configurations", "request_configuration_list"]
model_config = ConfigDict(
populate_by_name=True,
@@ -146,6 +148,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
"ticket_propagation": TicketPropagationConfiguration.from_dict(obj["ticket_propagation"]) if obj.get("ticket_propagation") is not None else None,
"custom_request_notification": obj.get("custom_request_notification"),
"risk_sensitivity_override": obj.get("risk_sensitivity_override"),
+ "match_remote_name": obj.get("match_remote_name"),
+ "match_remote_description": obj.get("match_remote_description"),
"configuration_template_id": obj.get("configuration_template_id"),
"request_template_id": obj.get("request_template_id"),
"is_requestable": obj.get("is_requestable"),
diff --git a/test/test_campaign.py b/test/test_campaign.py
new file mode 100644
index 0000000..f262e1b
--- /dev/null
+++ b/test/test_campaign.py
@@ -0,0 +1,72 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.campaign import Campaign
+
+class TestCampaign(unittest.TestCase):
+ """Campaign unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> Campaign:
+ """Test Campaign
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `Campaign`
+ """
+ model = Campaign()
+ if include_optional:
+ return Campaign(
+ campaign_id = 'f454d283-ca87-4a8a-bdbb-df212eca5353',
+ name = 'Q3 Access Review',
+ status = 'ONGOING',
+ is_template = False,
+ created_at = '2026-07-01T00:00:00.000+00:00',
+ updated_at = '2026-07-01T00:00:00.000+00:00',
+ created_by_user_id = '32acc112-21ff-4669-91c2-21e27683eaa1',
+ configuration = {configuration_id=39a4d283-ca87-4a8a-bdbb-df212eca5fdb, created_at=2026-07-01T00:00:00.000+00:00, updated_at=2026-07-01T00:00:00.000+00:00, reviewer_assignment_policy=MANUALLY, allow_self_review=false, send_reviewer_assignment_notification=true, allow_reviewer_reassignment=false, end_date=2026-09-30T00:00:00.000+00:00, timezone=America/Los_Angeles, revoke_on=END, reminder_schedule=[7, 3, 1], reminder_include_manager=true, require_reason_on_denial=false, hide_ai_suggestions=false, group_asset_visibility_policy=STRICT, is_template=false},
+ started_at = '2026-07-02T00:00:00.000+00:00',
+ started_by_user_id = '32acc112-21ff-4669-91c2-21e27683eaa1',
+ stopped_at = '2026-07-10T00:00:00.000+00:00',
+ stopped_by_user_id = '32acc112-21ff-4669-91c2-21e27683eaa1',
+ ended_at = '2026-07-14T00:00:00.000+00:00',
+ ended_by_user_id = '32acc112-21ff-4669-91c2-21e27683eaa1'
+ )
+ else:
+ return Campaign(
+ campaign_id = 'f454d283-ca87-4a8a-bdbb-df212eca5353',
+ name = 'Q3 Access Review',
+ status = 'ONGOING',
+ is_template = False,
+ created_at = '2026-07-01T00:00:00.000+00:00',
+ updated_at = '2026-07-01T00:00:00.000+00:00',
+ created_by_user_id = '32acc112-21ff-4669-91c2-21e27683eaa1',
+ )
+ """
+
+ def testCampaign(self):
+ """Test Campaign"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_campaign_configuration.py b/test/test_campaign_configuration.py
new file mode 100644
index 0000000..515511a
--- /dev/null
+++ b/test/test_campaign_configuration.py
@@ -0,0 +1,147 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.campaign_configuration import CampaignConfiguration
+
+class TestCampaignConfiguration(unittest.TestCase):
+ """CampaignConfiguration unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> CampaignConfiguration:
+ """Test CampaignConfiguration
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `CampaignConfiguration`
+ """
+ model = CampaignConfiguration()
+ if include_optional:
+ return CampaignConfiguration(
+ configuration_id = '39a4d283-ca87-4a8a-bdbb-df212eca5fdb',
+ created_at = '2026-07-01T00:00:00.000+00:00',
+ updated_at = '2026-07-01T00:00:00.000+00:00',
+ query = opal_security.models.opal_access_path_query_body.OpalAccessPathQueryBody(
+ principal_filter = opal_security.models.access_entity_filters.AccessEntityFilters(
+ entity_types = [
+ 'RESOURCE'
+ ],
+ entity_item_types = [
+ 'OPAL_ROLE'
+ ],
+ entity_name = opal_security.models.entity_name_filter.EntityNameFilter(
+ string_match_type = 'CONTAINS',
+ string = 'engineering', ),
+ entity_tag = opal_security.models.entity_tag_filter.EntityTagFilter(
+ key = 'team',
+ value = 'platform',
+ connection_id = '', ),
+ hr_idp_status = opal_security.models.idp_status_filter.IdpStatusFilter(
+ statuses = [
+ 'ACTIVE'
+ ],
+ not = True, ),
+ entity_admin_owner = opal_security.models.entity_admin_filter.EntityAdminFilter(
+ owner_ids = [
+ ''
+ ],
+ not = True, ),
+ entity_ids = [
+ ''
+ ],
+ imported_from_app = [
+ ''
+ ],
+ role_remote_ids = [
+ ''
+ ],
+ role_names = [
+ ''
+ ],
+ all_of = [
+ opal_security.models.access_entity_filters.AccessEntityFilters(
+ any_of = [
+
+ ],
+ not = opal_security.models.not.not(), )
+ ],
+ any_of = [
+
+ ],
+ not = opal_security.models.not.not(), ),
+ entitlement_filter = ,
+ principal_access_filters = null,
+ entitlement_access_filters = null,
+ access_level_remote_ids = [
+ ''
+ ],
+ access_level_names = [
+ ''
+ ],
+ edge_filter = opal_security.models.opal_access_path_edge_filter.OpalAccessPathEdgeFilter(
+ direct_only = True,
+ access_duration_type = 'EXPIRING_ONLY', ), ),
+ reviewer_assignment_policy = 'MANUALLY',
+ allow_self_review = False,
+ send_reviewer_assignment_notification = True,
+ allow_reviewer_reassignment = False,
+ start_date = '2026-07-02T00:00:00.000+00:00',
+ end_date = '2026-09-30T00:00:00.000+00:00',
+ timezone = 'America/Los_Angeles',
+ revoke_on = 'END',
+ reminder_schedule = [7, 3, 1],
+ reminder_include_manager = True,
+ require_reason_on_denial = False,
+ hide_ai_suggestions = False,
+ custom_start_message = 'Please complete your reviews by Friday.',
+ group_asset_visibility_policy = 'STRICT',
+ is_template = False,
+ cron_expression = '0 9 1 * *',
+ next_scheduled_run = '2026-08-01T16:00:00.000+00:00',
+ last_scheduled_run = '2026-07-01T16:00:00.000+00:00',
+ recurring_duration_days = 14
+ )
+ else:
+ return CampaignConfiguration(
+ configuration_id = '39a4d283-ca87-4a8a-bdbb-df212eca5fdb',
+ created_at = '2026-07-01T00:00:00.000+00:00',
+ updated_at = '2026-07-01T00:00:00.000+00:00',
+ reviewer_assignment_policy = 'MANUALLY',
+ allow_self_review = False,
+ send_reviewer_assignment_notification = True,
+ allow_reviewer_reassignment = False,
+ timezone = 'America/Los_Angeles',
+ revoke_on = 'END',
+ reminder_include_manager = True,
+ require_reason_on_denial = False,
+ hide_ai_suggestions = False,
+ group_asset_visibility_policy = 'STRICT',
+ is_template = False,
+ )
+ """
+
+ def testCampaignConfiguration(self):
+ """Test CampaignConfiguration"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_campaign_group_asset_visibility_policy_enum.py b/test/test_campaign_group_asset_visibility_policy_enum.py
new file mode 100644
index 0000000..e7fe747
--- /dev/null
+++ b/test/test_campaign_group_asset_visibility_policy_enum.py
@@ -0,0 +1,34 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.campaign_group_asset_visibility_policy_enum import CampaignGroupAssetVisibilityPolicyEnum
+
+class TestCampaignGroupAssetVisibilityPolicyEnum(unittest.TestCase):
+ """CampaignGroupAssetVisibilityPolicyEnum unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def testCampaignGroupAssetVisibilityPolicyEnum(self):
+ """Test CampaignGroupAssetVisibilityPolicyEnum"""
+ # inst = CampaignGroupAssetVisibilityPolicyEnum()
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_campaign_revoke_on_enum.py b/test/test_campaign_revoke_on_enum.py
new file mode 100644
index 0000000..cdde5a0
--- /dev/null
+++ b/test/test_campaign_revoke_on_enum.py
@@ -0,0 +1,34 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.campaign_revoke_on_enum import CampaignRevokeOnEnum
+
+class TestCampaignRevokeOnEnum(unittest.TestCase):
+ """CampaignRevokeOnEnum unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def testCampaignRevokeOnEnum(self):
+ """Test CampaignRevokeOnEnum"""
+ # inst = CampaignRevokeOnEnum()
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_campaign_status_enum.py b/test/test_campaign_status_enum.py
new file mode 100644
index 0000000..d2b1c42
--- /dev/null
+++ b/test/test_campaign_status_enum.py
@@ -0,0 +1,34 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.campaign_status_enum import CampaignStatusEnum
+
+class TestCampaignStatusEnum(unittest.TestCase):
+ """CampaignStatusEnum unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def testCampaignStatusEnum(self):
+ """Test CampaignStatusEnum"""
+ # inst = CampaignStatusEnum()
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_campaigns_api.py b/test/test_campaigns_api.py
new file mode 100644
index 0000000..1217233
--- /dev/null
+++ b/test/test_campaigns_api.py
@@ -0,0 +1,79 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.api.campaigns_api import CampaignsApi
+
+
+class TestCampaignsApi(unittest.TestCase):
+ """CampaignsApi unit test stubs"""
+
+ def setUp(self) -> None:
+ self.api = CampaignsApi()
+
+ def tearDown(self) -> None:
+ pass
+
+ def test_create_campaign(self) -> None:
+ """Test case for create_campaign
+
+ """
+ pass
+
+ def test_end_campaign(self) -> None:
+ """Test case for end_campaign
+
+ End campaign
+ """
+ pass
+
+ def test_get_campaign(self) -> None:
+ """Test case for get_campaign
+
+ Get campaign by ID
+ """
+ pass
+
+ def test_get_campaigns(self) -> None:
+ """Test case for get_campaigns
+
+ """
+ pass
+
+ def test_start_campaign(self) -> None:
+ """Test case for start_campaign
+
+ Start campaign
+ """
+ pass
+
+ def test_stop_campaign(self) -> None:
+ """Test case for stop_campaign
+
+ Stop campaign
+ """
+ pass
+
+ def test_update_campaign(self) -> None:
+ """Test case for update_campaign
+
+ Update campaign
+ """
+ pass
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_create_campaign_configuration_info.py b/test/test_create_campaign_configuration_info.py
new file mode 100644
index 0000000..8bb4c92
--- /dev/null
+++ b/test/test_create_campaign_configuration_info.py
@@ -0,0 +1,191 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.create_campaign_configuration_info import CreateCampaignConfigurationInfo
+
+class TestCreateCampaignConfigurationInfo(unittest.TestCase):
+ """CreateCampaignConfigurationInfo unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> CreateCampaignConfigurationInfo:
+ """Test CreateCampaignConfigurationInfo
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `CreateCampaignConfigurationInfo`
+ """
+ model = CreateCampaignConfigurationInfo()
+ if include_optional:
+ return CreateCampaignConfigurationInfo(
+ query = opal_security.models.opal_access_path_query_body.OpalAccessPathQueryBody(
+ principal_filter = opal_security.models.access_entity_filters.AccessEntityFilters(
+ entity_types = [
+ 'RESOURCE'
+ ],
+ entity_item_types = [
+ 'OPAL_ROLE'
+ ],
+ entity_name = opal_security.models.entity_name_filter.EntityNameFilter(
+ string_match_type = 'CONTAINS',
+ string = 'engineering', ),
+ entity_tag = opal_security.models.entity_tag_filter.EntityTagFilter(
+ key = 'team',
+ value = 'platform',
+ connection_id = '', ),
+ hr_idp_status = opal_security.models.idp_status_filter.IdpStatusFilter(
+ statuses = [
+ 'ACTIVE'
+ ],
+ not = True, ),
+ entity_admin_owner = opal_security.models.entity_admin_filter.EntityAdminFilter(
+ owner_ids = [
+ ''
+ ],
+ not = True, ),
+ entity_ids = [
+ ''
+ ],
+ imported_from_app = [
+ ''
+ ],
+ role_remote_ids = [
+ ''
+ ],
+ role_names = [
+ ''
+ ],
+ all_of = [
+ opal_security.models.access_entity_filters.AccessEntityFilters(
+ any_of = [
+
+ ],
+ not = opal_security.models.not.not(), )
+ ],
+ any_of = [
+
+ ],
+ not = opal_security.models.not.not(), ),
+ entitlement_filter = ,
+ principal_access_filters = null,
+ entitlement_access_filters = null,
+ access_level_remote_ids = [
+ ''
+ ],
+ access_level_names = [
+ ''
+ ],
+ edge_filter = opal_security.models.opal_access_path_edge_filter.OpalAccessPathEdgeFilter(
+ direct_only = True,
+ access_duration_type = 'EXPIRING_ONLY', ), ),
+ reviewer_assignment_policy = 'MANUALLY',
+ allow_self_review = False,
+ send_reviewer_assignment_notification = True,
+ allow_reviewer_reassignment = False,
+ start_date = '2026-07-02T00:00:00.000+00:00',
+ end_date = '2026-09-30T00:00:00.000+00:00',
+ timezone = 'America/Los_Angeles',
+ revoke_on = 'END',
+ reminder_schedule = [7, 3, 1],
+ reminder_include_manager = True,
+ require_reason_on_denial = False,
+ hide_ai_suggestions = False,
+ custom_start_message = 'Please complete your reviews by Friday.',
+ group_asset_visibility_policy = 'STRICT',
+ is_template = False,
+ cron_expression = '0 9 1 * *',
+ recurring_duration_days = 14,
+ excluded_role_assignment_ids = [
+ ''
+ ]
+ )
+ else:
+ return CreateCampaignConfigurationInfo(
+ query = opal_security.models.opal_access_path_query_body.OpalAccessPathQueryBody(
+ principal_filter = opal_security.models.access_entity_filters.AccessEntityFilters(
+ entity_types = [
+ 'RESOURCE'
+ ],
+ entity_item_types = [
+ 'OPAL_ROLE'
+ ],
+ entity_name = opal_security.models.entity_name_filter.EntityNameFilter(
+ string_match_type = 'CONTAINS',
+ string = 'engineering', ),
+ entity_tag = opal_security.models.entity_tag_filter.EntityTagFilter(
+ key = 'team',
+ value = 'platform',
+ connection_id = '', ),
+ hr_idp_status = opal_security.models.idp_status_filter.IdpStatusFilter(
+ statuses = [
+ 'ACTIVE'
+ ],
+ not = True, ),
+ entity_admin_owner = opal_security.models.entity_admin_filter.EntityAdminFilter(
+ owner_ids = [
+ ''
+ ],
+ not = True, ),
+ entity_ids = [
+ ''
+ ],
+ imported_from_app = [
+ ''
+ ],
+ role_remote_ids = [
+ ''
+ ],
+ role_names = [
+ ''
+ ],
+ all_of = [
+ opal_security.models.access_entity_filters.AccessEntityFilters(
+ any_of = [
+
+ ],
+ not = opal_security.models.not.not(), )
+ ],
+ any_of = [
+
+ ],
+ not = opal_security.models.not.not(), ),
+ entitlement_filter = ,
+ principal_access_filters = null,
+ entitlement_access_filters = null,
+ access_level_remote_ids = [
+ ''
+ ],
+ access_level_names = [
+ ''
+ ],
+ edge_filter = opal_security.models.opal_access_path_edge_filter.OpalAccessPathEdgeFilter(
+ direct_only = True,
+ access_duration_type = 'EXPIRING_ONLY', ), ),
+ )
+ """
+
+ def testCreateCampaignConfigurationInfo(self):
+ """Test CreateCampaignConfigurationInfo"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_create_campaign_info.py b/test/test_create_campaign_info.py
new file mode 100644
index 0000000..661b7ca
--- /dev/null
+++ b/test/test_create_campaign_info.py
@@ -0,0 +1,55 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.create_campaign_info import CreateCampaignInfo
+
+class TestCreateCampaignInfo(unittest.TestCase):
+ """CreateCampaignInfo unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> CreateCampaignInfo:
+ """Test CreateCampaignInfo
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `CreateCampaignInfo`
+ """
+ model = CreateCampaignInfo()
+ if include_optional:
+ return CreateCampaignInfo(
+ name = 'Q3 Access Review',
+ configuration = {query={principalFilter={entityTypes=[USER]}}, end_date=2026-09-30T00:00:00.000+00:00, timezone=America/Los_Angeles, allow_self_review=false}
+ )
+ else:
+ return CreateCampaignInfo(
+ name = 'Q3 Access Review',
+ configuration = {query={principalFilter={entityTypes=[USER]}}, end_date=2026-09-30T00:00:00.000+00:00, timezone=America/Los_Angeles, allow_self_review=false},
+ )
+ """
+
+ def testCreateCampaignInfo(self):
+ """Test CreateCampaignInfo"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_entity_admin_filter.py b/test/test_entity_admin_filter.py
new file mode 100644
index 0000000..cb116f0
--- /dev/null
+++ b/test/test_entity_admin_filter.py
@@ -0,0 +1,58 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.entity_admin_filter import EntityAdminFilter
+
+class TestEntityAdminFilter(unittest.TestCase):
+ """EntityAdminFilter unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> EntityAdminFilter:
+ """Test EntityAdminFilter
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `EntityAdminFilter`
+ """
+ model = EntityAdminFilter()
+ if include_optional:
+ return EntityAdminFilter(
+ owner_ids = [
+ ''
+ ],
+ var_not = True
+ )
+ else:
+ return EntityAdminFilter(
+ owner_ids = [
+ ''
+ ],
+ )
+ """
+
+ def testEntityAdminFilter(self):
+ """Test EntityAdminFilter"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_group_remote_info_tableau_group.py b/test/test_group_remote_info_tableau_group.py
new file mode 100644
index 0000000..0e8a204
--- /dev/null
+++ b/test/test_group_remote_info_tableau_group.py
@@ -0,0 +1,53 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.group_remote_info_tableau_group import GroupRemoteInfoTableauGroup
+
+class TestGroupRemoteInfoTableauGroup(unittest.TestCase):
+ """GroupRemoteInfoTableauGroup unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> GroupRemoteInfoTableauGroup:
+ """Test GroupRemoteInfoTableauGroup
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `GroupRemoteInfoTableauGroup`
+ """
+ model = GroupRemoteInfoTableauGroup()
+ if include_optional:
+ return GroupRemoteInfoTableauGroup(
+ group_id = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
+ )
+ else:
+ return GroupRemoteInfoTableauGroup(
+ group_id = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
+ )
+ """
+
+ def testGroupRemoteInfoTableauGroup(self):
+ """Test GroupRemoteInfoTableauGroup"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_idp_status_filter.py b/test/test_idp_status_filter.py
new file mode 100644
index 0000000..5ee962a
--- /dev/null
+++ b/test/test_idp_status_filter.py
@@ -0,0 +1,55 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.idp_status_filter import IdpStatusFilter
+
+class TestIdpStatusFilter(unittest.TestCase):
+ """IdpStatusFilter unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> IdpStatusFilter:
+ """Test IdpStatusFilter
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `IdpStatusFilter`
+ """
+ model = IdpStatusFilter()
+ if include_optional:
+ return IdpStatusFilter(
+ statuses = [
+ 'ACTIVE'
+ ],
+ var_not = True
+ )
+ else:
+ return IdpStatusFilter(
+ )
+ """
+
+ def testIdpStatusFilter(self):
+ """Test IdpStatusFilter"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_opal_access_path_edge_filter.py b/test/test_opal_access_path_edge_filter.py
new file mode 100644
index 0000000..0a4b6cb
--- /dev/null
+++ b/test/test_opal_access_path_edge_filter.py
@@ -0,0 +1,53 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.opal_access_path_edge_filter import OpalAccessPathEdgeFilter
+
+class TestOpalAccessPathEdgeFilter(unittest.TestCase):
+ """OpalAccessPathEdgeFilter unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> OpalAccessPathEdgeFilter:
+ """Test OpalAccessPathEdgeFilter
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `OpalAccessPathEdgeFilter`
+ """
+ model = OpalAccessPathEdgeFilter()
+ if include_optional:
+ return OpalAccessPathEdgeFilter(
+ direct_only = True,
+ access_duration_type = 'EXPIRING_ONLY'
+ )
+ else:
+ return OpalAccessPathEdgeFilter(
+ )
+ """
+
+ def testOpalAccessPathEdgeFilter(self):
+ """Test OpalAccessPathEdgeFilter"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_opal_access_path_query.py b/test/test_opal_access_path_query.py
new file mode 100644
index 0000000..0772c51
--- /dev/null
+++ b/test/test_opal_access_path_query.py
@@ -0,0 +1,116 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.opal_access_path_query import OpalAccessPathQuery
+
+class TestOpalAccessPathQuery(unittest.TestCase):
+ """OpalAccessPathQuery unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> OpalAccessPathQuery:
+ """Test OpalAccessPathQuery
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `OpalAccessPathQuery`
+ """
+ model = OpalAccessPathQuery()
+ if include_optional:
+ return OpalAccessPathQuery(
+ type = 'ACCESS_PATH',
+ query = opal_security.models.opal_access_path_query_body.OpalAccessPathQueryBody(
+ principal_filter = opal_security.models.access_entity_filters.AccessEntityFilters(
+ entity_types = [
+ 'RESOURCE'
+ ],
+ entity_item_types = [
+ 'OPAL_ROLE'
+ ],
+ entity_name = opal_security.models.entity_name_filter.EntityNameFilter(
+ string_match_type = 'CONTAINS',
+ string = 'engineering', ),
+ entity_tag = opal_security.models.entity_tag_filter.EntityTagFilter(
+ key = 'team',
+ value = 'platform',
+ connection_id = '', ),
+ hr_idp_status = opal_security.models.idp_status_filter.IdpStatusFilter(
+ statuses = [
+ 'ACTIVE'
+ ],
+ not = True, ),
+ entity_admin_owner = opal_security.models.entity_admin_filter.EntityAdminFilter(
+ owner_ids = [
+ ''
+ ],
+ not = True, ),
+ entity_ids = [
+ ''
+ ],
+ imported_from_app = [
+ ''
+ ],
+ role_remote_ids = [
+ ''
+ ],
+ role_names = [
+ ''
+ ],
+ all_of = [
+ opal_security.models.access_entity_filters.AccessEntityFilters(
+ any_of = [
+
+ ],
+ not = opal_security.models.not.not(), )
+ ],
+ any_of = [
+
+ ],
+ not = opal_security.models.not.not(), ),
+ entitlement_filter = ,
+ principal_access_filters = null,
+ entitlement_access_filters = null,
+ access_level_remote_ids = [
+ ''
+ ],
+ access_level_names = [
+ ''
+ ],
+ edge_filter = opal_security.models.opal_access_path_edge_filter.OpalAccessPathEdgeFilter(
+ direct_only = True,
+ access_duration_type = 'EXPIRING_ONLY', ), ),
+ first = 200,
+ after = '',
+ include_count = False
+ )
+ else:
+ return OpalAccessPathQuery(
+ type = 'ACCESS_PATH',
+ )
+ """
+
+ def testOpalAccessPathQuery(self):
+ """Test OpalAccessPathQuery"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_opal_access_path_query_body.py b/test/test_opal_access_path_query_body.py
new file mode 100644
index 0000000..0ee8639
--- /dev/null
+++ b/test/test_opal_access_path_query_body.py
@@ -0,0 +1,160 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.opal_access_path_query_body import OpalAccessPathQueryBody
+
+class TestOpalAccessPathQueryBody(unittest.TestCase):
+ """OpalAccessPathQueryBody unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> OpalAccessPathQueryBody:
+ """Test OpalAccessPathQueryBody
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `OpalAccessPathQueryBody`
+ """
+ model = OpalAccessPathQueryBody()
+ if include_optional:
+ return OpalAccessPathQueryBody(
+ principal_filter = opal_security.models.access_entity_filters.AccessEntityFilters(
+ entity_types = [
+ 'RESOURCE'
+ ],
+ entity_item_types = [
+ 'OPAL_ROLE'
+ ],
+ entity_name = opal_security.models.entity_name_filter.EntityNameFilter(
+ string_match_type = 'CONTAINS',
+ string = 'engineering', ),
+ entity_tag = opal_security.models.entity_tag_filter.EntityTagFilter(
+ key = 'team',
+ value = 'platform',
+ connection_id = '', ),
+ hr_idp_status = opal_security.models.idp_status_filter.IdpStatusFilter(
+ statuses = [
+ 'ACTIVE'
+ ],
+ not = True, ),
+ entity_admin_owner = opal_security.models.entity_admin_filter.EntityAdminFilter(
+ owner_ids = [
+ ''
+ ],
+ not = True, ),
+ entity_ids = [
+ ''
+ ],
+ imported_from_app = [
+ ''
+ ],
+ role_remote_ids = [
+ ''
+ ],
+ role_names = [
+ ''
+ ],
+ all_of = [
+ opal_security.models.access_entity_filters.AccessEntityFilters(
+ any_of = [
+
+ ],
+ not = opal_security.models.not.not(), )
+ ],
+ any_of = [
+
+ ],
+ not = opal_security.models.not.not(), ),
+ entitlement_filter = opal_security.models.access_entity_filters.AccessEntityFilters(
+ entity_types = [
+ 'RESOURCE'
+ ],
+ entity_item_types = [
+ 'OPAL_ROLE'
+ ],
+ entity_name = opal_security.models.entity_name_filter.EntityNameFilter(
+ string_match_type = 'CONTAINS',
+ string = 'engineering', ),
+ entity_tag = opal_security.models.entity_tag_filter.EntityTagFilter(
+ key = 'team',
+ value = 'platform',
+ connection_id = '', ),
+ hr_idp_status = opal_security.models.idp_status_filter.IdpStatusFilter(
+ statuses = [
+ 'ACTIVE'
+ ],
+ not = True, ),
+ entity_admin_owner = opal_security.models.entity_admin_filter.EntityAdminFilter(
+ owner_ids = [
+ ''
+ ],
+ not = True, ),
+ entity_ids = [
+ ''
+ ],
+ imported_from_app = [
+ ''
+ ],
+ role_remote_ids = [
+ ''
+ ],
+ role_names = [
+ ''
+ ],
+ all_of = [
+ opal_security.models.access_entity_filters.AccessEntityFilters(
+ any_of = [
+
+ ],
+ not = opal_security.models.not.not(), )
+ ],
+ any_of = [
+
+ ],
+ not = opal_security.models.not.not(), ),
+ principal_access_filters = opal_security.models.access_relationship_filters.AccessRelationshipFilters(
+ is_accessible_by = null,
+ has_access_to = null, ),
+ entitlement_access_filters = opal_security.models.access_relationship_filters.AccessRelationshipFilters(
+ is_accessible_by = null,
+ has_access_to = null, ),
+ access_level_remote_ids = [
+ ''
+ ],
+ access_level_names = [
+ ''
+ ],
+ edge_filter = opal_security.models.opal_access_path_edge_filter.OpalAccessPathEdgeFilter(
+ direct_only = True,
+ access_duration_type = 'EXPIRING_ONLY', )
+ )
+ else:
+ return OpalAccessPathQueryBody(
+ )
+ """
+
+ def testOpalAccessPathQueryBody(self):
+ """Test OpalAccessPathQueryBody"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_opal_access_path_query_results.py b/test/test_opal_access_path_query_results.py
new file mode 100644
index 0000000..116bb4a
--- /dev/null
+++ b/test/test_opal_access_path_query_results.py
@@ -0,0 +1,92 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.opal_access_path_query_results import OpalAccessPathQueryResults
+
+class TestOpalAccessPathQueryResults(unittest.TestCase):
+ """OpalAccessPathQueryResults unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> OpalAccessPathQueryResults:
+ """Test OpalAccessPathQueryResults
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `OpalAccessPathQueryResults`
+ """
+ model = OpalAccessPathQueryResults()
+ if include_optional:
+ return OpalAccessPathQueryResults(
+ type = 'ACCESS_PATH',
+ edges = [
+ opal_security.models.opal_access_path_result_edge.OpalAccessPathResultEdge(
+ node = opal_security.models.opal_access_path_result_node.OpalAccessPathResultNode(
+ principal_id = '',
+ entitlement_id = '',
+ access_level_remote_id = '',
+ access_level_name = '',
+ expiration = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
+ depth = 56,
+ path = [
+ ''
+ ], ),
+ cursor = '', )
+ ],
+ page_info = opal_security.models.page_info.PageInfo(
+ has_next_page = True,
+ end_cursor = '',
+ has_previous_page = True,
+ start_cursor = '', ),
+ total_count = 56
+ )
+ else:
+ return OpalAccessPathQueryResults(
+ type = 'ACCESS_PATH',
+ edges = [
+ opal_security.models.opal_access_path_result_edge.OpalAccessPathResultEdge(
+ node = opal_security.models.opal_access_path_result_node.OpalAccessPathResultNode(
+ principal_id = '',
+ entitlement_id = '',
+ access_level_remote_id = '',
+ access_level_name = '',
+ expiration = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
+ depth = 56,
+ path = [
+ ''
+ ], ),
+ cursor = '', )
+ ],
+ page_info = opal_security.models.page_info.PageInfo(
+ has_next_page = True,
+ end_cursor = '',
+ has_previous_page = True,
+ start_cursor = '', ),
+ )
+ """
+
+ def testOpalAccessPathQueryResults(self):
+ """Test OpalAccessPathQueryResults"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_opal_access_path_result_edge.py b/test/test_opal_access_path_result_edge.py
new file mode 100644
index 0000000..5c4dd90
--- /dev/null
+++ b/test/test_opal_access_path_result_edge.py
@@ -0,0 +1,73 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.opal_access_path_result_edge import OpalAccessPathResultEdge
+
+class TestOpalAccessPathResultEdge(unittest.TestCase):
+ """OpalAccessPathResultEdge unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> OpalAccessPathResultEdge:
+ """Test OpalAccessPathResultEdge
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `OpalAccessPathResultEdge`
+ """
+ model = OpalAccessPathResultEdge()
+ if include_optional:
+ return OpalAccessPathResultEdge(
+ node = opal_security.models.opal_access_path_result_node.OpalAccessPathResultNode(
+ principal_id = '',
+ entitlement_id = '',
+ access_level_remote_id = '',
+ access_level_name = '',
+ expiration = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
+ depth = 56,
+ path = [
+ ''
+ ], ),
+ cursor = ''
+ )
+ else:
+ return OpalAccessPathResultEdge(
+ node = opal_security.models.opal_access_path_result_node.OpalAccessPathResultNode(
+ principal_id = '',
+ entitlement_id = '',
+ access_level_remote_id = '',
+ access_level_name = '',
+ expiration = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
+ depth = 56,
+ path = [
+ ''
+ ], ),
+ cursor = '',
+ )
+ """
+
+ def testOpalAccessPathResultEdge(self):
+ """Test OpalAccessPathResultEdge"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_opal_access_path_result_node.py b/test/test_opal_access_path_result_node.py
new file mode 100644
index 0000000..5f81d45
--- /dev/null
+++ b/test/test_opal_access_path_result_node.py
@@ -0,0 +1,66 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.opal_access_path_result_node import OpalAccessPathResultNode
+
+class TestOpalAccessPathResultNode(unittest.TestCase):
+ """OpalAccessPathResultNode unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> OpalAccessPathResultNode:
+ """Test OpalAccessPathResultNode
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `OpalAccessPathResultNode`
+ """
+ model = OpalAccessPathResultNode()
+ if include_optional:
+ return OpalAccessPathResultNode(
+ principal_id = '',
+ entitlement_id = '',
+ access_level_remote_id = '',
+ access_level_name = '',
+ expiration = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
+ depth = 56,
+ path = [
+ ''
+ ]
+ )
+ else:
+ return OpalAccessPathResultNode(
+ principal_id = '',
+ entitlement_id = '',
+ depth = 56,
+ path = [
+ ''
+ ],
+ )
+ """
+
+ def testOpalAccessPathResultNode(self):
+ """Test OpalAccessPathResultNode"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_opal_query_results.py b/test/test_opal_query_results.py
new file mode 100644
index 0000000..650b4e4
--- /dev/null
+++ b/test/test_opal_query_results.py
@@ -0,0 +1,92 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.opal_query_results import OpalQueryResults
+
+class TestOpalQueryResults(unittest.TestCase):
+ """OpalQueryResults unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> OpalQueryResults:
+ """Test OpalQueryResults
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `OpalQueryResults`
+ """
+ model = OpalQueryResults()
+ if include_optional:
+ return OpalQueryResults(
+ type = 'NODE',
+ edges = [
+ opal_security.models.opal_access_path_result_edge.OpalAccessPathResultEdge(
+ node = opal_security.models.opal_access_path_result_node.OpalAccessPathResultNode(
+ principal_id = '',
+ entitlement_id = '',
+ access_level_remote_id = '',
+ access_level_name = '',
+ expiration = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
+ depth = 56,
+ path = [
+ ''
+ ], ),
+ cursor = '', )
+ ],
+ page_info = opal_security.models.page_info.PageInfo(
+ has_next_page = True,
+ end_cursor = '',
+ has_previous_page = True,
+ start_cursor = '', ),
+ total_count = 56
+ )
+ else:
+ return OpalQueryResults(
+ type = 'NODE',
+ edges = [
+ opal_security.models.opal_access_path_result_edge.OpalAccessPathResultEdge(
+ node = opal_security.models.opal_access_path_result_node.OpalAccessPathResultNode(
+ principal_id = '',
+ entitlement_id = '',
+ access_level_remote_id = '',
+ access_level_name = '',
+ expiration = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'),
+ depth = 56,
+ path = [
+ ''
+ ], ),
+ cursor = '', )
+ ],
+ page_info = opal_security.models.page_info.PageInfo(
+ has_next_page = True,
+ end_cursor = '',
+ has_previous_page = True,
+ start_cursor = '', ),
+ )
+ """
+
+ def testOpalQueryResults(self):
+ """Test OpalQueryResults"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_paginated_campaigns_list.py b/test/test_paginated_campaigns_list.py
new file mode 100644
index 0000000..8ef400e
--- /dev/null
+++ b/test/test_paginated_campaigns_list.py
@@ -0,0 +1,59 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.paginated_campaigns_list import PaginatedCampaignsList
+
+class TestPaginatedCampaignsList(unittest.TestCase):
+ """PaginatedCampaignsList unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> PaginatedCampaignsList:
+ """Test PaginatedCampaignsList
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `PaginatedCampaignsList`
+ """
+ model = PaginatedCampaignsList()
+ if include_optional:
+ return PaginatedCampaignsList(
+ next = 'cD0yMDIxLTAxLTA2KzAzJTNBMjQlM0E1My40MzQzMjYlMkIwMCUzQTAw',
+ previous = 'cj1sZXdwd2VycWVtY29zZnNkc2NzUWxNMEUxTXk0ME16UXpNallsTWtJ',
+ results = [
+ {campaign_id=f454d283-ca87-4a8a-bdbb-df212eca5353, name=Q3 Access Review, status=DRAFT, is_template=false, created_at=2026-07-01T00:00:00.000+00:00, updated_at=2026-07-01T00:00:00.000+00:00, created_by_user_id=32acc112-21ff-4669-91c2-21e27683eaa1}
+ ]
+ )
+ else:
+ return PaginatedCampaignsList(
+ results = [
+ {campaign_id=f454d283-ca87-4a8a-bdbb-df212eca5353, name=Q3 Access Review, status=DRAFT, is_template=false, created_at=2026-07-01T00:00:00.000+00:00, updated_at=2026-07-01T00:00:00.000+00:00, created_by_user_id=32acc112-21ff-4669-91c2-21e27683eaa1}
+ ],
+ )
+ """
+
+ def testPaginatedCampaignsList(self):
+ """Test PaginatedCampaignsList"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_paladin.py b/test/test_paladin.py
new file mode 100644
index 0000000..9140bd7
--- /dev/null
+++ b/test/test_paladin.py
@@ -0,0 +1,55 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.paladin import Paladin
+
+class TestPaladin(unittest.TestCase):
+ """Paladin unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> Paladin:
+ """Test Paladin
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `Paladin`
+ """
+ model = Paladin()
+ if include_optional:
+ return Paladin(
+ paladin_id = '32acc112-21ff-4669-91c2-21e27683eaa1',
+ name = 'paladin-agent-1'
+ )
+ else:
+ return Paladin(
+ paladin_id = '32acc112-21ff-4669-91c2-21e27683eaa1',
+ name = 'paladin-agent-1',
+ )
+ """
+
+ def testPaladin(self):
+ """Test Paladin"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_paladin_api.py b/test/test_paladin_api.py
new file mode 100644
index 0000000..b69a21c
--- /dev/null
+++ b/test/test_paladin_api.py
@@ -0,0 +1,46 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.api.paladin_api import PaladinApi
+
+
+class TestPaladinApi(unittest.TestCase):
+ """PaladinApi unit test stubs"""
+
+ def setUp(self) -> None:
+ self.api = PaladinApi()
+
+ def tearDown(self) -> None:
+ pass
+
+ def test_get_paladin(self) -> None:
+ """Test case for get_paladin
+
+ Get Paladin by ID
+ """
+ pass
+
+ def test_get_paladin_from_name(self) -> None:
+ """Test case for get_paladin_from_name
+
+ Get Paladins by name
+ """
+ pass
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_paladin_list.py b/test/test_paladin_list.py
new file mode 100644
index 0000000..4cf00f3
--- /dev/null
+++ b/test/test_paladin_list.py
@@ -0,0 +1,57 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.paladin_list import PaladinList
+
+class TestPaladinList(unittest.TestCase):
+ """PaladinList unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> PaladinList:
+ """Test PaladinList
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `PaladinList`
+ """
+ model = PaladinList()
+ if include_optional:
+ return PaladinList(
+ results = [
+ {paladin_id=32acc112-21ff-4669-91c2-21e27683eaa1, name=paladin-agent-1}
+ ]
+ )
+ else:
+ return PaladinList(
+ results = [
+ {paladin_id=32acc112-21ff-4669-91c2-21e27683eaa1, name=paladin-agent-1}
+ ],
+ )
+ """
+
+ def testPaladinList(self):
+ """Test PaladinList"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_resource_remote_info_alicloud_ecs_instance.py b/test/test_resource_remote_info_alicloud_ecs_instance.py
new file mode 100644
index 0000000..3164f84
--- /dev/null
+++ b/test/test_resource_remote_info_alicloud_ecs_instance.py
@@ -0,0 +1,53 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.resource_remote_info_alicloud_ecs_instance import ResourceRemoteInfoAlicloudEcsInstance
+
+class TestResourceRemoteInfoAlicloudEcsInstance(unittest.TestCase):
+ """ResourceRemoteInfoAlicloudEcsInstance unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> ResourceRemoteInfoAlicloudEcsInstance:
+ """Test ResourceRemoteInfoAlicloudEcsInstance
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `ResourceRemoteInfoAlicloudEcsInstance`
+ """
+ model = ResourceRemoteInfoAlicloudEcsInstance()
+ if include_optional:
+ return ResourceRemoteInfoAlicloudEcsInstance(
+ instance_id = 'i-bp1a1234567890abcd'
+ )
+ else:
+ return ResourceRemoteInfoAlicloudEcsInstance(
+ instance_id = 'i-bp1a1234567890abcd',
+ )
+ """
+
+ def testResourceRemoteInfoAlicloudEcsInstance(self):
+ """Test ResourceRemoteInfoAlicloudEcsInstance"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_resource_remote_info_alicloud_ram_role.py b/test/test_resource_remote_info_alicloud_ram_role.py
new file mode 100644
index 0000000..c4fe767
--- /dev/null
+++ b/test/test_resource_remote_info_alicloud_ram_role.py
@@ -0,0 +1,53 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.resource_remote_info_alicloud_ram_role import ResourceRemoteInfoAlicloudRamRole
+
+class TestResourceRemoteInfoAlicloudRamRole(unittest.TestCase):
+ """ResourceRemoteInfoAlicloudRamRole unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> ResourceRemoteInfoAlicloudRamRole:
+ """Test ResourceRemoteInfoAlicloudRamRole
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `ResourceRemoteInfoAlicloudRamRole`
+ """
+ model = ResourceRemoteInfoAlicloudRamRole()
+ if include_optional:
+ return ResourceRemoteInfoAlicloudRamRole(
+ role_arn = 'acs:ram::1234567890:role/MyRole'
+ )
+ else:
+ return ResourceRemoteInfoAlicloudRamRole(
+ role_arn = 'acs:ram::1234567890:role/MyRole',
+ )
+ """
+
+ def testResourceRemoteInfoAlicloudRamRole(self):
+ """Test ResourceRemoteInfoAlicloudRamRole"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_run_opal_query_request.py b/test/test_run_opal_query_request.py
new file mode 100644
index 0000000..00a9fa4
--- /dev/null
+++ b/test/test_run_opal_query_request.py
@@ -0,0 +1,116 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.run_opal_query_request import RunOpalQueryRequest
+
+class TestRunOpalQueryRequest(unittest.TestCase):
+ """RunOpalQueryRequest unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> RunOpalQueryRequest:
+ """Test RunOpalQueryRequest
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `RunOpalQueryRequest`
+ """
+ model = RunOpalQueryRequest()
+ if include_optional:
+ return RunOpalQueryRequest(
+ type = 'NODE',
+ query = opal_security.models.opal_access_path_query_body.OpalAccessPathQueryBody(
+ principal_filter = opal_security.models.access_entity_filters.AccessEntityFilters(
+ entity_types = [
+ 'RESOURCE'
+ ],
+ entity_item_types = [
+ 'OPAL_ROLE'
+ ],
+ entity_name = opal_security.models.entity_name_filter.EntityNameFilter(
+ string_match_type = 'CONTAINS',
+ string = 'engineering', ),
+ entity_tag = opal_security.models.entity_tag_filter.EntityTagFilter(
+ key = 'team',
+ value = 'platform',
+ connection_id = '', ),
+ hr_idp_status = opal_security.models.idp_status_filter.IdpStatusFilter(
+ statuses = [
+ 'ACTIVE'
+ ],
+ not = True, ),
+ entity_admin_owner = opal_security.models.entity_admin_filter.EntityAdminFilter(
+ owner_ids = [
+ ''
+ ],
+ not = True, ),
+ entity_ids = [
+ ''
+ ],
+ imported_from_app = [
+ ''
+ ],
+ role_remote_ids = [
+ ''
+ ],
+ role_names = [
+ ''
+ ],
+ all_of = [
+ opal_security.models.access_entity_filters.AccessEntityFilters(
+ any_of = [
+
+ ],
+ not = opal_security.models.not.not(), )
+ ],
+ any_of = [
+
+ ],
+ not = opal_security.models.not.not(), ),
+ entitlement_filter = ,
+ principal_access_filters = null,
+ entitlement_access_filters = null,
+ access_level_remote_ids = [
+ ''
+ ],
+ access_level_names = [
+ ''
+ ],
+ edge_filter = opal_security.models.opal_access_path_edge_filter.OpalAccessPathEdgeFilter(
+ direct_only = True,
+ access_duration_type = 'EXPIRING_ONLY', ), ),
+ first = 200,
+ after = '',
+ include_count = False
+ )
+ else:
+ return RunOpalQueryRequest(
+ type = 'NODE',
+ )
+ """
+
+ def testRunOpalQueryRequest(self):
+ """Test RunOpalQueryRequest"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_stop_campaign_request.py b/test/test_stop_campaign_request.py
new file mode 100644
index 0000000..90d430f
--- /dev/null
+++ b/test/test_stop_campaign_request.py
@@ -0,0 +1,52 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.stop_campaign_request import StopCampaignRequest
+
+class TestStopCampaignRequest(unittest.TestCase):
+ """StopCampaignRequest unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> StopCampaignRequest:
+ """Test StopCampaignRequest
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `StopCampaignRequest`
+ """
+ model = StopCampaignRequest()
+ if include_optional:
+ return StopCampaignRequest(
+ revoke_unreviewed = True
+ )
+ else:
+ return StopCampaignRequest(
+ )
+ """
+
+ def testStopCampaignRequest(self):
+ """Test StopCampaignRequest"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_update_campaign_configuration_info.py b/test/test_update_campaign_configuration_info.py
new file mode 100644
index 0000000..5976f91
--- /dev/null
+++ b/test/test_update_campaign_configuration_info.py
@@ -0,0 +1,66 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.update_campaign_configuration_info import UpdateCampaignConfigurationInfo
+
+class TestUpdateCampaignConfigurationInfo(unittest.TestCase):
+ """UpdateCampaignConfigurationInfo unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> UpdateCampaignConfigurationInfo:
+ """Test UpdateCampaignConfigurationInfo
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `UpdateCampaignConfigurationInfo`
+ """
+ model = UpdateCampaignConfigurationInfo()
+ if include_optional:
+ return UpdateCampaignConfigurationInfo(
+ allow_self_review = False,
+ send_reviewer_assignment_notification = True,
+ allow_reviewer_reassignment = False,
+ start_date = '2026-07-02T00:00:00.000+00:00',
+ end_date = '2026-09-30T00:00:00.000+00:00',
+ timezone = 'America/Los_Angeles',
+ revoke_on = 'END',
+ reminder_schedule = [7, 3, 1],
+ reminder_include_manager = True,
+ require_reason_on_denial = False,
+ hide_ai_suggestions = False,
+ custom_start_message = 'Please complete your reviews by Friday.',
+ group_asset_visibility_policy = 'STRICT',
+ cron_expression = '0 9 1 * *',
+ recurring_duration_days = 14
+ )
+ else:
+ return UpdateCampaignConfigurationInfo(
+ )
+ """
+
+ def testUpdateCampaignConfigurationInfo(self):
+ """Test UpdateCampaignConfigurationInfo"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/test/test_update_campaign_info.py b/test/test_update_campaign_info.py
new file mode 100644
index 0000000..c103d6a
--- /dev/null
+++ b/test/test_update_campaign_info.py
@@ -0,0 +1,53 @@
+# coding: utf-8
+
+"""
+ Opal API
+
+ The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically.
+
+ The version of the OpenAPI document: 1.0
+ Contact: hello@opal.dev
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
+
+ Do not edit the class manually.
+""" # noqa: E501
+
+
+import unittest
+
+from opal_security.models.update_campaign_info import UpdateCampaignInfo
+
+class TestUpdateCampaignInfo(unittest.TestCase):
+ """UpdateCampaignInfo unit test stubs"""
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def make_instance(self, include_optional) -> UpdateCampaignInfo:
+ """Test UpdateCampaignInfo
+ include_optional is a boolean, when False only required
+ params are included, when True both required and
+ optional params are included """
+ # uncomment below to create an instance of `UpdateCampaignInfo`
+ """
+ model = UpdateCampaignInfo()
+ if include_optional:
+ return UpdateCampaignInfo(
+ name = 'Q3 Access Review (Updated)',
+ configuration = {end_date=2026-09-30T00:00:00.000+00:00, timezone=America/Los_Angeles, allow_self_review=false}
+ )
+ else:
+ return UpdateCampaignInfo(
+ )
+ """
+
+ def testUpdateCampaignInfo(self):
+ """Test UpdateCampaignInfo"""
+ # inst_req_only = self.make_instance(include_optional=False)
+ # inst_req_and_optional = self.make_instance(include_optional=True)
+
+if __name__ == '__main__':
+ unittest.main()