diff --git a/.openapi-generator/FILES b/.openapi-generator/FILES index 20022a4..b342dd5 100644 --- a/.openapi-generator/FILES +++ b/.openapi-generator/FILES @@ -11,6 +11,9 @@ docs/AddResourceNhiRequest.md docs/AddResourceUserRequest.md docs/App.md docs/AppTypeEnum.md +docs/AppValidation.md +docs/AppValidationSeverityEnum.md +docs/AppValidationStatusEnum.md docs/AppsApi.md docs/AppsList.md docs/AwsPermissionSetMetadata.md @@ -84,6 +87,8 @@ docs/PaginatedResourcesList.md docs/PaginatedTagsList.md docs/PaginatedUARsList.md docs/PaginatedUsersList.md +docs/PropagationStatus.md +docs/PropagationStatusEnum.md docs/Request.md docs/RequestConfiguration.md docs/RequestCustomFieldResponse.md @@ -202,6 +207,9 @@ opal_security/models/add_resource_nhi_request.py opal_security/models/add_resource_user_request.py opal_security/models/app.py opal_security/models/app_type_enum.py +opal_security/models/app_validation.py +opal_security/models/app_validation_severity_enum.py +opal_security/models/app_validation_status_enum.py opal_security/models/apps_list.py opal_security/models/aws_permission_set_metadata.py opal_security/models/aws_permission_set_metadata_aws_permission_set.py @@ -265,6 +273,8 @@ opal_security/models/paginated_resources_list.py opal_security/models/paginated_tags_list.py opal_security/models/paginated_uars_list.py opal_security/models/paginated_users_list.py +opal_security/models/propagation_status.py +opal_security/models/propagation_status_enum.py opal_security/models/request.py opal_security/models/request_configuration.py opal_security/models/request_custom_field_response.py @@ -353,6 +363,9 @@ setup.cfg setup.py test-requirements.txt test/__init__.py -test/test_sync_error.py -test/test_sync_error_list.py +test/test_app_validation.py +test/test_app_validation_severity_enum.py +test/test_app_validation_status_enum.py +test/test_propagation_status.py +test/test_propagation_status_enum.py tox.ini diff --git a/.openapi-generator/VERSION b/.openapi-generator/VERSION index 758bb9c..b23eb27 100644 --- a/.openapi-generator/VERSION +++ b/.openapi-generator/VERSION @@ -1 +1 @@ -7.10.0 +7.11.0 diff --git a/README.md b/README.md index 3e8e131..faeae72 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This Python package is automatically generated by the [OpenAPI Generator](https: - API version: 1.0 - [Releases](https://github.com/opalsecurity/opal-python/releases/) -- Generator version: 7.10.0 +- Generator version: 7.11.0 - Build package: org.openapitools.codegen.languages.PythonClientCodegen For more information, please visit [https://www.opal.dev/](https://www.opal.dev/) @@ -247,6 +247,9 @@ Class | Method | HTTP request | Description - [AddResourceUserRequest](docs/AddResourceUserRequest.md) - [App](docs/App.md) - [AppTypeEnum](docs/AppTypeEnum.md) + - [AppValidation](docs/AppValidation.md) + - [AppValidationSeverityEnum](docs/AppValidationSeverityEnum.md) + - [AppValidationStatusEnum](docs/AppValidationStatusEnum.md) - [AppsList](docs/AppsList.md) - [AwsPermissionSetMetadata](docs/AwsPermissionSetMetadata.md) - [AwsPermissionSetMetadataAwsPermissionSet](docs/AwsPermissionSetMetadataAwsPermissionSet.md) @@ -310,6 +313,8 @@ Class | Method | HTTP request | Description - [PaginatedTagsList](docs/PaginatedTagsList.md) - [PaginatedUARsList](docs/PaginatedUARsList.md) - [PaginatedUsersList](docs/PaginatedUsersList.md) + - [PropagationStatus](docs/PropagationStatus.md) + - [PropagationStatusEnum](docs/PropagationStatusEnum.md) - [Request](docs/Request.md) - [RequestConfiguration](docs/RequestConfiguration.md) - [RequestCustomFieldResponse](docs/RequestCustomFieldResponse.md) diff --git a/api/openapi.yaml b/api/openapi.yaml index 2a1b4fa..0f0a9d4 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -780,6 +780,7 @@ paths: - groups /groups/{group_id}/reviewer-stages: get: + deprecated: true description: Gets the list of reviewer stages for a group. operationId: get_group_reviewer_stages parameters: @@ -808,6 +809,7 @@ paths: tags: - groups put: + deprecated: true description: Sets the list of reviewer stages for a group. operationId: set_group_reviewer_stages parameters: @@ -1174,6 +1176,8 @@ paths: format: uuid alias: type: string + hidden_from_end_user: + type: boolean type: object required: - mappings @@ -1476,7 +1480,7 @@ paths: - requests post: description: "Create an access request" - operationId: "createRequest" # TODO amruth confirm naming + operationId: "createRequest" requestBody: description: Resources to be updated required: true @@ -3415,6 +3419,11 @@ components: type: string app_type: $ref: "#/components/schemas/AppTypeEnum" + validations: + description: Validation checks of an apps' configuration and permissions. + items: + $ref: "#/components/schemas/AppValidation" + type: array required: - app_id - name @@ -3522,6 +3531,69 @@ components: - event_type - created_at type: object + AppValidation: + description: |- + # App validation object + ### Description + The `AppValidation` object is used to represent a validation check of an apps' configuration and permissions. + + ### Usage Example + List from the `GET Apps` endpoint. + example: + key: "iam:GetRole" + name: "Opal's service account is missing the 'iam:GetRole' permission." + usage_reason: "Opal uses the 'iam:GetRole' permissions to view access to resources." + details: "403 Google API Error. Service account is not authorized to access role assignments." + severity: HIGH + status: FAILED + updated_at: 2021-01-06T20:00:00Z + properties: + key: + description: The key of the app validation. These are not unique IDs between runs. + example: "iam:GetUser" + type: string + name: + description: The human-readable description of whether the validation has the permissions. + example: "Opal's service account is missing the 'iam:GetUser' description." + usage_reason: + description: The reason for needing the validation. + example: Opal uses the 'iam:GetUser' permission to import users. + type: string + details: + description: Extra details regarding the validation. Could be an error message or restrictions on permissions. + example: 403 Google API Error. Service account is not authorized to access role assignments. + type: string + severity: + $ref: "#/components/schemas/AppValidationSeverityEnum" + status: + $ref: "#/components/schemas/AppValidationStatusEnum" + updated_at: + description: The date and time the app validation was last run. + example: 2021-01-06T20:00:00Z + format: date-time + type: string + required: + - key + - name + - status + - severity + - updated_at + AppValidationSeverityEnum: + description: The severity of an app validation. + enum: + - CRITICAL + - HIGH + - MEDIUM + - LOW + example: CRITICAL + type: string + AppValidationStatusEnum: + description: The status of an app validation. + enum: + - SUCCESS + - FAILED + example: FAILED + type: string SubEvent: description: |- # Sub event Object @@ -3766,6 +3838,8 @@ components: example: 3 format: int32 type: integer + propagation_status: + $ref: "#/components/schemas/PropagationStatus" required: - email - full_name @@ -4375,12 +4449,48 @@ components: format: date-time nullable: true type: string + propagation_status: + $ref: "#/components/schemas/PropagationStatus" required: - email - full_name - group_id - user_id type: object + PropagationStatus: + description: The state of whether the push action was propagated to the remote system. If this is null, the access was synced from the remote system. + properties: + status: + $ref: "#/components/schemas/PropagationStatusEnum" + required: + - status + PropagationStatusEnum: + description: The status of whether the user has been synced to the group or resource in the remote system. + enum: + - SUCCESS + - ERR_REMOTE_INTERNAL_ERROR + - ERR_REMOTE_USER_NOT_FOUND + - ERR_REMOTE_USER_NOT_LINKED + - ERR_REMOTE_RESOURCE_NOT_FOUND + - ERR_REMOTE_THROTTLE + - ERR_NOT_AUTHORIZED_TO_QUERY_RESOURCE + - ERR_REMOTE_PROVISIONING_VIA_IDP_FAILED + - ERR_IDP_EMAIL_UPDATE_CONFLICT + - ERR_TIMEOUT + - ERR_UNKNOWN + - ERR_OPAL_INTERNAL_ERROR + - ERR_ORG_READ_ONLY + - ERR_OPERATION_UNSUPPORTED + - PENDING + - PENDING_MANUAL_PROPAGATION + - PENDING_TICKET_CREATION + - ERR_TICKET_CREATION_SKIPPED + - ERR_DRY_RUN_MODE_ENABLED + - ERR_HR_IDP_PROVIDER_NOT_LINKED + - ERR_REMOTE_UNRECOVERABLE_ERROR + example: + - SUCCESS + type: string UpdateGroupInfoList: example: groups: @@ -4562,6 +4672,7 @@ components: enum: - ACTIVE_DIRECTORY_GROUP - AWS_SSO_GROUP + - DATABRICKS_ACCOUNT_GROUP - DUO_GROUP - GIT_HUB_TEAM - GIT_LAB_GROUP @@ -4569,6 +4680,7 @@ components: - GOOGLE_GROUPS_GKE_GROUP - LDAP_GROUP - OKTA_GROUP + - OKTA_GROUP_RULE - TAILSCALE_GROUP - OPAL_GROUP - OPAL_ACCESS_RULE @@ -4606,6 +4718,7 @@ components: - AZURE_ENTERPRISE_APP - CUSTOM - CUSTOM_CONNECTOR + - DATABRICKS_ACCOUNT_SERVICE_PRINCIPAL - GCP_ORGANIZATION - GCP_BUCKET - GCP_COMPUTE_INSTANCE @@ -4666,28 +4779,10 @@ components: IdpGroupMapping: description: Information about a group mapping. example: - id: 7870617d-e72a-47f5-a84c-693817ab4567 - organization_id: 1520617d-e72a-47f5-a84c-693817ab48ad2 - app_resource_id: 6f99639b-7928-4043-8184-47cbc6766145 group_id: 6f99639b-7928-4043-8184-47cbc6766145 alias: "finance-team" hidden_from_end_user: False properties: - id: - description: The ID of the idp group mapping. - example: 7870617d-e72a-47f5-a84c-693817ab4567 - format: uuid - type: string - organization_id: - description: The ID of the organization. - example: 1520617d-e72a-47f5-a84c-693817ab48ad2 - format: uuid - type: string - app_resource_id: - description: The ID of the idp app resource. - example: 6f99639b-7928-4043-8184-47cbc6766145 - format: uuid - type: string group_id: description: The ID of the group. example: 6f99639b-7928-4043-8184-47cbc6766145 @@ -4702,35 +4797,26 @@ components: example: False type: boolean required: - - id - - organization_id - - app_resource_id - group_id - hidden_from_end_user type: object IdpGroupMappingList: example: - idp_group_mappings: - - id: 7870617d-e72a-47f5-a84c-693817ab4567 - organization_id: 1520617d-e72a-47f5-a84c-693817ab48ad2 - app_resource_id: 6f99639b-7928-4043-8184-47cbc6766145 - group_id: 6f99639b-7928-4043-8184-47cbc6766145 + mappings: + - group_id: 6f99639b-7928-4043-8184-47cbc6766145 alias: "finance-team" hidden_from_end_user: False - - id: 1520617d-e72a-47f5-a84c-693817ab48ad2 - organization_id: 6f99639b-7928-4043-8184-47cbc6766145 - app_resource_id: 7870617d-e72a-47f5-a84c-693817ab4567 - group_id: 7870617d-e72a-47f5-a84c-693817ab4567 + - group_id: 7870617d-e72a-47f5-a84c-693817ab4567 alias: "engineering-team" hidden_from_end_user: False properties: - idp_group_mappings: + mappings: items: $ref: "#/components/schemas/IdpGroupMapping" type: array type: object required: - - idp_group_mappings + - mappings ResourceWithAccessLevel: description: Information about a resource and corresponding access level example: @@ -7145,7 +7231,6 @@ components: - auto_approval - require_mfa_to_request - require_support_ticket - - reviewer_stages - priority CreateRequestConfigurationInfoList: description: |- @@ -7675,7 +7760,7 @@ components: identifier: type: string url: - type: string # TODO amruth Does url format exist? + type: string required: - ticketing_provider - remote_id diff --git a/docs/App.md b/docs/App.md index 46ca2eb..ecf9c58 100644 --- a/docs/App.md +++ b/docs/App.md @@ -11,6 +11,7 @@ Name | Type | Description | Notes **description** | **str** | A description of the app. | **admin_owner_id** | **str** | The ID of the owner of the app. | **app_type** | [**AppTypeEnum**](AppTypeEnum.md) | | +**validations** | [**List[AppValidation]**](AppValidation.md) | Validation checks of an apps' configuration and permissions. | [optional] ## Example diff --git a/docs/AppValidation.md b/docs/AppValidation.md new file mode 100644 index 0000000..51bf669 --- /dev/null +++ b/docs/AppValidation.md @@ -0,0 +1,36 @@ +# AppValidation + +# App validation object ### Description The `AppValidation` object is used to represent a validation check of an apps' configuration and permissions. ### Usage Example List from the `GET Apps` endpoint. + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**key** | **str** | The key of the app validation. These are not unique IDs between runs. | +**name** | **object** | | +**usage_reason** | **str** | The reason for needing the validation. | [optional] +**details** | **str** | Extra details regarding the validation. Could be an error message or restrictions on permissions. | [optional] +**severity** | [**AppValidationSeverityEnum**](AppValidationSeverityEnum.md) | | +**status** | [**AppValidationStatusEnum**](AppValidationStatusEnum.md) | | +**updated_at** | **datetime** | The date and time the app validation was last run. | + +## Example + +```python +from opal_security.models.app_validation import AppValidation + +# TODO update the JSON string below +json = "{}" +# create an instance of AppValidation from a JSON string +app_validation_instance = AppValidation.from_json(json) +# print the JSON string representation of the object +print(AppValidation.to_json()) + +# convert the object into a dict +app_validation_dict = app_validation_instance.to_dict() +# create an instance of AppValidation from a dict +app_validation_from_dict = AppValidation.from_dict(app_validation_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/AppValidationSeverityEnum.md b/docs/AppValidationSeverityEnum.md new file mode 100644 index 0000000..67a0442 --- /dev/null +++ b/docs/AppValidationSeverityEnum.md @@ -0,0 +1,17 @@ +# AppValidationSeverityEnum + +The severity of an app validation. + +## Enum + +* `CRITICAL` (value: `'CRITICAL'`) + +* `HIGH` (value: `'HIGH'`) + +* `MEDIUM` (value: `'MEDIUM'`) + +* `LOW` (value: `'LOW'`) + +[[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/AppValidationStatusEnum.md b/docs/AppValidationStatusEnum.md new file mode 100644 index 0000000..c100e98 --- /dev/null +++ b/docs/AppValidationStatusEnum.md @@ -0,0 +1,13 @@ +# AppValidationStatusEnum + +The status of an app validation. + +## Enum + +* `SUCCESS` (value: `'SUCCESS'`) + +* `FAILED` (value: `'FAILED'`) + +[[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 67b0dd0..a0bf4c2 100644 --- a/docs/GroupTypeEnum.md +++ b/docs/GroupTypeEnum.md @@ -8,6 +8,8 @@ The type of the group. * `AWS_SSO_GROUP` (value: `'AWS_SSO_GROUP'`) +* `DATABRICKS_ACCOUNT_GROUP` (value: `'DATABRICKS_ACCOUNT_GROUP'`) + * `DUO_GROUP` (value: `'DUO_GROUP'`) * `GIT_HUB_TEAM` (value: `'GIT_HUB_TEAM'`) @@ -22,6 +24,8 @@ The type of the group. * `OKTA_GROUP` (value: `'OKTA_GROUP'`) +* `OKTA_GROUP_RULE` (value: `'OKTA_GROUP_RULE'`) + * `TAILSCALE_GROUP` (value: `'TAILSCALE_GROUP'`) * `OPAL_GROUP` (value: `'OPAL_GROUP'`) diff --git a/docs/GroupUser.md b/docs/GroupUser.md index 28b1fa1..6f317a7 100644 --- a/docs/GroupUser.md +++ b/docs/GroupUser.md @@ -12,6 +12,7 @@ Name | Type | Description | Notes **full_name** | **str** | The user's full name. | **email** | **str** | The user's email. | **expiration_date** | **datetime** | The day and time the user's access will expire. | [optional] +**propagation_status** | [**PropagationStatus**](PropagationStatus.md) | | [optional] ## Example diff --git a/docs/IdpGroupMapping.md b/docs/IdpGroupMapping.md index 8d3c500..3be4693 100644 --- a/docs/IdpGroupMapping.md +++ b/docs/IdpGroupMapping.md @@ -6,9 +6,6 @@ Information about a group mapping. Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -**id** | **str** | The ID of the idp group mapping. | -**organization_id** | **str** | The ID of the organization. | -**app_resource_id** | **str** | The ID of the idp app resource. | **group_id** | **str** | The ID of the group. | **alias** | **str** | The alias of the group. | [optional] **hidden_from_end_user** | **bool** | A bool representing whether or not the group is hidden from the end user. | diff --git a/docs/IdpGroupMappingList.md b/docs/IdpGroupMappingList.md index c02c0d7..d3916e8 100644 --- a/docs/IdpGroupMappingList.md +++ b/docs/IdpGroupMappingList.md @@ -5,7 +5,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -**idp_group_mappings** | [**List[IdpGroupMapping]**](IdpGroupMapping.md) | | +**mappings** | [**List[IdpGroupMapping]**](IdpGroupMapping.md) | | ## Example diff --git a/docs/PropagationStatus.md b/docs/PropagationStatus.md new file mode 100644 index 0000000..ef1349a --- /dev/null +++ b/docs/PropagationStatus.md @@ -0,0 +1,30 @@ +# PropagationStatus + +The state of whether the push action was propagated to the remote system. If this is null, the access was synced from the remote system. + +## Properties + +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**status** | [**PropagationStatusEnum**](PropagationStatusEnum.md) | | + +## Example + +```python +from opal_security.models.propagation_status import PropagationStatus + +# TODO update the JSON string below +json = "{}" +# create an instance of PropagationStatus from a JSON string +propagation_status_instance = PropagationStatus.from_json(json) +# print the JSON string representation of the object +print(PropagationStatus.to_json()) + +# convert the object into a dict +propagation_status_dict = propagation_status_instance.to_dict() +# create an instance of PropagationStatus from a dict +propagation_status_from_dict = PropagationStatus.from_dict(propagation_status_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 new file mode 100644 index 0000000..ded75f9 --- /dev/null +++ b/docs/PropagationStatusEnum.md @@ -0,0 +1,51 @@ +# PropagationStatusEnum + +The status of whether the user has been synced to the group or resource in the remote system. + +## Enum + +* `SUCCESS` (value: `'SUCCESS'`) + +* `ERR_REMOTE_INTERNAL_ERROR` (value: `'ERR_REMOTE_INTERNAL_ERROR'`) + +* `ERR_REMOTE_USER_NOT_FOUND` (value: `'ERR_REMOTE_USER_NOT_FOUND'`) + +* `ERR_REMOTE_USER_NOT_LINKED` (value: `'ERR_REMOTE_USER_NOT_LINKED'`) + +* `ERR_REMOTE_RESOURCE_NOT_FOUND` (value: `'ERR_REMOTE_RESOURCE_NOT_FOUND'`) + +* `ERR_REMOTE_THROTTLE` (value: `'ERR_REMOTE_THROTTLE'`) + +* `ERR_NOT_AUTHORIZED_TO_QUERY_RESOURCE` (value: `'ERR_NOT_AUTHORIZED_TO_QUERY_RESOURCE'`) + +* `ERR_REMOTE_PROVISIONING_VIA_IDP_FAILED` (value: `'ERR_REMOTE_PROVISIONING_VIA_IDP_FAILED'`) + +* `ERR_IDP_EMAIL_UPDATE_CONFLICT` (value: `'ERR_IDP_EMAIL_UPDATE_CONFLICT'`) + +* `ERR_TIMEOUT` (value: `'ERR_TIMEOUT'`) + +* `ERR_UNKNOWN` (value: `'ERR_UNKNOWN'`) + +* `ERR_OPAL_INTERNAL_ERROR` (value: `'ERR_OPAL_INTERNAL_ERROR'`) + +* `ERR_ORG_READ_ONLY` (value: `'ERR_ORG_READ_ONLY'`) + +* `ERR_OPERATION_UNSUPPORTED` (value: `'ERR_OPERATION_UNSUPPORTED'`) + +* `PENDING` (value: `'PENDING'`) + +* `PENDING_MANUAL_PROPAGATION` (value: `'PENDING_MANUAL_PROPAGATION'`) + +* `PENDING_TICKET_CREATION` (value: `'PENDING_TICKET_CREATION'`) + +* `ERR_TICKET_CREATION_SKIPPED` (value: `'ERR_TICKET_CREATION_SKIPPED'`) + +* `ERR_DRY_RUN_MODE_ENABLED` (value: `'ERR_DRY_RUN_MODE_ENABLED'`) + +* `ERR_HR_IDP_PROVIDER_NOT_LINKED` (value: `'ERR_HR_IDP_PROVIDER_NOT_LINKED'`) + +* `ERR_REMOTE_UNRECOVERABLE_ERROR` (value: `'ERR_REMOTE_UNRECOVERABLE_ERROR'`) + +[[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/RequestConfiguration.md b/docs/RequestConfiguration.md index f3eb554..82e9687 100644 --- a/docs/RequestConfiguration.md +++ b/docs/RequestConfiguration.md @@ -14,7 +14,7 @@ Name | Type | Description | Notes **recommended_duration_minutes** | **int** | The recommended duration for which the resource should be requested (in minutes). -1 represents an indefinite duration. | [optional] **require_support_ticket** | **bool** | A bool representing whether or not access requests to the resource require an access ticket. | **request_template_id** | **str** | The ID of the associated request template. | [optional] -**reviewer_stages** | [**List[ReviewerStage]**](ReviewerStage.md) | The list of reviewer stages for the request configuration. | +**reviewer_stages** | [**List[ReviewerStage]**](ReviewerStage.md) | The list of reviewer stages for the request configuration. | [optional] **priority** | **int** | The priority of the request configuration. | ## Example diff --git a/docs/ResourceAccessUser.md b/docs/ResourceAccessUser.md index 601971a..4b2e9e4 100644 --- a/docs/ResourceAccessUser.md +++ b/docs/ResourceAccessUser.md @@ -14,6 +14,7 @@ Name | Type | Description | Notes **expiration_date** | **datetime** | The day and time the user's access will expire. | [optional] **has_direct_access** | **bool** | The user has direct access to this resources (vs. indirectly, like through a group). | **num_access_paths** | **int** | The number of ways in which the user has access through this resource (directly and indirectly). | +**propagation_status** | [**PropagationStatus**](PropagationStatus.md) | | [optional] ## Example diff --git a/docs/ResourceTypeEnum.md b/docs/ResourceTypeEnum.md index ac8a697..7b9ed0c 100644 --- a/docs/ResourceTypeEnum.md +++ b/docs/ResourceTypeEnum.md @@ -52,6 +52,8 @@ The type of the resource. * `CUSTOM_CONNECTOR` (value: `'CUSTOM_CONNECTOR'`) +* `DATABRICKS_ACCOUNT_SERVICE_PRINCIPAL` (value: `'DATABRICKS_ACCOUNT_SERVICE_PRINCIPAL'`) + * `GCP_ORGANIZATION` (value: `'GCP_ORGANIZATION'`) * `GCP_BUCKET` (value: `'GCP_BUCKET'`) diff --git a/docs/UpdateIdpGroupMappingsRequestMappingsInner.md b/docs/UpdateIdpGroupMappingsRequestMappingsInner.md index 55c4cfd..9ea2d1c 100644 --- a/docs/UpdateIdpGroupMappingsRequestMappingsInner.md +++ b/docs/UpdateIdpGroupMappingsRequestMappingsInner.md @@ -7,6 +7,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **group_id** | **str** | | [optional] **alias** | **str** | | [optional] +**hidden_from_end_user** | **bool** | | [optional] ## Example diff --git a/opal_security/__init__.py b/opal_security/__init__.py index 86ec533..15741f3 100644 --- a/opal_security/__init__.py +++ b/opal_security/__init__.py @@ -55,6 +55,9 @@ from opal_security.models.add_resource_user_request import AddResourceUserRequest from opal_security.models.app import App from opal_security.models.app_type_enum import AppTypeEnum +from opal_security.models.app_validation import AppValidation +from opal_security.models.app_validation_severity_enum import AppValidationSeverityEnum +from opal_security.models.app_validation_status_enum import AppValidationStatusEnum from opal_security.models.apps_list import AppsList from opal_security.models.aws_permission_set_metadata import AwsPermissionSetMetadata from opal_security.models.aws_permission_set_metadata_aws_permission_set import AwsPermissionSetMetadataAwsPermissionSet @@ -118,6 +121,8 @@ from opal_security.models.paginated_tags_list import PaginatedTagsList from opal_security.models.paginated_uars_list import PaginatedUARsList from opal_security.models.paginated_users_list import PaginatedUsersList +from opal_security.models.propagation_status import PropagationStatus +from opal_security.models.propagation_status_enum import PropagationStatusEnum from opal_security.models.request import Request from opal_security.models.request_configuration import RequestConfiguration from opal_security.models.request_custom_field_response import RequestCustomFieldResponse diff --git a/opal_security/api/groups_api.py b/opal_security/api/groups_api.py index 1a15e8f..dd8a954 100644 --- a/opal_security/api/groups_api.py +++ b/opal_security/api/groups_api.py @@ -2577,7 +2577,7 @@ def get_group_reviewer_stages( _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> List[ReviewerStage]: - """get_group_reviewer_stages + """(Deprecated) get_group_reviewer_stages Gets the list of reviewer stages for a group. @@ -2604,6 +2604,7 @@ def get_group_reviewer_stages( :type _host_index: int, optional :return: Returns the result object. """ # noqa: E501 + warnings.warn("GET /groups/{group_id}/reviewer-stages is deprecated.", DeprecationWarning) _param = self._get_group_reviewer_stages_serialize( group_id=group_id, @@ -2644,7 +2645,7 @@ def get_group_reviewer_stages_with_http_info( _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> ApiResponse[List[ReviewerStage]]: - """get_group_reviewer_stages + """(Deprecated) get_group_reviewer_stages Gets the list of reviewer stages for a group. @@ -2671,6 +2672,7 @@ def get_group_reviewer_stages_with_http_info( :type _host_index: int, optional :return: Returns the result object. """ # noqa: E501 + warnings.warn("GET /groups/{group_id}/reviewer-stages is deprecated.", DeprecationWarning) _param = self._get_group_reviewer_stages_serialize( group_id=group_id, @@ -2711,7 +2713,7 @@ def get_group_reviewer_stages_without_preload_content( _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> RESTResponseType: - """get_group_reviewer_stages + """(Deprecated) get_group_reviewer_stages Gets the list of reviewer stages for a group. @@ -2738,6 +2740,7 @@ def get_group_reviewer_stages_without_preload_content( :type _host_index: int, optional :return: Returns the result object. """ # noqa: E501 + warnings.warn("GET /groups/{group_id}/reviewer-stages is deprecated.", DeprecationWarning) _param = self._get_group_reviewer_stages_serialize( group_id=group_id, @@ -5078,7 +5081,7 @@ def set_group_reviewer_stages( _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> List[ReviewerStage]: - """set_group_reviewer_stages + """(Deprecated) set_group_reviewer_stages Sets the list of reviewer stages for a group. @@ -5107,6 +5110,7 @@ def set_group_reviewer_stages( :type _host_index: int, optional :return: Returns the result object. """ # noqa: E501 + warnings.warn("PUT /groups/{group_id}/reviewer-stages is deprecated.", DeprecationWarning) _param = self._set_group_reviewer_stages_serialize( group_id=group_id, @@ -5149,7 +5153,7 @@ def set_group_reviewer_stages_with_http_info( _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> ApiResponse[List[ReviewerStage]]: - """set_group_reviewer_stages + """(Deprecated) set_group_reviewer_stages Sets the list of reviewer stages for a group. @@ -5178,6 +5182,7 @@ def set_group_reviewer_stages_with_http_info( :type _host_index: int, optional :return: Returns the result object. """ # noqa: E501 + warnings.warn("PUT /groups/{group_id}/reviewer-stages is deprecated.", DeprecationWarning) _param = self._set_group_reviewer_stages_serialize( group_id=group_id, @@ -5220,7 +5225,7 @@ def set_group_reviewer_stages_without_preload_content( _headers: Optional[Dict[StrictStr, Any]] = None, _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, ) -> RESTResponseType: - """set_group_reviewer_stages + """(Deprecated) set_group_reviewer_stages Sets the list of reviewer stages for a group. @@ -5249,6 +5254,7 @@ def set_group_reviewer_stages_without_preload_content( :type _host_index: int, optional :return: Returns the result object. """ # noqa: E501 + warnings.warn("PUT /groups/{group_id}/reviewer-stages is deprecated.", DeprecationWarning) _param = self._set_group_reviewer_stages_serialize( group_id=group_id, diff --git a/opal_security/api_client.py b/opal_security/api_client.py index a99efc4..d4b3ebc 100644 --- a/opal_security/api_client.py +++ b/opal_security/api_client.py @@ -518,7 +518,7 @@ def parameters_to_url_query(self, params, collection_formats): if k in collection_formats: collection_format = collection_formats[k] if collection_format == 'multi': - new_params.extend((k, str(value)) for value in v) + new_params.extend((k, quote(str(value))) for value in v) else: if collection_format == 'ssv': delimiter = ' ' diff --git a/opal_security/exceptions.py b/opal_security/exceptions.py index 12f9285..e1d48ca 100644 --- a/opal_security/exceptions.py +++ b/opal_security/exceptions.py @@ -151,6 +151,13 @@ def from_response( if http_resp.status == 404: raise NotFoundException(http_resp=http_resp, body=body, data=data) + # Added new conditions for 409 and 422 + if http_resp.status == 409: + raise ConflictException(http_resp=http_resp, body=body, data=data) + + if http_resp.status == 422: + raise UnprocessableEntityException(http_resp=http_resp, body=body, data=data) + if 500 <= http_resp.status <= 599: raise ServiceException(http_resp=http_resp, body=body, data=data) raise ApiException(http_resp=http_resp, body=body, data=data) @@ -189,6 +196,16 @@ class ServiceException(ApiException): pass +class ConflictException(ApiException): + """Exception for HTTP 409 Conflict.""" + pass + + +class UnprocessableEntityException(ApiException): + """Exception for HTTP 422 Unprocessable Entity.""" + pass + + def render_path(path_to_item): """Returns a string representation of a path""" result = "" diff --git a/opal_security/models/__init__.py b/opal_security/models/__init__.py index 86e8eae..38f376b 100644 --- a/opal_security/models/__init__.py +++ b/opal_security/models/__init__.py @@ -23,6 +23,9 @@ from opal_security.models.add_resource_user_request import AddResourceUserRequest from opal_security.models.app import App from opal_security.models.app_type_enum import AppTypeEnum +from opal_security.models.app_validation import AppValidation +from opal_security.models.app_validation_severity_enum import AppValidationSeverityEnum +from opal_security.models.app_validation_status_enum import AppValidationStatusEnum from opal_security.models.apps_list import AppsList from opal_security.models.aws_permission_set_metadata import AwsPermissionSetMetadata from opal_security.models.aws_permission_set_metadata_aws_permission_set import AwsPermissionSetMetadataAwsPermissionSet @@ -86,6 +89,8 @@ from opal_security.models.paginated_tags_list import PaginatedTagsList from opal_security.models.paginated_uars_list import PaginatedUARsList from opal_security.models.paginated_users_list import PaginatedUsersList +from opal_security.models.propagation_status import PropagationStatus +from opal_security.models.propagation_status_enum import PropagationStatusEnum from opal_security.models.request import Request from opal_security.models.request_configuration import RequestConfiguration from opal_security.models.request_custom_field_response import RequestCustomFieldResponse diff --git a/opal_security/models/app.py b/opal_security/models/app.py index 484c320..a0f32dd 100644 --- a/opal_security/models/app.py +++ b/opal_security/models/app.py @@ -19,8 +19,9 @@ import json from pydantic import BaseModel, ConfigDict, Field, StrictStr -from typing import Any, ClassVar, Dict, List +from typing import Any, ClassVar, Dict, List, Optional from opal_security.models.app_type_enum import AppTypeEnum +from opal_security.models.app_validation import AppValidation from typing import Optional, Set from typing_extensions import Self @@ -33,8 +34,9 @@ class App(BaseModel): description: StrictStr = Field(description="A description of the app.") admin_owner_id: StrictStr = Field(description="The ID of the owner of the app.") app_type: AppTypeEnum + validations: Optional[List[AppValidation]] = Field(default=None, description="Validation checks of an apps' configuration and permissions.") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["app_id", "name", "description", "admin_owner_id", "app_type"] + __properties: ClassVar[List[str]] = ["app_id", "name", "description", "admin_owner_id", "app_type", "validations"] model_config = ConfigDict( populate_by_name=True, @@ -77,6 +79,13 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) + # override the default output from pydantic by calling `to_dict()` of each item in validations (list) + _items = [] + if self.validations: + for _item_validations in self.validations: + if _item_validations: + _items.append(_item_validations.to_dict()) + _dict['validations'] = _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(): @@ -98,7 +107,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "name": obj.get("name"), "description": obj.get("description"), "admin_owner_id": obj.get("admin_owner_id"), - "app_type": obj.get("app_type") + "app_type": obj.get("app_type"), + "validations": [AppValidation.from_dict(_item) for _item in obj["validations"]] if obj.get("validations") is not None else None }) # store additional fields in additional_properties for _key in obj.keys(): diff --git a/opal_security/models/app_validation.py b/opal_security/models/app_validation.py new file mode 100644 index 0000000..61e4627 --- /dev/null +++ b/opal_security/models/app_validation.py @@ -0,0 +1,121 @@ +# 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, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from opal_security.models.app_validation_severity_enum import AppValidationSeverityEnum +from opal_security.models.app_validation_status_enum import AppValidationStatusEnum +from typing import Optional, Set +from typing_extensions import Self + +class AppValidation(BaseModel): + """ + # App validation object ### Description The `AppValidation` object is used to represent a validation check of an apps' configuration and permissions. ### Usage Example List from the `GET Apps` endpoint. + """ # noqa: E501 + key: StrictStr = Field(description="The key of the app validation. These are not unique IDs between runs.") + name: Optional[Any] + usage_reason: Optional[StrictStr] = Field(default=None, description="The reason for needing the validation.") + details: Optional[StrictStr] = Field(default=None, description="Extra details regarding the validation. Could be an error message or restrictions on permissions.") + severity: AppValidationSeverityEnum + status: AppValidationStatusEnum + updated_at: datetime = Field(description="The date and time the app validation was last run.") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["key", "name", "usage_reason", "details", "severity", "status", "updated_at"] + + 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 AppValidation 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 + + # set to None if name (nullable) is None + # and model_fields_set contains the field + if self.name is None and "name" in self.model_fields_set: + _dict['name'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AppValidation from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "key": obj.get("key"), + "name": obj.get("name"), + "usage_reason": obj.get("usage_reason"), + "details": obj.get("details"), + "severity": obj.get("severity"), + "status": obj.get("status"), + "updated_at": obj.get("updated_at") + }) + # 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/app_validation_severity_enum.py b/opal_security/models/app_validation_severity_enum.py new file mode 100644 index 0000000..84fe957 --- /dev/null +++ b/opal_security/models/app_validation_severity_enum.py @@ -0,0 +1,40 @@ +# 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 AppValidationSeverityEnum(str, Enum): + """ + The severity of an app validation. + """ + + """ + allowed enum values + """ + CRITICAL = 'CRITICAL' + HIGH = 'HIGH' + MEDIUM = 'MEDIUM' + LOW = 'LOW' + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of AppValidationSeverityEnum from a JSON string""" + return cls(json.loads(json_str)) + + diff --git a/opal_security/models/app_validation_status_enum.py b/opal_security/models/app_validation_status_enum.py new file mode 100644 index 0000000..097fc28 --- /dev/null +++ b/opal_security/models/app_validation_status_enum.py @@ -0,0 +1,38 @@ +# 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 AppValidationStatusEnum(str, Enum): + """ + The status of an app validation. + """ + + """ + allowed enum values + """ + SUCCESS = 'SUCCESS' + FAILED = 'FAILED' + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of AppValidationStatusEnum from a JSON string""" + return cls(json.loads(json_str)) + + diff --git a/opal_security/models/group_type_enum.py b/opal_security/models/group_type_enum.py index d994f6c..84916a9 100644 --- a/opal_security/models/group_type_enum.py +++ b/opal_security/models/group_type_enum.py @@ -29,6 +29,7 @@ class GroupTypeEnum(str, Enum): """ ACTIVE_DIRECTORY_GROUP = 'ACTIVE_DIRECTORY_GROUP' AWS_SSO_GROUP = 'AWS_SSO_GROUP' + DATABRICKS_ACCOUNT_GROUP = 'DATABRICKS_ACCOUNT_GROUP' DUO_GROUP = 'DUO_GROUP' GIT_HUB_TEAM = 'GIT_HUB_TEAM' GIT_LAB_GROUP = 'GIT_LAB_GROUP' @@ -36,6 +37,7 @@ class GroupTypeEnum(str, Enum): GOOGLE_GROUPS_GKE_GROUP = 'GOOGLE_GROUPS_GKE_GROUP' LDAP_GROUP = 'LDAP_GROUP' OKTA_GROUP = 'OKTA_GROUP' + OKTA_GROUP_RULE = 'OKTA_GROUP_RULE' TAILSCALE_GROUP = 'TAILSCALE_GROUP' OPAL_GROUP = 'OPAL_GROUP' OPAL_ACCESS_RULE = 'OPAL_ACCESS_RULE' diff --git a/opal_security/models/group_user.py b/opal_security/models/group_user.py index 5cf7ec5..f0714c9 100644 --- a/opal_security/models/group_user.py +++ b/opal_security/models/group_user.py @@ -22,6 +22,7 @@ from pydantic import BaseModel, ConfigDict, Field, StrictStr from typing import Any, ClassVar, Dict, List, Optional from opal_security.models.group_access_level import GroupAccessLevel +from opal_security.models.propagation_status import PropagationStatus from typing import Optional, Set from typing_extensions import Self @@ -35,8 +36,9 @@ class GroupUser(BaseModel): full_name: StrictStr = Field(description="The user's full name.") email: StrictStr = Field(description="The user's email.") expiration_date: Optional[datetime] = Field(default=None, description="The day and time the user's access will expire.") + propagation_status: Optional[PropagationStatus] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["group_id", "user_id", "access_level", "full_name", "email", "expiration_date"] + __properties: ClassVar[List[str]] = ["group_id", "user_id", "access_level", "full_name", "email", "expiration_date", "propagation_status"] model_config = ConfigDict( populate_by_name=True, @@ -82,6 +84,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of access_level if self.access_level: _dict['access_level'] = self.access_level.to_dict() + # override the default output from pydantic by calling `to_dict()` of propagation_status + if self.propagation_status: + _dict['propagation_status'] = self.propagation_status.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(): @@ -104,7 +109,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "access_level": GroupAccessLevel.from_dict(obj["access_level"]) if obj.get("access_level") is not None else None, "full_name": obj.get("full_name"), "email": obj.get("email"), - "expiration_date": obj.get("expiration_date") + "expiration_date": obj.get("expiration_date"), + "propagation_status": PropagationStatus.from_dict(obj["propagation_status"]) if obj.get("propagation_status") is not None else None }) # store additional fields in additional_properties for _key in obj.keys(): diff --git a/opal_security/models/idp_group_mapping.py b/opal_security/models/idp_group_mapping.py index 55b7d6f..c3d7987 100644 --- a/opal_security/models/idp_group_mapping.py +++ b/opal_security/models/idp_group_mapping.py @@ -27,14 +27,11 @@ class IdpGroupMapping(BaseModel): """ Information about a group mapping. """ # noqa: E501 - id: StrictStr = Field(description="The ID of the idp group mapping.") - organization_id: StrictStr = Field(description="The ID of the organization.") - app_resource_id: StrictStr = Field(description="The ID of the idp app resource.") group_id: StrictStr = Field(description="The ID of the group.") alias: Optional[StrictStr] = Field(default=None, description="The alias of the group.") hidden_from_end_user: StrictBool = Field(description="A bool representing whether or not the group is hidden from the end user.") additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["id", "organization_id", "app_resource_id", "group_id", "alias", "hidden_from_end_user"] + __properties: ClassVar[List[str]] = ["group_id", "alias", "hidden_from_end_user"] model_config = ConfigDict( populate_by_name=True, @@ -94,9 +91,6 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "id": obj.get("id"), - "organization_id": obj.get("organization_id"), - "app_resource_id": obj.get("app_resource_id"), "group_id": obj.get("group_id"), "alias": obj.get("alias"), "hidden_from_end_user": obj.get("hidden_from_end_user") diff --git a/opal_security/models/idp_group_mapping_list.py b/opal_security/models/idp_group_mapping_list.py index 8ebb702..15da33f 100644 --- a/opal_security/models/idp_group_mapping_list.py +++ b/opal_security/models/idp_group_mapping_list.py @@ -28,9 +28,9 @@ class IdpGroupMappingList(BaseModel): """ IdpGroupMappingList """ # noqa: E501 - idp_group_mappings: List[IdpGroupMapping] + mappings: List[IdpGroupMapping] additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["idp_group_mappings"] + __properties: ClassVar[List[str]] = ["mappings"] model_config = ConfigDict( populate_by_name=True, @@ -73,13 +73,13 @@ def to_dict(self) -> Dict[str, Any]: exclude=excluded_fields, exclude_none=True, ) - # override the default output from pydantic by calling `to_dict()` of each item in idp_group_mappings (list) + # override the default output from pydantic by calling `to_dict()` of each item in mappings (list) _items = [] - if self.idp_group_mappings: - for _item_idp_group_mappings in self.idp_group_mappings: - if _item_idp_group_mappings: - _items.append(_item_idp_group_mappings.to_dict()) - _dict['idp_group_mappings'] = _items + if self.mappings: + for _item_mappings in self.mappings: + if _item_mappings: + _items.append(_item_mappings.to_dict()) + _dict['mappings'] = _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(): @@ -97,7 +97,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: return cls.model_validate(obj) _obj = cls.model_validate({ - "idp_group_mappings": [IdpGroupMapping.from_dict(_item) for _item in obj["idp_group_mappings"]] if obj.get("idp_group_mappings") is not None else None + "mappings": [IdpGroupMapping.from_dict(_item) for _item in obj["mappings"]] if obj.get("mappings") is not None else None }) # store additional fields in additional_properties for _key in obj.keys(): diff --git a/opal_security/models/propagation_status.py b/opal_security/models/propagation_status.py new file mode 100644 index 0000000..db7e1b1 --- /dev/null +++ b/opal_security/models/propagation_status.py @@ -0,0 +1,102 @@ +# coding: utf-8 + +""" + Opal API + + The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically. + + The version of the OpenAPI document: 1.0 + Contact: hello@opal.dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict +from typing import Any, ClassVar, Dict, List +from opal_security.models.propagation_status_enum import PropagationStatusEnum +from typing import Optional, Set +from typing_extensions import Self + +class PropagationStatus(BaseModel): + """ + The state of whether the push action was propagated to the remote system. If this is null, the access was synced from the remote system. + """ # noqa: E501 + status: PropagationStatusEnum + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["status"] + + 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 PropagationStatus 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 PropagationStatus from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "status": obj.get("status") + }) + # 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 new file mode 100644 index 0000000..0a98d55 --- /dev/null +++ b/opal_security/models/propagation_status_enum.py @@ -0,0 +1,57 @@ +# coding: utf-8 + +""" + Opal API + + The Opal API is a RESTful API that allows you to interact with the Opal Security platform programmatically. + + The version of the OpenAPI document: 1.0 + Contact: hello@opal.dev + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import json +from enum import Enum +from typing_extensions import Self + + +class PropagationStatusEnum(str, Enum): + """ + The status of whether the user has been synced to the group or resource in the remote system. + """ + + """ + allowed enum values + """ + SUCCESS = 'SUCCESS' + ERR_REMOTE_INTERNAL_ERROR = 'ERR_REMOTE_INTERNAL_ERROR' + ERR_REMOTE_USER_NOT_FOUND = 'ERR_REMOTE_USER_NOT_FOUND' + ERR_REMOTE_USER_NOT_LINKED = 'ERR_REMOTE_USER_NOT_LINKED' + ERR_REMOTE_RESOURCE_NOT_FOUND = 'ERR_REMOTE_RESOURCE_NOT_FOUND' + ERR_REMOTE_THROTTLE = 'ERR_REMOTE_THROTTLE' + ERR_NOT_AUTHORIZED_TO_QUERY_RESOURCE = 'ERR_NOT_AUTHORIZED_TO_QUERY_RESOURCE' + ERR_REMOTE_PROVISIONING_VIA_IDP_FAILED = 'ERR_REMOTE_PROVISIONING_VIA_IDP_FAILED' + ERR_IDP_EMAIL_UPDATE_CONFLICT = 'ERR_IDP_EMAIL_UPDATE_CONFLICT' + ERR_TIMEOUT = 'ERR_TIMEOUT' + ERR_UNKNOWN = 'ERR_UNKNOWN' + ERR_OPAL_INTERNAL_ERROR = 'ERR_OPAL_INTERNAL_ERROR' + ERR_ORG_READ_ONLY = 'ERR_ORG_READ_ONLY' + ERR_OPERATION_UNSUPPORTED = 'ERR_OPERATION_UNSUPPORTED' + PENDING = 'PENDING' + PENDING_MANUAL_PROPAGATION = 'PENDING_MANUAL_PROPAGATION' + PENDING_TICKET_CREATION = 'PENDING_TICKET_CREATION' + ERR_TICKET_CREATION_SKIPPED = 'ERR_TICKET_CREATION_SKIPPED' + 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' + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of PropagationStatusEnum from a JSON string""" + return cls(json.loads(json_str)) + + diff --git a/opal_security/models/request_configuration.py b/opal_security/models/request_configuration.py index 7829824..22839b2 100644 --- a/opal_security/models/request_configuration.py +++ b/opal_security/models/request_configuration.py @@ -37,7 +37,7 @@ class RequestConfiguration(BaseModel): recommended_duration_minutes: Optional[StrictInt] = Field(default=None, description="The recommended duration for which the resource should be requested (in minutes). -1 represents an indefinite duration.") require_support_ticket: StrictBool = Field(description="A bool representing whether or not access requests to the resource require an access ticket.") request_template_id: Optional[StrictStr] = Field(default=None, description="The ID of the associated request template.") - reviewer_stages: List[ReviewerStage] = Field(description="The list of reviewer stages for the request configuration.") + reviewer_stages: Optional[List[ReviewerStage]] = Field(default=None, description="The list of reviewer stages for the request configuration.") priority: StrictInt = Field(description="The priority of the request configuration.") additional_properties: Dict[str, Any] = {} __properties: ClassVar[List[str]] = ["condition", "allow_requests", "auto_approval", "require_mfa_to_request", "max_duration_minutes", "recommended_duration_minutes", "require_support_ticket", "request_template_id", "reviewer_stages", "priority"] diff --git a/opal_security/models/resource_access_user.py b/opal_security/models/resource_access_user.py index 5b3e579..daeb466 100644 --- a/opal_security/models/resource_access_user.py +++ b/opal_security/models/resource_access_user.py @@ -21,6 +21,7 @@ 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.propagation_status import PropagationStatus from opal_security.models.resource_access_level import ResourceAccessLevel from typing import Optional, Set from typing_extensions import Self @@ -37,8 +38,9 @@ class ResourceAccessUser(BaseModel): expiration_date: Optional[datetime] = Field(default=None, description="The day and time the user's access will expire.") has_direct_access: StrictBool = Field(description="The user has direct access to this resources (vs. indirectly, like through a group).") num_access_paths: StrictInt = Field(description="The number of ways in which the user has access through this resource (directly and indirectly).") + propagation_status: Optional[PropagationStatus] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["resource_id", "user_id", "access_level", "full_name", "email", "expiration_date", "has_direct_access", "num_access_paths"] + __properties: ClassVar[List[str]] = ["resource_id", "user_id", "access_level", "full_name", "email", "expiration_date", "has_direct_access", "num_access_paths", "propagation_status"] model_config = ConfigDict( populate_by_name=True, @@ -84,6 +86,9 @@ def to_dict(self) -> Dict[str, Any]: # override the default output from pydantic by calling `to_dict()` of access_level if self.access_level: _dict['access_level'] = self.access_level.to_dict() + # override the default output from pydantic by calling `to_dict()` of propagation_status + if self.propagation_status: + _dict['propagation_status'] = self.propagation_status.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(): @@ -108,7 +113,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "email": obj.get("email"), "expiration_date": obj.get("expiration_date"), "has_direct_access": obj.get("has_direct_access"), - "num_access_paths": obj.get("num_access_paths") + "num_access_paths": obj.get("num_access_paths"), + "propagation_status": PropagationStatus.from_dict(obj["propagation_status"]) if obj.get("propagation_status") is not None else None }) # store additional fields in additional_properties for _key in obj.keys(): diff --git a/opal_security/models/resource_type_enum.py b/opal_security/models/resource_type_enum.py index 6341c3c..5aa794e 100644 --- a/opal_security/models/resource_type_enum.py +++ b/opal_security/models/resource_type_enum.py @@ -51,6 +51,7 @@ class ResourceTypeEnum(str, Enum): AZURE_ENTERPRISE_APP = 'AZURE_ENTERPRISE_APP' CUSTOM = 'CUSTOM' CUSTOM_CONNECTOR = 'CUSTOM_CONNECTOR' + DATABRICKS_ACCOUNT_SERVICE_PRINCIPAL = 'DATABRICKS_ACCOUNT_SERVICE_PRINCIPAL' GCP_ORGANIZATION = 'GCP_ORGANIZATION' GCP_BUCKET = 'GCP_BUCKET' GCP_COMPUTE_INSTANCE = 'GCP_COMPUTE_INSTANCE' diff --git a/opal_security/models/update_idp_group_mappings_request_mappings_inner.py b/opal_security/models/update_idp_group_mappings_request_mappings_inner.py index 7c9fd2e..ae2964d 100644 --- a/opal_security/models/update_idp_group_mappings_request_mappings_inner.py +++ b/opal_security/models/update_idp_group_mappings_request_mappings_inner.py @@ -18,7 +18,7 @@ import re # noqa: F401 import json -from pydantic import BaseModel, ConfigDict, StrictStr +from pydantic import BaseModel, ConfigDict, StrictBool, StrictStr from typing import Any, ClassVar, Dict, List, Optional from typing import Optional, Set from typing_extensions import Self @@ -29,8 +29,9 @@ class UpdateIdpGroupMappingsRequestMappingsInner(BaseModel): """ # noqa: E501 group_id: Optional[StrictStr] = None alias: Optional[StrictStr] = None + hidden_from_end_user: Optional[StrictBool] = None additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["group_id", "alias"] + __properties: ClassVar[List[str]] = ["group_id", "alias", "hidden_from_end_user"] model_config = ConfigDict( populate_by_name=True, @@ -91,7 +92,8 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate({ "group_id": obj.get("group_id"), - "alias": obj.get("alias") + "alias": obj.get("alias"), + "hidden_from_end_user": obj.get("hidden_from_end_user") }) # store additional fields in additional_properties for _key in obj.keys(): diff --git a/pyproject.toml b/pyproject.toml index ed45f2a..f45123a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ include = ["opal_security/py.typed"] [tool.poetry.dependencies] python = "^3.8" -urllib3 = ">= 1.25.3 < 3.0.0" +urllib3 = ">= 1.25.3, < 3.0.0" python-dateutil = ">= 2.8.2" pydantic = ">= 2" typing-extensions = ">= 4.7.1" diff --git a/test/test_app_validation.py b/test/test_app_validation.py new file mode 100644 index 0000000..732efcf --- /dev/null +++ b/test/test_app_validation.py @@ -0,0 +1,63 @@ +# 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.app_validation import AppValidation + +class TestAppValidation(unittest.TestCase): + """AppValidation unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> AppValidation: + """Test AppValidation + 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 `AppValidation` + """ + model = AppValidation() + if include_optional: + return AppValidation( + key = 'iam:GetUser', + name = None, + usage_reason = 'Opal uses the 'iam:GetUser' permission to import users.', + details = '403 Google API Error. Service account is not authorized to access role assignments.', + severity = 'CRITICAL', + status = 'FAILED', + updated_at = '2021-01-06T20:00:00Z' + ) + else: + return AppValidation( + key = 'iam:GetUser', + name = None, + severity = 'CRITICAL', + status = 'FAILED', + updated_at = '2021-01-06T20:00:00Z', + ) + """ + + def testAppValidation(self): + """Test AppValidation""" + # 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_app_validation_severity_enum.py b/test/test_app_validation_severity_enum.py new file mode 100644 index 0000000..cbce09c --- /dev/null +++ b/test/test_app_validation_severity_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.app_validation_severity_enum import AppValidationSeverityEnum + +class TestAppValidationSeverityEnum(unittest.TestCase): + """AppValidationSeverityEnum unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testAppValidationSeverityEnum(self): + """Test AppValidationSeverityEnum""" + # inst = AppValidationSeverityEnum() + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_app_validation_status_enum.py b/test/test_app_validation_status_enum.py new file mode 100644 index 0000000..032767c --- /dev/null +++ b/test/test_app_validation_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.app_validation_status_enum import AppValidationStatusEnum + +class TestAppValidationStatusEnum(unittest.TestCase): + """AppValidationStatusEnum unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testAppValidationStatusEnum(self): + """Test AppValidationStatusEnum""" + # inst = AppValidationStatusEnum() + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_propagation_status.py b/test/test_propagation_status.py new file mode 100644 index 0000000..1cf6108 --- /dev/null +++ b/test/test_propagation_status.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.propagation_status import PropagationStatus + +class TestPropagationStatus(unittest.TestCase): + """PropagationStatus unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> PropagationStatus: + """Test PropagationStatus + 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 `PropagationStatus` + """ + model = PropagationStatus() + if include_optional: + return PropagationStatus( + status = '[SUCCESS]' + ) + else: + return PropagationStatus( + status = '[SUCCESS]', + ) + """ + + def testPropagationStatus(self): + """Test PropagationStatus""" + # 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_propagation_status_enum.py b/test/test_propagation_status_enum.py new file mode 100644 index 0000000..e3b65bd --- /dev/null +++ b/test/test_propagation_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.propagation_status_enum import PropagationStatusEnum + +class TestPropagationStatusEnum(unittest.TestCase): + """PropagationStatusEnum unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testPropagationStatusEnum(self): + """Test PropagationStatusEnum""" + # inst = PropagationStatusEnum() + +if __name__ == '__main__': + unittest.main()