/// <summary>
        /// Retrieves the delegated tenant for the specified client and service.
        /// </summary>
        /// <param name="tenantStore">The <see cref="ITenantStore"/>.</param>
        /// <param name="clientTenantId">The Id of the client tenant.</param>
        /// <param name="serviceTenantId">
        /// The Id of the service tenant representing the service that needs to make use of the delegated tenant.
        /// </param>
        /// <returns>The client tenant.</returns>
        /// <exception cref="TenantNotFoundException">There is no tenant with the specified client or service tenant Id.</exception>
        /// <exception cref="ArgumentException">There is no delegated tenant for the specified client and service.</exception>
        /// <exception cref="InvalidMarainTenantTypeException">The tenant Ids provided do not match the correct types of tenant.</exception>
        public static async Task <ITenant> GetDelegatedTenantAsync(
            this ITenantStore tenantStore,
            string clientTenantId,
            string serviceTenantId)
        {
            // Whilst we're saying "client tenant", the client here could itself be a delegated tenant:
            ITenant client = await tenantStore.GetTenantOfTypeAsync(
                clientTenantId,
                MarainTenantType.Client,
                MarainTenantType.Delegated).ConfigureAwait(false);

            // This method will throw if there is no delegated tenant.
            string delegatedTenantId = client.GetDelegatedTenantIdForServiceId(serviceTenantId);

            return(await tenantStore.GetDelegatedTenantAsync(delegatedTenantId).ConfigureAwait(false));
        }
        public void ThenTheTenantCalledShouldHaveTheIdOfTheTenantCalledSetAsTheOn_Behalf_Of_TenantForTheServiceCalled(
            string enrolledTenantName,
            string onBehalfOfTenantName,
            string serviceTenantName)
        {
            InMemoryTenantProvider tenantProvider =
                ContainerBindings.GetServiceProvider(this.scenarioContext).GetRequiredService <InMemoryTenantProvider>();

            ITenant enrolledTenant = tenantProvider.GetTenantByName(enrolledTenantName)
                                     ?? throw new TenantNotFoundException($"Could not find tenant with name '{enrolledTenantName}'");

            ITenant onBehalfOfTenant = tenantProvider.GetTenantByName(onBehalfOfTenantName)
                                       ?? throw new TenantNotFoundException($"Could not find tenant with name '{onBehalfOfTenantName}'");

            ITenant serviceTenant = tenantProvider.GetTenantByName(serviceTenantName)
                                    ?? throw new TenantNotFoundException($"Could not find tenant with name '{serviceTenantName}'");

            Assert.AreEqual(onBehalfOfTenant.Id, enrolledTenant.GetDelegatedTenantIdForServiceId(serviceTenant.Id));
        }
        public void ThenTheTenantCalledShouldNotHaveADelegatedTenantForTheServiceCalled(
            string enrolledTenantName,
            string serviceTenantName)
        {
            InMemoryTenantProvider tenantProvider =
                ContainerBindings.GetServiceProvider(this.scenarioContext).GetRequiredService <InMemoryTenantProvider>();

            ITenant enrolledTenant = tenantProvider.GetTenantByName(enrolledTenantName)
                                     ?? throw new TenantNotFoundException($"Could not find tenant with name '{enrolledTenantName}'");

            ITenant serviceTenant = tenantProvider.GetTenantByName(serviceTenantName)
                                    ?? throw new TenantNotFoundException($"Could not find tenant with name '{serviceTenantName}'");

            try
            {
                enrolledTenant.GetDelegatedTenantIdForServiceId(serviceTenant.Id);
                Assert.Fail($"Did not expect tenant with name '{enrolledTenant}' to have a delegated tenant for service '{serviceTenantName}', but one exists.");
            }
            catch (ArgumentException)
            {
            }
        }
Exemplo n.º 4
0
        /// <inheritdoc/>
        public async Task <string> GetDelegatedTenantIdForRequestingTenantAsync(string tenantId)
        {
            ITenant tenant = await this.GetTenantAsync(tenantId).ConfigureAwait(false);

            return(tenant.GetDelegatedTenantIdForServiceId(this.serviceConfiguration.ServiceTenantId));
        }
        /// <summary>
        /// Unenrolls the specified tenant from the service.
        /// </summary>
        /// <param name="tenantStore">The tenant store.</param>
        /// <param name="enrolledTenant">The tenant that is currently enrolled.</param>
        /// <param name="serviceTenant">The service they need to be unenrolled from.</param>
        /// <param name="logger">Optional logger.</param>
        /// <returns>A task which completes when the unenrollment has finished.</returns>
        public static async Task UnenrollFromServiceAsync(
            this ITenantStore tenantStore,
            ITenant enrolledTenant,
            ITenant serviceTenant,
            ILogger?logger = null)
        {
            if (!enrolledTenant.IsEnrolledForService(serviceTenant.Id))
            {
                throw new InvalidOperationException(
                          $"Cannot unenroll tenant '{enrolledTenant.Name}' with Id '{enrolledTenant.Id}' from service with Id '{serviceTenant.Id}' because it is not currently enrolled");
            }

            logger?.LogDebug(
                "Unenrolling tenant '{enrolledTenantName}' with Id '{enrolledTenantId}' from service '{serviceTenantName}' with Id '{serviceTenantId}'",
                enrolledTenant.Name,
                enrolledTenant.Id,
                serviceTenant.Name,
                serviceTenant.Id);

            var propertiesToRemove = new List <string>();

            ServiceManifest manifest = serviceTenant.GetServiceManifest();

            // If there are dependencies, we first need to unenroll from each of those and then remove the delegated tenant.
            if (manifest.DependsOnServiceTenants.Count > 0)
            {
                logger?.LogDebug(
                    "Service '{serviceTenantName}' has dependencies. Retrieving delegated tenant for unenrollment.",
                    serviceTenant.Name);

                string delegatedTenantId = enrolledTenant.GetDelegatedTenantIdForServiceId(serviceTenant.Id);

                logger?.LogDebug(
                    "Retrieved delegated tenant with Id '{delegatedTenantId}. Unenrolling from dependencies.",
                    delegatedTenantId);

                foreach (ServiceDependency current in manifest.DependsOnServiceTenants)
                {
                    await tenantStore.UnenrollFromServiceAsync(delegatedTenantId, current.Id).ConfigureAwait(false);
                }

                // Now delete the delegated tenant.
                logger?.LogDebug(
                    "Deleting delegated tenant with Id '{delegatedTenantId}'.",
                    delegatedTenantId);
                await tenantStore.DeleteTenantAsync(delegatedTenantId).ConfigureAwait(false);

                propertiesToRemove.AddRange(enrolledTenant.GetPropertiesToRemoveDelegatedTenantForService(serviceTenant));
            }

            if (manifest.RequiredConfigurationEntries.Count > 0)
            {
                // Now remove any config for the service that's being unenrolled from.
                logger?.LogDebug(
                    "Removing configuration for service '{serviceTenantName}' from '{enrolledTenantName}'",
                    serviceTenant.Name,
                    enrolledTenant.Name);

                foreach (ServiceManifestRequiredConfigurationEntry current in manifest.RequiredConfigurationEntries)
                {
                    logger?.LogDebug(
                        "Removing configuration item '{requiredConfigurationEntryKey}' for service '{serviceTenantName}' from '{enrolledTenantName}'",
                        current.Key,
                        serviceTenant.Name,
                        enrolledTenant.Name);
                    propertiesToRemove.AddRange(current.GetPropertiesToRemoveFromTenant(enrolledTenant));
                }
            }

            // Finally, remove the enrollment entry for the service.
            logger?.LogDebug(
                "Removing enrollment entry for service '{serviceTenantName}' from '{enrolledTenantName}'",
                serviceTenant.Name,
                enrolledTenant.Name);

            IEnumerable <KeyValuePair <string, object> > propertiesToChange =
                enrolledTenant.GetPropertyUpdatesToRemoveServiceEnrollment(serviceTenant.Id);

            logger?.LogDebug(
                "Updating tenant '{enrolledTenantName}'",
                enrolledTenant.Name);

            await tenantStore.UpdateTenantAsync(
                enrolledTenant.Id,
                propertiesToSetOrAdd : propertiesToChange,
                propertiesToRemove : propertiesToRemove).ConfigureAwait(false);

            logger?.LogInformation(
                "Successfully unenrolled tenant '{enrolledTenantName}' with Id '{enrolledTenantId}' from service '{serviceTenantName}' with Id '{serviceTenantId}'",
                enrolledTenant.Name,
                enrolledTenant.Id,
                serviceTenant.Name,
                serviceTenant.Id);
        }