diff --git a/.openapi-generator/FILES b/.openapi-generator/FILES index 1d586f4..848fc28 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 @@ -183,6 +202,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 +292,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 +319,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 +355,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 @@ -379,9 +405,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 +438,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 +479,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 +494,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 +503,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 +522,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 @@ -518,6 +562,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 +651,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 +674,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 +705,34 @@ 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_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..1b4dac8 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 | @@ -313,9 +320,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 +353,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 +394,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 +409,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 +418,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 +437,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) @@ -452,6 +477,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 +566,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 +589,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..5899c1e 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 @@ -55,7 +57,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 +601,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 +2032,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 @@ -4864,8 +5196,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 +5309,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 +5346,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 +5370,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 +5605,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 +5662,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 +5782,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 +5811,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 +6049,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. @@ -5618,79 +6192,666 @@ components: - f454d283-as87-4a8a-bdbb-df212eca5353 - f454d283-as87-4a8a-bdbb-df212eca5329 properties: - group_visibility: - description: Specifies what users can see during an Access Review + group_visibility: + description: Specifies what users can see during an Access Review + type: string + enum: [STRICT, VIEW_VISIBLE_AND_ASSIGNED, VIEW_ALL] + users: + description: + The access review will only include the following users. If any + users are selected, any entity filters will be applied to only the + entities that the selected users have access to. + items: + example: userd283-ca87-4a8a-bdbb-df212eca5353 + type: string + format: uuid + type: array + filter_operator: + description: + 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 - enum: [STRICT, VIEW_VISIBLE_AND_ASSIGNED, VIEW_ALL] - users: + end_date: + description: Scheduled end date of the campaign. + example: 2026-09-30T00:00:00Z + format: date-time + nullable: true + type: string + timezone: description: - The access review will only include the following users. If any - users are selected, any entity filters will be applied to only the - entities that the selected users have access to. + 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: - example: userd283-ca87-4a8a-bdbb-df212eca5353 - type: string - format: uuid + type: integer type: array - filter_operator: + reminder_include_manager: + description: Whether to include the reviewer's manager in reminders. + example: true + type: boolean + require_reason_on_denial: description: - Specifies whether entities must match all (AND) or any (OR) of the - filters. + 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 - enum: [ANY, ALL] - entities: + group_asset_visibility_policy: + $ref: "#/components/schemas/CampaignGroupAssetVisibilityPolicyEnum" + is_template: description: - This access review will include resources and groups with ids in - the given strings. + 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 + recurring_duration_days: + description: + 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 +7177,7 @@ components: - CUSTOM_CONNECTOR - DATABRICKS - DATASTAX_ASTRA + - ALICLOUD - DEVIN - DUO - GCP @@ -6045,6 +7207,7 @@ components: - SALESFORCE - SNOWFLAKE - SLACK + - TABLEAU - TAILSCALE - TELEPORT - TWINGATE @@ -7349,6 +8512,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 @@ -7615,6 +8779,7 @@ components: - ZENDESK_GROUP - ZENDESK_ORGANIZATION - HUBSPOT_TEAM + - TABLEAU_GROUP example: OPAL_GROUP type: string ResourceTypeEnum: @@ -7706,6 +8871,8 @@ components: - TWINGATE_RESOURCE - ZENDESK_ROLE - HUBSPOT_ROLE + - ALICLOUD_RAM_ROLE + - ALICLOUD_ECS_INSTANCE example: AWS_IAM_ROLE type: string EntityItemTypeEnum: @@ -8566,6 +9733,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 +10639,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 @@ -12952,7 +14149,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/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/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/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/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/opal_security/__init__.py b/opal_security/__init__.py index bfd68aa..dcfba71 100644 --- a/opal_security/__init__.py +++ b/opal_security/__init__.py @@ -22,6 +22,7 @@ "AccessRulesApi", "AppsApi", "BundlesApi", + "CampaignsApi", "ConfigurationTemplatesApi", "DelegationsApi", "EventStreamsApi", @@ -75,9 +76,16 @@ "Bundle", "BundleGroup", "BundleResource", + "Campaign", + "CampaignConfiguration", + "CampaignGroupAssetVisibilityPolicyEnum", + "CampaignRevokeOnEnum", + "CampaignStatusEnum", "Condition", "ConfigurationTemplate", "CreateBundleInfo", + "CreateCampaignConfigurationInfo", + "CreateCampaignInfo", "CreateConfigurationTemplateInfo", "CreateDelegationRequest", "CreateEventStreamInfo", @@ -101,6 +109,7 @@ "CreateUARInfo", "Delegation", "DenyRequestRequest", + "EntityAdminFilter", "EntityItemTypeEnum", "EntityNameFilter", "EntityTagFilter", @@ -141,6 +150,7 @@ "GroupRemoteInfoRootlyOnCallSchedule", "GroupRemoteInfoSlackUserGroup", "GroupRemoteInfoSnowflakeRole", + "GroupRemoteInfoTableauGroup", "GroupRemoteInfoTailscaleGroup", "GroupRemoteInfoTwingateGroup", "GroupRemoteInfoTwingateGroupSynced", @@ -155,6 +165,7 @@ "GroupWithAccessLevel", "IdpGroupMapping", "IdpGroupMappingList", + "IdpStatusFilter", "MessageChannel", "MessageChannelIDList", "MessageChannelList", @@ -163,11 +174,18 @@ "OnCallScheduleIDList", "OnCallScheduleList", "OnCallScheduleProviderEnum", + "OpalAccessPathEdgeFilter", + "OpalAccessPathQuery", + "OpalAccessPathQueryBody", + "OpalAccessPathQueryResults", + "OpalAccessPathResultEdge", + "OpalAccessPathResultNode", "OpalNodeQuery", "OpalNodeQueryBody", "OpalNodeQueryResults", "OpalQueryResultEdge", "OpalQueryResultNode", + "OpalQueryResults", "Owner", "PageInfo", "PaginatedAccessRulesList", @@ -175,6 +193,7 @@ "PaginatedBundleGroupList", "PaginatedBundleList", "PaginatedBundleResourceList", + "PaginatedCampaignsList", "PaginatedConfigurationTemplateList", "PaginatedDelegationsList", "PaginatedEventList", @@ -214,6 +233,8 @@ "ResourceAccessUserList", "ResourceNHI", "ResourceRemoteInfo", + "ResourceRemoteInfoAlicloudEcsInstance", + "ResourceRemoteInfoAlicloudRamRole", "ResourceRemoteInfoAnthropicWorkspace", "ResourceRemoteInfoAwsAccount", "ResourceRemoteInfoAwsEc2Instance", @@ -301,10 +322,12 @@ "RuleClauses", "RuleConjunction", "RuleDisjunction", + "RunOpalQueryRequest", "ScopedRolePermission", "ScopedRolePermissionList", "Session", "SessionsList", + "StopCampaignRequest", "StringMatchType", "SubEvent", "SyncError", @@ -322,6 +345,8 @@ "UARReviewerAssignmentPolicyEnum", "UARScope", "UpdateAccessRuleInfo", + "UpdateCampaignConfigurationInfo", + "UpdateCampaignInfo", "UpdateConfigurationTemplateInfo", "UpdateEventStreamInfo", "UpdateGroupBindingInfo", @@ -355,6 +380,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 @@ -412,9 +438,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 +471,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 +512,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 +527,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 +536,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 +555,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 @@ -551,6 +595,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 +684,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 +707,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..17804a9 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 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/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/models/__init__.py b/opal_security/models/__init__.py index e39bbb8..abef889 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 @@ -178,6 +196,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 +285,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 +308,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/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_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/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_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/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_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()