Skip to content

Commit 67534e2

Browse files
authored
[PM-29556] Fix: changing organization plan nulls out public and private keys (#6738)
Main fix: only assign new key value where old keys are not set and new keys have been provided. Refactors: - use consistent DTO model for keypairs - delete duplicate property assignment for new orgs
1 parent 96622d7 commit 67534e2

File tree

18 files changed

+220
-133
lines changed

18 files changed

+220
-133
lines changed

src/Api/AdminConsole/Controllers/ProviderClientsController.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ public async Task<IResult> CreateAsync(
5757
Owner = user,
5858
BillingEmail = provider.BillingEmail,
5959
OwnerKey = requestBody.Key,
60-
PublicKey = requestBody.KeyPair.PublicKey,
61-
PrivateKey = requestBody.KeyPair.EncryptedPrivateKey,
60+
Keys = requestBody.KeyPair.ToPublicKeyEncryptionKeyPairData(),
6261
CollectionName = requestBody.CollectionName,
6362
IsFromProvider = true
6463
};

src/Api/AdminConsole/Models/Request/Organizations/OrganizationCreateRequestModel.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,10 @@ public virtual OrganizationSignup ToOrganizationSignup(User user)
113113
BillingAddressCountry = BillingAddressCountry,
114114
},
115115
InitiationPath = InitiationPath,
116-
SkipTrial = SkipTrial
116+
SkipTrial = SkipTrial,
117+
Keys = Keys?.ToPublicKeyEncryptionKeyPairData()
117118
};
118119

119-
Keys?.ToOrganizationSignup(orgSignup);
120-
121120
return orgSignup;
122121
}
123122

src/Api/AdminConsole/Models/Request/Organizations/OrganizationKeysRequestModel.cs

Lines changed: 5 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
#nullable disable
33

44
using System.ComponentModel.DataAnnotations;
5-
using Bit.Core.AdminConsole.Entities;
6-
using Bit.Core.Models.Business;
5+
using Bit.Core.KeyManagement.Models.Data;
76

87
namespace Bit.Api.AdminConsole.Models.Request.Organizations;
98

@@ -14,48 +13,10 @@ public class OrganizationKeysRequestModel
1413
[Required]
1514
public string EncryptedPrivateKey { get; set; }
1615

17-
public OrganizationSignup ToOrganizationSignup(OrganizationSignup existingSignup)
16+
public PublicKeyEncryptionKeyPairData ToPublicKeyEncryptionKeyPairData()
1817
{
19-
if (string.IsNullOrWhiteSpace(existingSignup.PublicKey))
20-
{
21-
existingSignup.PublicKey = PublicKey;
22-
}
23-
24-
if (string.IsNullOrWhiteSpace(existingSignup.PrivateKey))
25-
{
26-
existingSignup.PrivateKey = EncryptedPrivateKey;
27-
}
28-
29-
return existingSignup;
30-
}
31-
32-
public OrganizationUpgrade ToOrganizationUpgrade(OrganizationUpgrade existingUpgrade)
33-
{
34-
if (string.IsNullOrWhiteSpace(existingUpgrade.PublicKey))
35-
{
36-
existingUpgrade.PublicKey = PublicKey;
37-
}
38-
39-
if (string.IsNullOrWhiteSpace(existingUpgrade.PrivateKey))
40-
{
41-
existingUpgrade.PrivateKey = EncryptedPrivateKey;
42-
}
43-
44-
return existingUpgrade;
45-
}
46-
47-
public Organization ToOrganization(Organization existingOrg)
48-
{
49-
if (string.IsNullOrWhiteSpace(existingOrg.PublicKey))
50-
{
51-
existingOrg.PublicKey = PublicKey;
52-
}
53-
54-
if (string.IsNullOrWhiteSpace(existingOrg.PrivateKey))
55-
{
56-
existingOrg.PrivateKey = EncryptedPrivateKey;
57-
}
58-
59-
return existingOrg;
18+
return new PublicKeyEncryptionKeyPairData(
19+
wrappedPrivateKey: EncryptedPrivateKey,
20+
publicKey: PublicKey);
6021
}
6122
}

src/Api/AdminConsole/Models/Request/Organizations/OrganizationNoPaymentCreateRequest.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,9 @@ public virtual OrganizationSignup ToOrganizationSignup(User user)
110110
BillingAddressCountry = BillingAddressCountry,
111111
},
112112
InitiationPath = InitiationPath,
113+
Keys = Keys?.ToPublicKeyEncryptionKeyPairData()
113114
};
114115

115-
Keys?.ToOrganizationSignup(orgSignup);
116-
117116
return orgSignup;
118117
}
119118
}

src/Api/AdminConsole/Models/Request/Organizations/OrganizationUpdateRequestModel.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ public class OrganizationUpdateRequestModel
2222
OrganizationId = organizationId,
2323
Name = Name,
2424
BillingEmail = BillingEmail,
25-
PublicKey = Keys?.PublicKey,
26-
EncryptedPrivateKey = Keys?.EncryptedPrivateKey
25+
Keys = Keys?.ToPublicKeyEncryptionKeyPairData()
2726
};
2827
}

src/Api/AdminConsole/Models/Request/Organizations/OrganizationUpgradeRequestModel.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,10 @@ public OrganizationUpgrade ToOrganizationUpgrade()
4343
{
4444
BillingAddressCountry = BillingAddressCountry,
4545
BillingAddressPostalCode = BillingAddressPostalCode
46-
}
46+
},
47+
Keys = Keys?.ToPublicKeyEncryptionKeyPairData()
4748
};
4849

49-
Keys?.ToOrganizationUpgrade(orgUpgrade);
50-
5150
return orgUpgrade;
5251
}
5352
}

src/Api/Billing/Models/Requests/KeyPairRequestBody.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#nullable disable
33

44
using System.ComponentModel.DataAnnotations;
5+
using Bit.Core.KeyManagement.Models.Data;
56

67
namespace Bit.Api.Billing.Models.Requests;
78

@@ -12,4 +13,11 @@ public class KeyPairRequestBody
1213
public string PublicKey { get; set; }
1314
[Required(ErrorMessage = "'encryptedPrivateKey' must be provided")]
1415
public string EncryptedPrivateKey { get; set; }
16+
17+
public PublicKeyEncryptionKeyPairData ToPublicKeyEncryptionKeyPairData()
18+
{
19+
return new PublicKeyEncryptionKeyPairData(
20+
wrappedPrivateKey: EncryptedPrivateKey,
21+
publicKey: PublicKey);
22+
}
1523
}

src/Core/AdminConsole/OrganizationFeatures/Organizations/CloudOrganizationSignUpCommand.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,8 @@ public async Task<SignUpOrganizationResponse> SignUpOrganizationAsync(Organizati
9999
ReferenceData = signup.Owner.ReferenceData,
100100
Enabled = true,
101101
LicenseKey = CoreHelpers.SecureRandomString(20),
102-
PublicKey = signup.PublicKey,
103-
PrivateKey = signup.PrivateKey,
102+
PublicKey = signup.Keys?.PublicKey,
103+
PrivateKey = signup.Keys?.WrappedPrivateKey,
104104
CreationDate = DateTime.UtcNow,
105105
RevisionDate = DateTime.UtcNow,
106106
Status = OrganizationStatusType.Created,
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using Bit.Core.AdminConsole.Entities;
2+
using Bit.Core.KeyManagement.Models.Data;
3+
4+
namespace Bit.Core.AdminConsole.OrganizationFeatures.Organizations;
5+
6+
public static class OrganizationExtensions
7+
{
8+
/// <summary>
9+
/// Updates the organization public and private keys if provided and not already set.
10+
/// This is legacy code for old organizations that were not created with a public/private keypair.
11+
/// It is a soft migration that will silently migrate organizations when they perform certain actions,
12+
/// e.g. change their details or upgrade their plan.
13+
/// </summary>
14+
public static void BackfillPublicPrivateKeys(this Organization organization, PublicKeyEncryptionKeyPairData? keyPair)
15+
{
16+
// Only backfill if both new keys are provided and both old keys are missing.
17+
if (string.IsNullOrWhiteSpace(keyPair?.PublicKey) ||
18+
string.IsNullOrWhiteSpace(keyPair.WrappedPrivateKey) ||
19+
!string.IsNullOrWhiteSpace(organization.PublicKey) ||
20+
!string.IsNullOrWhiteSpace(organization.PrivateKey))
21+
{
22+
return;
23+
}
24+
25+
organization.PublicKey = keyPair.PublicKey;
26+
organization.PrivateKey = keyPair.WrappedPrivateKey;
27+
}
28+
}

src/Core/AdminConsole/OrganizationFeatures/Organizations/ProviderClientOrganizationSignUpCommand.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ public async Task<ProviderClientOrganizationSignUpResponse> SignUpClientOrganiza
9393
ReferenceData = signup.Owner.ReferenceData,
9494
Enabled = true,
9595
LicenseKey = CoreHelpers.SecureRandomString(20),
96-
PublicKey = signup.PublicKey,
97-
PrivateKey = signup.PrivateKey,
96+
PublicKey = signup.Keys?.PublicKey,
97+
PrivateKey = signup.Keys?.WrappedPrivateKey,
9898
CreationDate = DateTime.UtcNow,
9999
RevisionDate = DateTime.UtcNow,
100100
Status = OrganizationStatusType.Created,

0 commit comments

Comments
 (0)