From 16cf5dfe001107773a3016f1252a37e8a2974e7a Mon Sep 17 00:00:00 2001 From: Philip Kalinsky Date: Thu, 5 Mar 2020 12:57:56 -0500 Subject: [PATCH] step in state machine to reset tenant admin password to random value --- ...b29ab247fb_tenant_admin_password_update.py | 297 ++++++++++++++++++ atat/domain/csp/cloud/azure_cloud_provider.py | 74 +++++ atat/domain/csp/cloud/mock_cloud_provider.py | 10 + atat/domain/csp/cloud/models.py | 9 + atat/models/mixins/state_machines.py | 1 + tests/domain/cloud/test_azure_csp.py | 34 ++ tests/domain/test_portfolio_state_machine.py | 1 + 7 files changed, 426 insertions(+) create mode 100644 alembic/versions/18b29ab247fb_tenant_admin_password_update.py diff --git a/alembic/versions/18b29ab247fb_tenant_admin_password_update.py b/alembic/versions/18b29ab247fb_tenant_admin_password_update.py new file mode 100644 index 00000000..ca5b51f2 --- /dev/null +++ b/alembic/versions/18b29ab247fb_tenant_admin_password_update.py @@ -0,0 +1,297 @@ +"""tenant admin password update + +Revision ID: 18b29ab247fb +Revises: 9f2813487e00 +Create Date: 2020-03-05 12:37:42.056513 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '18b29ab247fb' # pragma: allowlist secret +down_revision = '9f2813487e00' # pragma: allowlist secret +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column( + "portfolio_state_machines", + "state", + type_=sa.Enum( + "UNSTARTED", + "STARTING", + "STARTED", + "COMPLETED", + "FAILED", + "TENANT_CREATED", + "TENANT_IN_PROGRESS", + "TENANT_FAILED", + "BILLING_PROFILE_CREATION_CREATED", + "BILLING_PROFILE_CREATION_IN_PROGRESS", + "BILLING_PROFILE_CREATION_FAILED", + "BILLING_PROFILE_VERIFICATION_CREATED", + "BILLING_PROFILE_VERIFICATION_IN_PROGRESS", + "BILLING_PROFILE_VERIFICATION_FAILED", + "BILLING_PROFILE_TENANT_ACCESS_CREATED", + "BILLING_PROFILE_TENANT_ACCESS_IN_PROGRESS", + "BILLING_PROFILE_TENANT_ACCESS_FAILED", + "TASK_ORDER_BILLING_CREATION_CREATED", + "TASK_ORDER_BILLING_CREATION_IN_PROGRESS", + "TASK_ORDER_BILLING_CREATION_FAILED", + "TASK_ORDER_BILLING_VERIFICATION_CREATED", + "TASK_ORDER_BILLING_VERIFICATION_IN_PROGRESS", + "TASK_ORDER_BILLING_VERIFICATION_FAILED", + "BILLING_INSTRUCTION_CREATED", + "BILLING_INSTRUCTION_IN_PROGRESS", + "BILLING_INSTRUCTION_FAILED", + "PRODUCT_PURCHASE_CREATED", + "PRODUCT_PURCHASE_IN_PROGRESS", + "PRODUCT_PURCHASE_FAILED", + "PRODUCT_PURCHASE_VERIFICATION_CREATED", + "PRODUCT_PURCHASE_VERIFICATION_IN_PROGRESS", + "PRODUCT_PURCHASE_VERIFICATION_FAILED", + "TENANT_PRINCIPAL_APP_CREATED", + "TENANT_PRINCIPAL_APP_IN_PROGRESS", + "TENANT_PRINCIPAL_APP_FAILED", + "TENANT_PRINCIPAL_CREATED", + "TENANT_PRINCIPAL_IN_PROGRESS", + "TENANT_PRINCIPAL_FAILED", + "TENANT_PRINCIPAL_CREDENTIAL_CREATED", + "TENANT_PRINCIPAL_CREDENTIAL_IN_PROGRESS", + "TENANT_PRINCIPAL_CREDENTIAL_FAILED", + "ADMIN_ROLE_DEFINITION_CREATED", + "ADMIN_ROLE_DEFINITION_IN_PROGRESS", + "ADMIN_ROLE_DEFINITION_FAILED", + "PRINCIPAL_ADMIN_ROLE_CREATED", + "PRINCIPAL_ADMIN_ROLE_IN_PROGRESS", + "PRINCIPAL_ADMIN_ROLE_FAILED", + "INITIAL_MGMT_GROUP_CREATED", + "INITIAL_MGMT_GROUP_IN_PROGRESS", + "INITIAL_MGMT_GROUP_FAILED", + "INITIAL_MGMT_GROUP_VERIFICATION_CREATED", + "INITIAL_MGMT_GROUP_VERIFICATION_IN_PROGRESS", + "INITIAL_MGMT_GROUP_VERIFICATION_FAILED", + "TENANT_ADMIN_OWNERSHIP_CREATED", + "TENANT_ADMIN_OWNERSHIP_IN_PROGRESS", + "TENANT_ADMIN_OWNERSHIP_FAILED", + "TENANT_PRINCIPAL_OWNERSHIP_CREATED", + "TENANT_PRINCIPAL_OWNERSHIP_IN_PROGRESS", + "TENANT_PRINCIPAL_OWNERSHIP_FAILED", + "BILLING_OWNER_CREATED", + "BILLING_OWNER_IN_PROGRESS", + "BILLING_OWNER_FAILED", + name="fsmstates", + native_enum=False, + ), + existing_type=sa.Enum( + "UNSTARTED", + "STARTING", + "STARTED", + "COMPLETED", + "FAILED", + "TENANT_CREATED", + "TENANT_IN_PROGRESS", + "TENANT_FAILED", + "BILLING_PROFILE_CREATION_CREATED", + "BILLING_PROFILE_CREATION_IN_PROGRESS", + "BILLING_PROFILE_CREATION_FAILED", + "BILLING_PROFILE_VERIFICATION_CREATED", + "BILLING_PROFILE_VERIFICATION_IN_PROGRESS", + "BILLING_PROFILE_VERIFICATION_FAILED", + "BILLING_PROFILE_TENANT_ACCESS_CREATED", + "BILLING_PROFILE_TENANT_ACCESS_IN_PROGRESS", + "BILLING_PROFILE_TENANT_ACCESS_FAILED", + "TASK_ORDER_BILLING_CREATION_CREATED", + "TASK_ORDER_BILLING_CREATION_IN_PROGRESS", + "TASK_ORDER_BILLING_CREATION_FAILED", + "TASK_ORDER_BILLING_VERIFICATION_CREATED", + "TASK_ORDER_BILLING_VERIFICATION_IN_PROGRESS", + "TASK_ORDER_BILLING_VERIFICATION_FAILED", + "BILLING_INSTRUCTION_CREATED", + "BILLING_INSTRUCTION_IN_PROGRESS", + "BILLING_INSTRUCTION_FAILED", + "PRODUCT_PURCHASE_CREATED", + "PRODUCT_PURCHASE_IN_PROGRESS", + "PRODUCT_PURCHASE_FAILED", + "PRODUCT_PURCHASE_VERIFICATION_CREATED", + "PRODUCT_PURCHASE_VERIFICATION_IN_PROGRESS", + "PRODUCT_PURCHASE_VERIFICATION_FAILED", + "TENANT_PRINCIPAL_APP_CREATED", + "TENANT_PRINCIPAL_APP_IN_PROGRESS", + "TENANT_PRINCIPAL_APP_FAILED", + "TENANT_PRINCIPAL_CREATED", + "TENANT_PRINCIPAL_IN_PROGRESS", + "TENANT_PRINCIPAL_FAILED", + "TENANT_PRINCIPAL_CREDENTIAL_CREATED", + "TENANT_PRINCIPAL_CREDENTIAL_IN_PROGRESS", + "TENANT_PRINCIPAL_CREDENTIAL_FAILED", + "ADMIN_ROLE_DEFINITION_CREATED", + "ADMIN_ROLE_DEFINITION_IN_PROGRESS", + "ADMIN_ROLE_DEFINITION_FAILED", + "PRINCIPAL_ADMIN_ROLE_CREATED", + "PRINCIPAL_ADMIN_ROLE_IN_PROGRESS", + "PRINCIPAL_ADMIN_ROLE_FAILED", + "INITIAL_MGMT_GROUP_CREATED", + "INITIAL_MGMT_GROUP_IN_PROGRESS", + "INITIAL_MGMT_GROUP_FAILED", + "INITIAL_MGMT_GROUP_VERIFICATION_CREATED", + "INITIAL_MGMT_GROUP_VERIFICATION_IN_PROGRESS", + "INITIAL_MGMT_GROUP_VERIFICATION_FAILED", + "TENANT_ADMIN_OWNERSHIP_CREATED", + "TENANT_ADMIN_OWNERSHIP_IN_PROGRESS", + "TENANT_ADMIN_OWNERSHIP_FAILED", + "TENANT_ADMIN_CREDENTIAL_RESET_CREATED", + "TENANT_ADMIN_CREDENTIAL_RESET_IN_PROGRESS", + "TENANT_ADMIN_CREDENTIAL_RESET_FAILED", + "TENANT_PRINCIPAL_OWNERSHIP_CREATED", + "TENANT_PRINCIPAL_OWNERSHIP_IN_PROGRESS", + "TENANT_PRINCIPAL_OWNERSHIP_FAILED", + name="fsmstates", + native_enum=False, + ), + existing_nullable=False, + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column( + "portfolio_state_machines", + "state", + type_=sa.Enum( + "UNSTARTED", + "STARTING", + "STARTED", + "COMPLETED", + "FAILED", + "TENANT_CREATED", + "TENANT_IN_PROGRESS", + "TENANT_FAILED", + "BILLING_PROFILE_CREATION_CREATED", + "BILLING_PROFILE_CREATION_IN_PROGRESS", + "BILLING_PROFILE_CREATION_FAILED", + "BILLING_PROFILE_VERIFICATION_CREATED", + "BILLING_PROFILE_VERIFICATION_IN_PROGRESS", + "BILLING_PROFILE_VERIFICATION_FAILED", + "BILLING_PROFILE_TENANT_ACCESS_CREATED", + "BILLING_PROFILE_TENANT_ACCESS_IN_PROGRESS", + "BILLING_PROFILE_TENANT_ACCESS_FAILED", + "TASK_ORDER_BILLING_CREATION_CREATED", + "TASK_ORDER_BILLING_CREATION_IN_PROGRESS", + "TASK_ORDER_BILLING_CREATION_FAILED", + "TASK_ORDER_BILLING_VERIFICATION_CREATED", + "TASK_ORDER_BILLING_VERIFICATION_IN_PROGRESS", + "TASK_ORDER_BILLING_VERIFICATION_FAILED", + "BILLING_INSTRUCTION_CREATED", + "BILLING_INSTRUCTION_IN_PROGRESS", + "BILLING_INSTRUCTION_FAILED", + "PRODUCT_PURCHASE_CREATED", + "PRODUCT_PURCHASE_IN_PROGRESS", + "PRODUCT_PURCHASE_FAILED", + "PRODUCT_PURCHASE_VERIFICATION_CREATED", + "PRODUCT_PURCHASE_VERIFICATION_IN_PROGRESS", + "PRODUCT_PURCHASE_VERIFICATION_FAILED", + "TENANT_PRINCIPAL_APP_CREATED", + "TENANT_PRINCIPAL_APP_IN_PROGRESS", + "TENANT_PRINCIPAL_APP_FAILED", + "TENANT_PRINCIPAL_CREATED", + "TENANT_PRINCIPAL_IN_PROGRESS", + "TENANT_PRINCIPAL_FAILED", + "TENANT_PRINCIPAL_CREDENTIAL_CREATED", + "TENANT_PRINCIPAL_CREDENTIAL_IN_PROGRESS", + "TENANT_PRINCIPAL_CREDENTIAL_FAILED", + "ADMIN_ROLE_DEFINITION_CREATED", + "ADMIN_ROLE_DEFINITION_IN_PROGRESS", + "ADMIN_ROLE_DEFINITION_FAILED", + "PRINCIPAL_ADMIN_ROLE_CREATED", + "PRINCIPAL_ADMIN_ROLE_IN_PROGRESS", + "PRINCIPAL_ADMIN_ROLE_FAILED", + "INITIAL_MGMT_GROUP_CREATED", + "INITIAL_MGMT_GROUP_IN_PROGRESS", + "INITIAL_MGMT_GROUP_FAILED", + "INITIAL_MGMT_GROUP_VERIFICATION_CREATED", + "INITIAL_MGMT_GROUP_VERIFICATION_IN_PROGRESS", + "INITIAL_MGMT_GROUP_VERIFICATION_FAILED", + "TENANT_ADMIN_OWNERSHIP_CREATED", + "TENANT_ADMIN_OWNERSHIP_IN_PROGRESS", + "TENANT_ADMIN_OWNERSHIP_FAILED", + "TENANT_PRINCIPAL_OWNERSHIP_CREATED", + "TENANT_PRINCIPAL_OWNERSHIP_IN_PROGRESS", + "TENANT_PRINCIPAL_OWNERSHIP_FAILED", + name="fsmstates", + native_enum=False, + ), + existing_type=sa.Enum( + "UNSTARTED", + "STARTING", + "STARTED", + "COMPLETED", + "FAILED", + "TENANT_CREATED", + "TENANT_IN_PROGRESS", + "TENANT_FAILED", + "BILLING_PROFILE_CREATION_CREATED", + "BILLING_PROFILE_CREATION_IN_PROGRESS", + "BILLING_PROFILE_CREATION_FAILED", + "BILLING_PROFILE_VERIFICATION_CREATED", + "BILLING_PROFILE_VERIFICATION_IN_PROGRESS", + "BILLING_PROFILE_VERIFICATION_FAILED", + "BILLING_PROFILE_TENANT_ACCESS_CREATED", + "BILLING_PROFILE_TENANT_ACCESS_IN_PROGRESS", + "BILLING_PROFILE_TENANT_ACCESS_FAILED", + "TASK_ORDER_BILLING_CREATION_CREATED", + "TASK_ORDER_BILLING_CREATION_IN_PROGRESS", + "TASK_ORDER_BILLING_CREATION_FAILED", + "TASK_ORDER_BILLING_VERIFICATION_CREATED", + "TASK_ORDER_BILLING_VERIFICATION_IN_PROGRESS", + "TASK_ORDER_BILLING_VERIFICATION_FAILED", + "BILLING_INSTRUCTION_CREATED", + "BILLING_INSTRUCTION_IN_PROGRESS", + "BILLING_INSTRUCTION_FAILED", + "PRODUCT_PURCHASE_CREATED", + "PRODUCT_PURCHASE_IN_PROGRESS", + "PRODUCT_PURCHASE_FAILED", + "PRODUCT_PURCHASE_VERIFICATION_CREATED", + "PRODUCT_PURCHASE_VERIFICATION_IN_PROGRESS", + "PRODUCT_PURCHASE_VERIFICATION_FAILED", + "TENANT_PRINCIPAL_APP_CREATED", + "TENANT_PRINCIPAL_APP_IN_PROGRESS", + "TENANT_PRINCIPAL_APP_FAILED", + "TENANT_PRINCIPAL_CREATED", + "TENANT_PRINCIPAL_IN_PROGRESS", + "TENANT_PRINCIPAL_FAILED", + "TENANT_PRINCIPAL_CREDENTIAL_CREATED", + "TENANT_PRINCIPAL_CREDENTIAL_IN_PROGRESS", + "TENANT_PRINCIPAL_CREDENTIAL_FAILED", + "ADMIN_ROLE_DEFINITION_CREATED", + "ADMIN_ROLE_DEFINITION_IN_PROGRESS", + "ADMIN_ROLE_DEFINITION_FAILED", + "PRINCIPAL_ADMIN_ROLE_CREATED", + "PRINCIPAL_ADMIN_ROLE_IN_PROGRESS", + "PRINCIPAL_ADMIN_ROLE_FAILED", + "INITIAL_MGMT_GROUP_CREATED", + "INITIAL_MGMT_GROUP_IN_PROGRESS", + "INITIAL_MGMT_GROUP_FAILED", + "INITIAL_MGMT_GROUP_VERIFICATION_CREATED", + "INITIAL_MGMT_GROUP_VERIFICATION_IN_PROGRESS", + "INITIAL_MGMT_GROUP_VERIFICATION_FAILED", + "TENANT_ADMIN_OWNERSHIP_CREATED", + "TENANT_ADMIN_OWNERSHIP_IN_PROGRESS", + "TENANT_ADMIN_OWNERSHIP_FAILED", + "TENANT_PRINCIPAL_OWNERSHIP_CREATED", + "TENANT_PRINCIPAL_OWNERSHIP_IN_PROGRESS", + "TENANT_PRINCIPAL_OWNERSHIP_FAILED", + "BILLING_OWNER_CREATED", + "BILLING_OWNER_IN_PROGRESS", + "BILLING_OWNER_FAILED", + name="fsmstates", + native_enum=False, + ), + existing_nullable=False, + ) + # ### end Alembic commands ### diff --git a/atat/domain/csp/cloud/azure_cloud_provider.py b/atat/domain/csp/cloud/azure_cloud_provider.py index d6b6d7ec..9b0eba37 100644 --- a/atat/domain/csp/cloud/azure_cloud_provider.py +++ b/atat/domain/csp/cloud/azure_cloud_provider.py @@ -1,4 +1,6 @@ import json +import random +import string from secrets import token_hex, token_urlsafe from uuid import uuid4 from flask import current_app as app @@ -54,6 +56,8 @@ from .models import ( TaskOrderBillingVerificationCSPResult, TenantAdminOwnershipCSPPayload, TenantAdminOwnershipCSPResult, + TenantAdminCredentialResetCSPPayload, + TenantAdminCredentialResetCSPResult, TenantCSPPayload, TenantCSPResult, TenantPrincipalAppCSPPayload, @@ -933,6 +937,20 @@ class AzureCloudProvider(CloudProviderInterface): f"azure application error during product purchase verification. {str(exc)}", ) + def create_tenant_admin_credential_reset( + self, payload: TenantAdminCredentialResetCSPPayload + ): + + graph_token = self._get_tenant_admin_token( + payload.tenant_id, self.graph_resource + ) + if graph_token is None: + raise AuthenticationException( + "Could not resolve graph token for tenant admin" + ) + + self._update_active_directory_user_password_profile(graph_token, payload) + def create_tenant_admin_ownership(self, payload: TenantAdminOwnershipCSPPayload): mgmt_token = self._get_elevated_management_token(payload.tenant_id) @@ -1581,6 +1599,62 @@ class AzureCloudProvider(CloudProviderInterface): f"azure application error updating active directory user email. {str(exc)}", ) + def _update_active_directory_user_password_profile(self, graph_token, payload): + request_body = { + "passwordProfile": { + "forceChangePasswordNextSignIn": True, + "forceChangePasswordNextSignInWithMfa": False, + "password": payload.new_password + or "".join(random.choice(string.ascii_letters) for i in range(15)), + } + } + + auth_header = { + "Authorization": f"Bearer {graph_token}", + } + + url = f"{self.graph_resource}v1.0/users/{payload.user_id}" + + try: + result = self.sdk.requests.patch( + url, headers=auth_header, json=request_body, timeout=30 + ) + result.raise_for_status() + + if result.ok: + return True + else: + raise UserProvisioningException( + f"Failed update user password profile: {response.json()}" + ) + + except self.sdk.requests.exceptions.ConnectionError: + app.logger.error( + f"Could not update active directory user password profile. Connection Error", + exc_info=1, + ) + raise ConnectionException( + "connection error updating active directory user password profile" + ) + except self.sdk.requests.exceptions.Timeout: + app.logger.error( + f"Could not update active directory user password profile. Request timed out.", + exc_info=1, + ) + raise ConnectionException( + "timout error updating active directory user password profile" + ) + except self.sdk.requests.exceptions.HTTPError as exc: + app.logger.error( + result.status_code, + "azure application error updating active directory user password profile", + exc_info=1, + ) + raise UnknownServerException( + result.status_code, + f"azure application error updating active directory user password profile. {str(exc)}", + ) + def create_user_role(self, payload: UserRoleCSPPayload): graph_token = self._get_tenant_principal_token(payload.tenant_id) if graph_token is None: diff --git a/atat/domain/csp/cloud/mock_cloud_provider.py b/atat/domain/csp/cloud/mock_cloud_provider.py index 01cf3bfd..a69874ad 100644 --- a/atat/domain/csp/cloud/mock_cloud_provider.py +++ b/atat/domain/csp/cloud/mock_cloud_provider.py @@ -51,6 +51,8 @@ from .models import ( TaskOrderBillingVerificationCSPResult, TenantAdminOwnershipCSPPayload, TenantAdminOwnershipCSPResult, + TenantAdminCredentialResetCSPPayload, + TenantAdminCredentialResetCSPResult, TenantCSPPayload, TenantCSPResult, TenantPrincipalAppCSPPayload, @@ -335,6 +337,14 @@ class MockCloudProvider(CloudProviderInterface): self._maybe_raise(self.UNAUTHORIZED_RATE, self.AUTHORIZATION_EXCEPTION) return TenantAdminOwnershipCSPResult(**dict(id="admin_owner_assignment_id")) + def create_tenant_admin_credential_reset( + self, payload: TenantAdminCredentialResetCSPPayload + ): + self._maybe_raise(self.NETWORK_FAILURE_PCT, self.NETWORK_EXCEPTION) + self._maybe_raise(self.SERVER_FAILURE_PCT, self.SERVER_EXCEPTION) + self._maybe_raise(self.UNAUTHORIZED_RATE, self.AUTHORIZATION_EXCEPTION) + return TenantAdminCredentialResetCSPResult() + def create_tenant_principal_ownership( self, payload: TenantPrincipalOwnershipCSPPayload ): diff --git a/atat/domain/csp/cloud/models.py b/atat/domain/csp/cloud/models.py index 21c70f43..1fb7d9b1 100644 --- a/atat/domain/csp/cloud/models.py +++ b/atat/domain/csp/cloud/models.py @@ -244,6 +244,15 @@ class TenantAdminOwnershipCSPResult(AliasModel): fields = {"admin_owner_assignment_id": "id"} +class TenantAdminCredentialResetCSPPayload(BaseCSPPayload): + user_id: str + new_password: Optional[str] + + +class TenantAdminCredentialResetCSPResult(AliasModel): + pass + + class TenantPrincipalOwnershipCSPPayload(BaseCSPPayload): principal_id: str diff --git a/atat/models/mixins/state_machines.py b/atat/models/mixins/state_machines.py index bd834c3d..74fb02d0 100644 --- a/atat/models/mixins/state_machines.py +++ b/atat/models/mixins/state_machines.py @@ -29,6 +29,7 @@ class AzureStages(Enum): TENANT_ADMIN_OWNERSHIP = "tenant admin ownership" TENANT_PRINCIPAL_OWNERSHIP = "tenant principial ownership" BILLING_OWNER = "billing owner" + TENANT_ADMIN_CREDENTIAL_RESET = "tenant admin credential reset" def _build_csp_states(csp_stages): diff --git a/tests/domain/cloud/test_azure_csp.py b/tests/domain/cloud/test_azure_csp.py index 96e985b9..81425bb0 100644 --- a/tests/domain/cloud/test_azure_csp.py +++ b/tests/domain/cloud/test_azure_csp.py @@ -56,6 +56,8 @@ from atat.domain.csp.cloud.models import ( TaskOrderBillingVerificationCSPResult, TenantAdminOwnershipCSPPayload, TenantAdminOwnershipCSPResult, + TenantAdminCredentialResetCSPPayload, + TenantAdminCredentialResetCSPResult, TenantCSPPayload, TenantCSPResult, TenantPrincipalAppCSPPayload, @@ -1431,6 +1433,38 @@ def test_update_active_directory_user_email(mock_azure: AzureCloudProvider): assert result +def test_update_active_directory_user_password_profile(mock_azure: AzureCloudProvider): + mock_result = Mock() + mock_result.ok = True + mock_http_error_resp = mock_requests_response( + status=500, + raise_for_status=mock_azure.sdk.requests.exceptions.HTTPError( + "500 Server Error" + ), + ) + mock_azure.sdk.requests.patch.side_effect = [ + mock_azure.sdk.requests.exceptions.ConnectionError, + mock_azure.sdk.requests.exceptions.Timeout, + mock_http_error_resp, + mock_result, + ] + payload = TenantAdminCredentialResetCSPPayload( + tenant_id="6d2d2d6c-a6d6-41e1-8bb1-73d11475f8f4", + user_id="admin", + new_password="asdfghjkl", # pragma: allowlist secret + ) + with pytest.raises(ConnectionException): + mock_azure._update_active_directory_user_password_profile("token", payload) + with pytest.raises(ConnectionException): + mock_azure._update_active_directory_user_password_profile("token", payload) + with pytest.raises(UnknownServerException, match=r".*500 Server Error.*"): + mock_azure._update_active_directory_user_password_profile("token", payload) + + result = mock_azure._update_active_directory_user_password_profile("token", payload) + + assert result + + def test_create_user(mock_azure: AzureCloudProvider): with patch.object( AzureCloudProvider, diff --git a/tests/domain/test_portfolio_state_machine.py b/tests/domain/test_portfolio_state_machine.py index d0d71623..ab7f4414 100644 --- a/tests/domain/test_portfolio_state_machine.py +++ b/tests/domain/test_portfolio_state_machine.py @@ -305,6 +305,7 @@ def test_fsm_transition_start( FSMStates.INITIAL_MGMT_GROUP_CREATED, FSMStates.INITIAL_MGMT_GROUP_VERIFICATION_CREATED, FSMStates.TENANT_ADMIN_OWNERSHIP_CREATED, + FSMStates.TENANT_ADMIN_CREDENTIAL_RESET_CREATED, FSMStates.TENANT_PRINCIPAL_OWNERSHIP_CREATED, FSMStates.BILLING_OWNER_CREATED, FSMStates.COMPLETED,