From 6d062dcbd43d5c73e73063b50ec77a85ed10f4ec Mon Sep 17 00:00:00 2001 From: Robert E Date: Sun, 8 Sep 2024 13:32:05 +1000 Subject: [PATCH] Serializing identites --- .../WindowsCertStore/PrivateKeyAccessRule.cs | 32 +++++++++++------- .../WindowsX509CertificateStore.cs | 2 +- .../Certificates/PrivateKeyAccessRule.cs | 33 ++++++++++++++++--- .../WindowsX509CertificateStore.cs | 6 ++-- .../IisWebSiteAfterPostDeployFeature.cs | 12 +++---- 5 files changed, 59 insertions(+), 26 deletions(-) diff --git a/source/Calamari.FullFrameworkTools/WindowsCertStore/PrivateKeyAccessRule.cs b/source/Calamari.FullFrameworkTools/WindowsCertStore/PrivateKeyAccessRule.cs index 8ba42d8bf..294af3269 100644 --- a/source/Calamari.FullFrameworkTools/WindowsCertStore/PrivateKeyAccessRule.cs +++ b/source/Calamari.FullFrameworkTools/WindowsCertStore/PrivateKeyAccessRule.cs @@ -11,26 +11,34 @@ public class PrivateKeyAccessRule { [JsonConstructor] public PrivateKeyAccessRule(string identity, PrivateKeyAccess access) - :this(new NTAccount(identity), access) - { - } - - public PrivateKeyAccessRule(IdentityReference identity, PrivateKeyAccess access) { Identity = identity; Access = access; } - - public IdentityReference Identity { get; } + public PrivateKeyAccess Access { get; } - - private static JsonSerializerSettings JsonSerializerSettings => new JsonSerializerSettings + public string Identity { get; } + + + public IdentityReference GetIdentityReference() { - Converters = new List + return TryParse(Identity, out var temp) ? temp! : new NTAccount(Identity); + } + + + public static bool TryParse(string value, out SecurityIdentifier? result) + { + try { - new StringEnumConverter(), + result = new SecurityIdentifier(value); + return true; } - }; + catch (ArgumentException) + { + result = null; + return false; + } + } } diff --git a/source/Calamari.FullFrameworkTools/WindowsCertStore/WindowsX509CertificateStore.cs b/source/Calamari.FullFrameworkTools/WindowsCertStore/WindowsX509CertificateStore.cs index 6ce6c384b..d9b03426b 100644 --- a/source/Calamari.FullFrameworkTools/WindowsCertStore/WindowsX509CertificateStore.cs +++ b/source/Calamari.FullFrameworkTools/WindowsCertStore/WindowsX509CertificateStore.cs @@ -108,7 +108,7 @@ public void ImportCertificateToStore(byte[] pfxBytes, string password, string us if (certificate.HasPrivateKey()) { // Because we have to store the private-key in the machine key-store, we must grant the user access to it - var keySecurity = new[] {new PrivateKeyAccessRule(account, PrivateKeyAccess.FullControl)}; + var keySecurity = new[] {new PrivateKeyAccessRule(account.Value, PrivateKeyAccess.FullControl)}; AddPrivateKeyAccessRules(keySecurity, certificate); } } diff --git a/source/Calamari.Shared/Integration/Certificates/PrivateKeyAccessRule.cs b/source/Calamari.Shared/Integration/Certificates/PrivateKeyAccessRule.cs index 677ad6336..d5ddd6b43 100644 --- a/source/Calamari.Shared/Integration/Certificates/PrivateKeyAccessRule.cs +++ b/source/Calamari.Shared/Integration/Certificates/PrivateKeyAccessRule.cs @@ -10,17 +10,42 @@ public class PrivateKeyAccessRule { [JsonConstructor] public PrivateKeyAccessRule(string identity, PrivateKeyAccess access) - :this(new NTAccount(identity), access) + { + Identity = identity; + Access = access; } - public PrivateKeyAccessRule(IdentityReference identity, PrivateKeyAccess access) + /*public PrivateKeyAccessRule(IdentityReference identity, PrivateKeyAccess access) { Identity = identity; Access = access; - } + }*/ - public IdentityReference Identity { get; } + /*public IdentityReference Identity { get; }*/ + public string Identity { get; } + + public IdentityReference GetIdentityReference() + { + return TryParse(Identity, out var temp) ? (IdentityReference)temp : new NTAccount(Identity); + } + + + public static bool TryParse(string value, out SecurityIdentifier result) + { + try + { + result = new SecurityIdentifier(value); + return true; + } + catch (ArgumentException) + { + result = null; + return false; + } + } + + public PrivateKeyAccess Access { get; } public static ICollection FromJson(string json) diff --git a/source/Calamari.Shared/Integration/Certificates/WindowsX509CertificateStore.cs b/source/Calamari.Shared/Integration/Certificates/WindowsX509CertificateStore.cs index fde07eb9a..a71e9e466 100644 --- a/source/Calamari.Shared/Integration/Certificates/WindowsX509CertificateStore.cs +++ b/source/Calamari.Shared/Integration/Certificates/WindowsX509CertificateStore.cs @@ -97,7 +97,7 @@ public void ImportCertificateToStore(byte[] pfxBytes, string password, string us if (certificate.HasPrivateKey()) { // Because we have to store the private-key in the machine key-store, we must grant the user access to it - var keySecurity = new[] {new PrivateKeyAccessRule(account, PrivateKeyAccess.FullControl)}; + var keySecurity = new[] {new PrivateKeyAccessRule(userName, PrivateKeyAccess.FullControl)}; AddPrivateKeyAccessRules(keySecurity, certificate); } } @@ -439,11 +439,11 @@ static CryptoKeyAccessRule ToCryptoKeyAccessRule(PrivateKeyAccessRule rule) switch (rule.Access) { case PrivateKeyAccess.ReadOnly: - return new CryptoKeyAccessRule(rule.Identity, CryptoKeyRights.GenericRead, AccessControlType.Allow); + return new CryptoKeyAccessRule(rule.GetIdentityReference(), CryptoKeyRights.GenericRead, AccessControlType.Allow); case PrivateKeyAccess.FullControl: // We use 'GenericAll' here rather than 'FullControl' as 'FullControl' doesn't correctly set the access for CNG keys - return new CryptoKeyAccessRule(rule.Identity, CryptoKeyRights.GenericAll, AccessControlType.Allow); + return new CryptoKeyAccessRule(rule.GetIdentityReference(), CryptoKeyRights.GenericAll, AccessControlType.Allow); default: throw new ArgumentOutOfRangeException(nameof(rule.Access)); diff --git a/source/Calamari/Deployment/Features/IisWebSiteAfterPostDeployFeature.cs b/source/Calamari/Deployment/Features/IisWebSiteAfterPostDeployFeature.cs index 11a271a93..1761893f5 100644 --- a/source/Calamari/Deployment/Features/IisWebSiteAfterPostDeployFeature.cs +++ b/source/Calamari/Deployment/Features/IisWebSiteAfterPostDeployFeature.cs @@ -66,7 +66,7 @@ static PrivateKeyAccessRule CreatePrivateKeyAccessForApplicationPoolAccount(IVar PrivateKeyAccess.FullControl); } - static IdentityReference GetIdentityForApplicationPoolIdentity(ApplicationPoolIdentityType applicationPoolIdentityType, + static string GetIdentityForApplicationPoolIdentity(ApplicationPoolIdentityType applicationPoolIdentityType, IVariables variables) { //TODO: Once this only runs netcore we can remove this check (or potentially externalize the whole check) @@ -79,19 +79,19 @@ static IdentityReference GetIdentityForApplicationPoolIdentity(ApplicationPoolId switch (applicationPoolIdentityType) { case ApplicationPoolIdentityType.ApplicationPoolIdentity: - return new NTAccount("IIS AppPool\\" + variables.Get(SpecialVariables.Action.IisWebSite.ApplicationPoolName)); + return new NTAccount("IIS AppPool\\" + variables.Get(SpecialVariables.Action.IisWebSite.ApplicationPoolName)).Value; case ApplicationPoolIdentityType.LocalService: - return new SecurityIdentifier(WellKnownSidType.LocalServiceSid, null); + return new SecurityIdentifier(WellKnownSidType.LocalServiceSid, null).Value; case ApplicationPoolIdentityType.LocalSystem: - return new SecurityIdentifier(WellKnownSidType.LocalServiceSid, null); + return new SecurityIdentifier(WellKnownSidType.LocalServiceSid, null).Value; case ApplicationPoolIdentityType.NetworkService: - return new SecurityIdentifier(WellKnownSidType.NetworkServiceSid, null); + return new SecurityIdentifier(WellKnownSidType.NetworkServiceSid, null).Value; case ApplicationPoolIdentityType.SpecificUser: - return new NTAccount(StripLocalAccountIdentifierFromUsername(variables.Get(SpecialVariables.Action.IisWebSite.ApplicationPoolUserName))); + return new NTAccount(StripLocalAccountIdentifierFromUsername(variables.Get(SpecialVariables.Action.IisWebSite.ApplicationPoolUserName))).Value; default: throw new ArgumentOutOfRangeException(nameof(applicationPoolIdentityType), applicationPoolIdentityType, null);