Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AC-1721] Include limit collection creation/deletion in license file #3388

Merged
merged 54 commits into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
4f08039
[AC-1117] Add manage permission (#3126)
differsthecat Aug 11, 2023
cf78f12
[AC-1374] Limit collection creation/deletion to Owner/Admin (#3145)
vincentsalucci Aug 14, 2023
78bdd51
Merge branch 'master' into feature/flexible-collections
vincentsalucci Aug 14, 2023
2f45726
Merge branch 'master' into feature/flexible-collections
vincentsalucci Aug 24, 2023
d5da5bb
fix: merge conflict resolution
vincentsalucci Aug 24, 2023
e87c20c
Merge branch 'master' into feature/flexible-collections
vincentsalucci Aug 30, 2023
5dc3ca8
[AC-1174] CollectionUser and CollectionGroup authorization handlers (…
shane-melton Aug 30, 2023
e8053e2
Fix improper merge conflict resolution
shane-melton Aug 30, 2023
3dfd38c
Merge branch 'master' into feature/flexible-collections
vincentsalucci Sep 1, 2023
3c9c8ac
Merge remote-tracking branch 'origin/master' into feature/flexible-co…
eliykat Sep 4, 2023
4ac1b10
Merge branch 'master' into feature/flexible-collections
vincentsalucci Sep 12, 2023
064a28c
fix: add permission check for collection management api, refs AC-1647…
vincentsalucci Sep 12, 2023
acd3997
Merge branch 'master' into feature/flexible-collections
vincentsalucci Sep 13, 2023
34dfdc5
[AC-1125] Enforce org setting for creating/deleting collections (#3241)
vincentsalucci Sep 18, 2023
9f5fec6
Merge remote-tracking branch 'origin/master' into feature/flexible-co…
eliykat Sep 19, 2023
ffa09d1
Merge branch 'master' into feature/flexible-collections
vincentsalucci Sep 19, 2023
f2acf1c
refactor: remove organizationId from CollectionBulkDeleteRequestModel…
vincentsalucci Sep 20, 2023
2c7d02d
Merge branch 'master' into feature/flexible-collections
eliykat Sep 26, 2023
5d431ad
[AC-1174] Bulk Collection Management (#3229)
shane-melton Sep 26, 2023
a3f554a
[AC-1646] Rename LimitCollectionCdOwnerAdmin column (#3300)
eliykat Sep 26, 2023
30b91cd
Merge branch 'master' into feature/flexible-collections
eliykat Sep 27, 2023
dd10614
Merge branch 'master' into feature/flexible-collections
eliykat Sep 28, 2023
fbb7aa1
[AC-1666] Removed EditAnyCollection from Create/Delete permission che…
vincentsalucci Sep 29, 2023
279d0cc
[AC-1669] Bug - Remove obsolete assignUserId from CollectionService.S…
vincentsalucci Oct 5, 2023
0abd7c3
Merge branch 'master' into feature/flexible-collections
vincentsalucci Oct 5, 2023
fed3252
Merge remote-tracking branch 'origin/master' into feature/flexible-co…
eliykat Oct 9, 2023
6bc38ac
Merge branch 'master' into feature/flexible-collections
eliykat Oct 13, 2023
3b049a6
[AC-1713] [Flexible collections] Add feature flags to server (#3334)
eliykat Oct 17, 2023
ae18e76
Merge remote-tracking branch 'origin/master' into feature/flexible-co…
eliykat Oct 18, 2023
52e723c
Add joint codeownership for auth handlers (#3346)
eliykat Oct 22, 2023
cd376be
Merge remote-tracking branch 'origin/master' into feature/flexible-co…
eliykat Oct 22, 2023
ad27f3d
[AC-1717] Update default values for LimitCollectionCreationDeletion (…
eliykat Oct 24, 2023
d91eb23
Merge branch 'master' into feature/flexible-collections
eliykat Oct 24, 2023
9d5c5bc
Fix: add missing namespace after merging in master
eliykat Oct 24, 2023
596e0df
Fix: add missing namespace after merging in master
eliykat Oct 24, 2023
3a5c35b
[AC-1683] Fix DB migrations for new Manage permission (#3307)
shane-melton Oct 24, 2023
0fe97d7
[AC-1648] [Flexible Collections] Bump migration scripts before featur…
eliykat Oct 24, 2023
c11ba10
Merge branch 'master' into feature/flexible-collections
shane-melton Oct 24, 2023
8c78fc2
Merge remote-tracking branch 'origin/master' into feature/flexible-co…
eliykat Oct 27, 2023
8b95d1b
feat: update OrganizationLicense (add property, update GetDataBytes, …
vincentsalucci Oct 27, 2023
e1004c6
feat: update Organization.UpdateFromLicense and SignUpAsync to use va…
vincentsalucci Oct 27, 2023
87a3709
Merge branch 'master' into ac/ac-1721/limit-collection-license-ffc
vincentsalucci Nov 6, 2023
d94d6f9
feat: Add cloud-only access for PutCollectionManagement endpoint, ref…
vincentsalucci Nov 8, 2023
7d668f4
Merge branch 'master' into ac/ac-1721/limit-collection-license-ffc
vincentsalucci Nov 8, 2023
c5fc542
Merge branch 'master' into ac/ac-1721/limit-collection-license-ffc
vincentsalucci Nov 20, 2023
ee83803
Merge branch 'master' into ac/ac-1721/limit-collection-license-ffc
vincentsalucci Nov 29, 2023
3a0e236
feat: add feature flag to organization entity for updating from licen…
vincentsalucci Nov 29, 2023
7c3db2e
Merge branch 'master' into ac/ac-1721/limit-collection-license-ffc
vincentsalucci Nov 29, 2023
7a309da
feat: updated license fixture with new version (14), refs AC-1721
vincentsalucci Nov 29, 2023
65dc89b
Merge branch 'master' into ac/ac-1721/limit-collection-license-ffc
vincentsalucci Dec 1, 2023
845ad29
feat: disable validity checks for version 14, refs AC-1721
vincentsalucci Dec 1, 2023
7599a71
fix: dotnet format, refs AC-1721
vincentsalucci Dec 1, 2023
4d69a17
Merge branch 'master' into ac/ac-1721/limit-collection-license-ffc
vincentsalucci Dec 6, 2023
fced6cb
feat: default org license LimitCollectionCreationDeletion to true, re…
vincentsalucci Dec 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,7 @@ public async Task<OrganizationSsoResponseModel> PostSso(Guid id, [FromBody] Orga

[HttpPut("{id}/collection-management")]
[RequireFeature(FeatureFlagKeys.FlexibleCollections)]
[SelfHosted(NotSelfHostedOnly = true)]
public async Task<OrganizationResponseModel> PutCollectionManagement(Guid id, [FromBody] OrganizationCollectionManagementUpdateRequestModel model)
{
var organization = await _organizationRepository.GetByIdAsync(id);
Expand Down
3 changes: 2 additions & 1 deletion src/Core/AdminConsole/Entities/Organization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ public TwoFactorProvider GetTwoFactorProvider(TwoFactorProviderType provider)
return providers[provider];
}

public void UpdateFromLicense(OrganizationLicense license)
public void UpdateFromLicense(OrganizationLicense license, bool flexibleCollectionsIsEnabled)
{
Name = license.Name;
BusinessName = license.BusinessName;
Expand Down Expand Up @@ -267,5 +267,6 @@ public void UpdateFromLicense(OrganizationLicense license)
UseSecretsManager = license.UseSecretsManager;
SmSeats = license.SmSeats;
SmServiceAccounts = license.SmServiceAccounts;
LimitCollectionCreationDeletion = !flexibleCollectionsIsEnabled || license.LimitCollectionCreationDeletion;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,9 @@ public async Task<Tuple<Organization, OrganizationUser>> SignUpAsync(

await ValidateSignUpPoliciesAsync(owner.Id);

var flexibleCollectionsIsEnabled =
_featureService.IsEnabled(FeatureFlagKeys.FlexibleCollections, _currentContext);

var organization = new Organization
{
Name = license.Name,
Expand Down Expand Up @@ -594,7 +597,8 @@ public async Task<Tuple<Organization, OrganizationUser>> SignUpAsync(
UsePasswordManager = license.UsePasswordManager,
UseSecretsManager = license.UseSecretsManager,
SmSeats = license.SmSeats,
SmServiceAccounts = license.SmServiceAccounts
SmServiceAccounts = license.SmServiceAccounts,
LimitCollectionCreationDeletion = !flexibleCollectionsIsEnabled || license.LimitCollectionCreationDeletion
};

var result = await SignUpAsync(organization, owner.Id, ownerKey, collectionName, false);
Expand Down
16 changes: 13 additions & 3 deletions src/Core/Models/Business/OrganizationLicense.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public OrganizationLicense(Organization org, SubscriptionInfo subscriptionInfo,
UseSecretsManager = org.UseSecretsManager;
SmSeats = org.SmSeats;
SmServiceAccounts = org.SmServiceAccounts;
LimitCollectionCreationDeletion = org.LimitCollectionCreationDeletion;

if (subscriptionInfo?.Subscription == null)
{
Expand Down Expand Up @@ -135,6 +136,7 @@ public OrganizationLicense(Organization org, SubscriptionInfo subscriptionInfo,
public bool UseSecretsManager { get; set; }
public int? SmSeats { get; set; }
public int? SmServiceAccounts { get; set; }
public bool LimitCollectionCreationDeletion { get; set; } = true;
public bool Trial { get; set; }
public LicenseType? LicenseType { get; set; }
public string Hash { get; set; }
Expand All @@ -146,11 +148,10 @@ public OrganizationLicense(Organization org, SubscriptionInfo subscriptionInfo,
/// </summary>
/// <remarks>Intentionally set one version behind to allow self hosted users some time to update before
/// getting out of date license errors</remarks>
public const int CurrentLicenseFileVersion = 12;

public const int CurrentLicenseFileVersion = 13;
private bool ValidLicenseVersion
{
get => Version is >= 1 and <= 13;
get => Version is >= 1 and <= 14;
}

public byte[] GetDataBytes(bool forHash = false)
Expand Down Expand Up @@ -191,6 +192,8 @@ public byte[] GetDataBytes(bool forHash = false)
(Version >= 13 || !p.Name.Equals(nameof(UsePasswordManager))) &&
(Version >= 13 || !p.Name.Equals(nameof(SmSeats))) &&
(Version >= 13 || !p.Name.Equals(nameof(SmServiceAccounts))) &&
// LimitCollectionCreationDeletion was added in Version 14
(Version >= 14 || !p.Name.Equals(nameof(LimitCollectionCreationDeletion))) &&
Comment on lines +195 to +196
Copy link
Member

@eliykat eliykat Nov 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One problem with the current approach is that if the feature flag is off, the license file won't match the org object (because the create/update methods will choose to ignore the value in the license file). So there's a risk that validation will fail. Given that it's not a billing-critical property, maybe we just exclude it from validation for now. We should exclude this from validation until FC is enabled everywhere.

Alternatively, maybe we don't flag any of this logic and we just let the value be updated from the license file. After all, the actual logic will still be flagged on self-hosted. My concern there was that it'll be a latent change that will suddenly take effect after updating the self-hosted instance, and that could be unexpected.

There's a bit to this so let's discuss in the next FC sync.

Copy link
Member

@eliykat eliykat Nov 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vincentsalucci I think the conclusion from our sync was that my feedback here is still accurate. Amended the comment above.

Once #3474 is merged, you'll need to update the tests with this version of the license file. Happy to help with that if required.

(
!forHash ||
(
Expand Down Expand Up @@ -338,6 +341,13 @@ public bool VerifyData(Organization organization, IGlobalSettings globalSettings
organization.SmServiceAccounts == SmServiceAccounts;
}

// Restore validity check when Flexible Collections are enabled for cloud and self-host
// https://bitwarden.atlassian.net/browse/AC-1875
// if (valid && Version >= 14)
// {
// valid = organization.LimitCollectionCreationDeletion == LimitCollectionCreationDeletion;
// }

return valid;
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using System.Text.Json;
using Bit.Core.AdminConsole.Entities;
using Bit.Core.Context;
using Bit.Core.Exceptions;
using Bit.Core.Models.Business;
using Bit.Core.Models.Data.Organizations;
Expand All @@ -17,15 +18,21 @@ public class UpdateOrganizationLicenseCommand : IUpdateOrganizationLicenseComman
private readonly ILicensingService _licensingService;
private readonly IGlobalSettings _globalSettings;
private readonly IOrganizationService _organizationService;
private readonly IFeatureService _featureService;
private readonly ICurrentContext _currentContext;

public UpdateOrganizationLicenseCommand(
ILicensingService licensingService,
IGlobalSettings globalSettings,
IOrganizationService organizationService)
IOrganizationService organizationService,
IFeatureService featureService,
ICurrentContext currentContext)
{
_licensingService = licensingService;
_globalSettings = globalSettings;
_organizationService = organizationService;
_featureService = featureService;
_currentContext = currentContext;
}

public async Task UpdateLicenseAsync(SelfHostedOrganizationDetails selfHostedOrganization,
Expand Down Expand Up @@ -58,8 +65,9 @@ private async Task WriteLicenseFileAsync(Organization organization, Organization

private async Task UpdateOrganizationAsync(SelfHostedOrganizationDetails selfHostedOrganizationDetails, OrganizationLicense license)
{
var flexibleCollectionsIsEnabled = _featureService.IsEnabled(FeatureFlagKeys.FlexibleCollections, _currentContext);
var organization = selfHostedOrganizationDetails.ToOrganization();
organization.UpdateFromLicense(license);
organization.UpdateFromLicense(license, flexibleCollectionsIsEnabled);

await _organizationService.ReplaceAndUpdateCacheAsync(organization);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ public static class OrganizationLicenseFileFixtures
private const string Version13 =
"{\n 'LicenseKey': 'myLicenseKey',\n 'InstallationId': '78900000-0000-0000-0000-000000000123',\n 'Id': '12300000-0000-0000-0000-000000000456',\n 'Name': 'myOrg',\n 'BillingEmail': 'myBillingEmail',\n 'BusinessName': 'myBusinessName',\n 'Enabled': true,\n 'Plan': 'myPlan',\n 'PlanType': 11,\n 'Seats': 10,\n 'MaxCollections': 2,\n 'UsePolicies': true,\n 'UseSso': true,\n 'UseKeyConnector': true,\n 'UseScim': true,\n 'UseGroups': true,\n 'UseEvents': true,\n 'UseDirectory': true,\n 'UseTotp': true,\n 'Use2fa': true,\n 'UseApi': true,\n 'UseResetPassword': true,\n 'MaxStorageGb': 100,\n 'SelfHost': true,\n 'UsersGetPremium': true,\n 'UseCustomPermissions': true,\n 'Version': 12,\n 'Issued': '2023-11-23T03:25:24.265409Z',\n 'Refresh': '2023-11-30T03:25:24.265409Z',\n 'Expires': '2023-11-30T03:25:24.265409Z',\n 'ExpirationWithoutGracePeriod': null,\n 'UsePasswordManager': true,\n 'UseSecretsManager': true,\n 'SmSeats': 5,\n 'SmServiceAccounts': 8,\n 'Trial': true,\n 'LicenseType': 1,\n 'Hash': 'hZ4WcSX/7ooRZ6asDRMJ/t0K5hZkQdvkgEyy6wY\\u002BwQk=',\n 'Signature': ''\n}";

private static readonly Dictionary<int, string> LicenseVersions = new() { { 12, Version12 }, { 13, Version13 } };
private const string Version14 =
"{\n 'LicenseKey': 'myLicenseKey',\n 'InstallationId': '78900000-0000-0000-0000-000000000123',\n 'Id': '12300000-0000-0000-0000-000000000456',\n 'Name': 'myOrg',\n 'BillingEmail': 'myBillingEmail',\n 'BusinessName': 'myBusinessName',\n 'Enabled': true,\n 'Plan': 'myPlan',\n 'PlanType': 11,\n 'Seats': 10,\n 'MaxCollections': 2,\n 'UsePolicies': true,\n 'UseSso': true,\n 'UseKeyConnector': true,\n 'UseScim': true,\n 'UseGroups': true,\n 'UseEvents': true,\n 'UseDirectory': true,\n 'UseTotp': true,\n 'Use2fa': true,\n 'UseApi': true,\n 'UseResetPassword': true,\n 'MaxStorageGb': 100,\n 'SelfHost': true,\n 'UsersGetPremium': true,\n 'UseCustomPermissions': true,\n 'Version': 13,\n 'Issued': '2023-11-29T22:42:33.970597Z',\n 'Refresh': '2023-12-06T22:42:33.970597Z',\n 'Expires': '2023-12-06T22:42:33.970597Z',\n 'ExpirationWithoutGracePeriod': null,\n 'UsePasswordManager': true,\n 'UseSecretsManager': true,\n 'SmSeats': 5,\n 'SmServiceAccounts': 8,\n 'LimitCollectionCreationDeletion': true,\n 'Trial': true,\n 'LicenseType': 1,\n 'Hash': '4G2u\\u002BWKO9EOiVnDVNr7uPxxRkv7TtaOmDl7kAYH05Fw=',\n 'Signature': ''\n}";

private static readonly Dictionary<int, string> LicenseVersions = new() { { 12, Version12 }, { 13, Version13 }, { 14, Version14 } };

public static OrganizationLicense GetVersion(int licenseVersion)
{
Expand Down
Loading