1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-30 07:36:14 -05:00

Key Connector feature toggle (#1716)

This commit is contained in:
Oscar Hinton
2021-11-17 11:46:35 +01:00
committed by GitHub
parent 3a22f91ff5
commit f866b25e43
45 changed files with 3720 additions and 69 deletions

View File

@ -10,6 +10,7 @@ using NSubstitute;
using System.Threading.Tasks;
using System.Security.Claims;
using System;
using Bit.Core.Models.Data;
using Xunit;
namespace Bit.Api.Test.Controllers
@ -59,7 +60,10 @@ namespace Bit.Api.Test.Controllers
var ssoConfig = new SsoConfig
{
Id = default,
Data = "{\"useKeyConnector\": true}",
Data = new SsoConfigurationData
{
KeyConnectorEnabled = true,
}.Serialize(),
Enabled = true,
OrganizationId = orgId,
};

View File

@ -25,6 +25,7 @@ namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
x.MaxCollections.Equals(y.MaxCollections) &&
x.UsePolicies.Equals(y.UsePolicies) &&
x.UseSso.Equals(y.UseSso) &&
x.UseKeyConnector.Equals(y.UseKeyConnector) &&
x.UseGroups.Equals(y.UseGroups) &&
x.UseDirectory.Equals(y.UseDirectory) &&
x.UseEvents.Equals(y.UseEvents) &&

View File

@ -909,7 +909,7 @@ namespace Bit.Core.Test.Services
SsoConfig ssoConfig)
{
ssoConfig.Enabled = true;
ssoConfig.SetData(new SsoConfigurationData { UseKeyConnector = true });
ssoConfig.SetData(new SsoConfigurationData { KeyConnectorEnabled = true });
var ssoConfigRepository = sutProvider.GetDependency<ISsoConfigRepository>();
var organizationRepository = sutProvider.GetDependency<IOrganizationRepository>();
var applicationCacheService = sutProvider.GetDependency<IApplicationCacheService>();

View File

@ -144,7 +144,7 @@ namespace Bit.Core.Test.Services
});
var ssoConfig = new SsoConfig { Enabled = true };
var data = new SsoConfigurationData { UseKeyConnector = true };
var data = new SsoConfigurationData { KeyConnectorEnabled = true };
ssoConfig.SetData(data);
sutProvider.GetDependency<ISsoConfigRepository>()

View File

@ -15,9 +15,9 @@ namespace Bit.Core.Test.Services
public class SsoConfigServiceTests
{
[Theory, CustomAutoData(typeof(SutProviderCustomization))]
public async Task SaveAsync_ExistingItem_UpdatesRevisionDateOnly(SutProvider<SsoConfigService> sutProvider)
public async Task SaveAsync_ExistingItem_UpdatesRevisionDateOnly(SutProvider<SsoConfigService> sutProvider,
Organization organization)
{
var utcNow = DateTime.UtcNow;
var ssoConfig = new SsoConfig
@ -25,7 +25,7 @@ namespace Bit.Core.Test.Services
Id = 1,
Data = "{}",
Enabled = true,
OrganizationId = Guid.NewGuid(),
OrganizationId = organization.Id,
CreationDate = utcNow.AddDays(-10),
RevisionDate = utcNow.AddDays(-10),
};
@ -33,7 +33,7 @@ namespace Bit.Core.Test.Services
sutProvider.GetDependency<ISsoConfigRepository>()
.UpsertAsync(ssoConfig).Returns(Task.CompletedTask);
await sutProvider.Sut.SaveAsync(ssoConfig);
await sutProvider.Sut.SaveAsync(ssoConfig, organization);
await sutProvider.GetDependency<ISsoConfigRepository>().Received()
.UpsertAsync(ssoConfig);
@ -43,7 +43,8 @@ namespace Bit.Core.Test.Services
}
[Theory, CustomAutoData(typeof(SutProviderCustomization))]
public async Task SaveAsync_NewItem_UpdatesCreationAndRevisionDate(SutProvider<SsoConfigService> sutProvider)
public async Task SaveAsync_NewItem_UpdatesCreationAndRevisionDate(SutProvider<SsoConfigService> sutProvider,
Organization organization)
{
var utcNow = DateTime.UtcNow;
@ -52,7 +53,7 @@ namespace Bit.Core.Test.Services
Id = default,
Data = "{}",
Enabled = true,
OrganizationId = Guid.NewGuid(),
OrganizationId = organization.Id,
CreationDate = utcNow.AddDays(-10),
RevisionDate = utcNow.AddDays(-10),
};
@ -60,7 +61,7 @@ namespace Bit.Core.Test.Services
sutProvider.GetDependency<ISsoConfigRepository>()
.UpsertAsync(ssoConfig).Returns(Task.CompletedTask);
await sutProvider.Sut.SaveAsync(ssoConfig);
await sutProvider.Sut.SaveAsync(ssoConfig, organization);
await sutProvider.GetDependency<ISsoConfigRepository>().Received()
.UpsertAsync(ssoConfig);
@ -70,16 +71,20 @@ namespace Bit.Core.Test.Services
}
[Theory, CustomAutoData(typeof(SutProviderCustomization))]
public async Task SaveAsync_PreventDisablingKeyConnector(SutProvider<SsoConfigService> sutProvider, Guid orgId)
public async Task SaveAsync_PreventDisablingKeyConnector(SutProvider<SsoConfigService> sutProvider,
Organization organization)
{
var utcNow = DateTime.UtcNow;
var oldSsoConfig = new SsoConfig
{
Id = 1,
Data = "{\"useKeyConnector\": true}",
Data = new SsoConfigurationData
{
KeyConnectorEnabled = true,
}.Serialize(),
Enabled = true,
OrganizationId = orgId,
OrganizationId = organization.Id,
CreationDate = utcNow.AddDays(-10),
RevisionDate = utcNow.AddDays(-10),
};
@ -89,19 +94,19 @@ namespace Bit.Core.Test.Services
Id = 1,
Data = "{}",
Enabled = true,
OrganizationId = orgId,
OrganizationId = organization.Id,
CreationDate = utcNow.AddDays(-10),
RevisionDate = utcNow,
};
var ssoConfigRepository = sutProvider.GetDependency<ISsoConfigRepository>();
ssoConfigRepository.GetByOrganizationIdAsync(orgId).Returns(oldSsoConfig);
ssoConfigRepository.GetByOrganizationIdAsync(organization.Id).Returns(oldSsoConfig);
ssoConfigRepository.UpsertAsync(newSsoConfig).Returns(Task.CompletedTask);
sutProvider.GetDependency<IOrganizationUserRepository>().GetManyDetailsByOrganizationAsync(orgId)
sutProvider.GetDependency<IOrganizationUserRepository>().GetManyDetailsByOrganizationAsync(organization.Id)
.Returns(new[] { new OrganizationUserUserDetails { UsesKeyConnector = true } });
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.SaveAsync(newSsoConfig));
() => sutProvider.Sut.SaveAsync(newSsoConfig, organization));
Assert.Contains("Key Connector cannot be disabled at this moment.", exception.Message);
@ -111,16 +116,19 @@ namespace Bit.Core.Test.Services
[Theory, CustomAutoData(typeof(SutProviderCustomization))]
public async Task SaveAsync_AllowDisablingKeyConnectorWhenNoUserIsUsingIt(
SutProvider<SsoConfigService> sutProvider, Guid orgId)
SutProvider<SsoConfigService> sutProvider, Organization organization)
{
var utcNow = DateTime.UtcNow;
var oldSsoConfig = new SsoConfig
{
Id = 1,
Data = "{\"useKeyConnector\": true}",
Data = new SsoConfigurationData
{
KeyConnectorEnabled = true,
}.Serialize(),
Enabled = true,
OrganizationId = orgId,
OrganizationId = organization.Id,
CreationDate = utcNow.AddDays(-10),
RevisionDate = utcNow.AddDays(-10),
};
@ -130,37 +138,41 @@ namespace Bit.Core.Test.Services
Id = 1,
Data = "{}",
Enabled = true,
OrganizationId = orgId,
OrganizationId = organization.Id,
CreationDate = utcNow.AddDays(-10),
RevisionDate = utcNow,
};
var ssoConfigRepository = sutProvider.GetDependency<ISsoConfigRepository>();
ssoConfigRepository.GetByOrganizationIdAsync(orgId).Returns(oldSsoConfig);
ssoConfigRepository.GetByOrganizationIdAsync(organization.Id).Returns(oldSsoConfig);
ssoConfigRepository.UpsertAsync(newSsoConfig).Returns(Task.CompletedTask);
sutProvider.GetDependency<IOrganizationUserRepository>().GetManyDetailsByOrganizationAsync(orgId)
sutProvider.GetDependency<IOrganizationUserRepository>().GetManyDetailsByOrganizationAsync(organization.Id)
.Returns(new[] { new OrganizationUserUserDetails { UsesKeyConnector = false } });
await sutProvider.Sut.SaveAsync(newSsoConfig);
await sutProvider.Sut.SaveAsync(newSsoConfig, organization);
}
[Theory, CustomAutoData(typeof(SutProviderCustomization))]
public async Task SaveAsync_KeyConnector_SingleOrgNotEnabled_Throws(SutProvider<SsoConfigService> sutProvider)
public async Task SaveAsync_KeyConnector_SingleOrgNotEnabled_Throws(SutProvider<SsoConfigService> sutProvider,
Organization organization)
{
var utcNow = DateTime.UtcNow;
var ssoConfig = new SsoConfig
{
Id = default,
Data = "{\"useKeyConnector\": true}",
Data = new SsoConfigurationData
{
KeyConnectorEnabled = true,
}.Serialize(),
Enabled = true,
OrganizationId = Guid.NewGuid(),
OrganizationId = organization.Id,
CreationDate = utcNow.AddDays(-10),
RevisionDate = utcNow.AddDays(-10),
};
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.SaveAsync(ssoConfig));
() => sutProvider.Sut.SaveAsync(ssoConfig, organization));
Assert.Contains("Key Connector requires the Single Organization policy to be enabled.", exception.Message);
@ -169,16 +181,20 @@ namespace Bit.Core.Test.Services
}
[Theory, CustomAutoData(typeof(SutProviderCustomization))]
public async Task SaveAsync_KeyConnector_SsoPolicyNotEnabled_Throws(SutProvider<SsoConfigService> sutProvider)
public async Task SaveAsync_KeyConnector_SsoPolicyNotEnabled_Throws(SutProvider<SsoConfigService> sutProvider,
Organization organization)
{
var utcNow = DateTime.UtcNow;
var ssoConfig = new SsoConfig
{
Id = default,
Data = "{\"useKeyConnector\": true}",
Data = new SsoConfigurationData
{
KeyConnectorEnabled = true,
}.Serialize(),
Enabled = true,
OrganizationId = Guid.NewGuid(),
OrganizationId = organization.Id,
CreationDate = utcNow.AddDays(-10),
RevisionDate = utcNow.AddDays(-10),
};
@ -190,7 +206,7 @@ namespace Bit.Core.Test.Services
});
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.SaveAsync(ssoConfig));
() => sutProvider.Sut.SaveAsync(ssoConfig, organization));
Assert.Contains("Key Connector requires the Single Sign-On Authentication policy to be enabled.", exception.Message);
@ -199,16 +215,20 @@ namespace Bit.Core.Test.Services
}
[Theory, CustomAutoData(typeof(SutProviderCustomization))]
public async Task SaveAsync_KeyConnector_SsoConfigNotEnabled_Throws(SutProvider<SsoConfigService> sutProvider)
public async Task SaveAsync_KeyConnector_SsoConfigNotEnabled_Throws(SutProvider<SsoConfigService> sutProvider,
Organization organization)
{
var utcNow = DateTime.UtcNow;
var ssoConfig = new SsoConfig
{
Id = default,
Data = "{\"useKeyConnector\": true}",
Data = new SsoConfigurationData
{
KeyConnectorEnabled = true,
}.Serialize(),
Enabled = false,
OrganizationId = Guid.NewGuid(),
OrganizationId = organization.Id,
CreationDate = utcNow.AddDays(-10),
RevisionDate = utcNow.AddDays(-10),
};
@ -220,12 +240,79 @@ namespace Bit.Core.Test.Services
});
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.SaveAsync(ssoConfig));
() => sutProvider.Sut.SaveAsync(ssoConfig, organization));
Assert.Contains("You must enable SSO to use Key Connector.", exception.Message);
await sutProvider.GetDependency<ISsoConfigRepository>().DidNotReceiveWithAnyArgs()
.UpsertAsync(default);
}
[Theory, CustomAutoData(typeof(SutProviderCustomization))]
public async Task SaveAsync_KeyConnector_KeyConnectorAbilityNotEnabled_Throws(SutProvider<SsoConfigService> sutProvider,
Organization organization)
{
var utcNow = DateTime.UtcNow;
organization.UseKeyConnector = false;
var ssoConfig = new SsoConfig
{
Id = default,
Data = new SsoConfigurationData
{
KeyConnectorEnabled = true,
}.Serialize(),
Enabled = true,
OrganizationId = organization.Id,
CreationDate = utcNow.AddDays(-10),
RevisionDate = utcNow.AddDays(-10),
};
sutProvider.GetDependency<IPolicyRepository>().GetByOrganizationIdTypeAsync(
Arg.Any<Guid>(), Arg.Any<Enums.PolicyType>()).Returns(new Policy
{
Enabled = true,
});
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.SaveAsync(ssoConfig, organization));
Assert.Contains("Organization cannot use Key Connector.", exception.Message);
await sutProvider.GetDependency<ISsoConfigRepository>().DidNotReceiveWithAnyArgs()
.UpsertAsync(default);
}
[Theory, CustomAutoData(typeof(SutProviderCustomization))]
public async Task SaveAsync_KeyConnector_Success(SutProvider<SsoConfigService> sutProvider,
Organization organization)
{
var utcNow = DateTime.UtcNow;
organization.UseKeyConnector = true;
var ssoConfig = new SsoConfig
{
Id = default,
Data = new SsoConfigurationData
{
KeyConnectorEnabled = true,
}.Serialize(),
Enabled = true,
OrganizationId = organization.Id,
CreationDate = utcNow.AddDays(-10),
RevisionDate = utcNow.AddDays(-10),
};
sutProvider.GetDependency<IPolicyRepository>().GetByOrganizationIdTypeAsync(
Arg.Any<Guid>(), Arg.Any<Enums.PolicyType>()).Returns(new Policy
{
Enabled = true,
});
await sutProvider.Sut.SaveAsync(ssoConfig, organization);
await sutProvider.GetDependency<ISsoConfigRepository>().ReceivedWithAnyArgs()
.UpsertAsync(default);
}
}
}