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

Release 2.7 #60

Merged
merged 13 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
v2.7.0
- Modified RFJKS store type support java keystores of both PKCS12 and JKS
- Added support for OpenSSH private keys for SSH authentication
- Bug fix for orchestrators installed on Windows 2016
- Bug Fix: Supplied Linux user needing password reset could cause orchestrator locking.
- Bug Fix: Not supplying group for Linux File Owner on Store Creation caused the supplied owner to erroneously be used as the group for the newly create certificate store file.
- Updgraded Nuget packages for BouncyCastle and Renci.SSH.Net

v2.6.0
- Added ability for Linux installed universal orchestrator to manage stores as an "agent" (stores reside on same server as universal orchestrator) without the need to have SSH enabled.
- Added ability for Linux installed universal orchestrator to manage certificate stores on Windows servers by using SSH to communicate between the Linux UO server and the Windows machines hosting the certificate stores.
Expand Down
23 changes: 13 additions & 10 deletions README.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions RemoteFile/ApplicationSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public enum FileTransferProtocolEnum
public static string DefaultLinuxPermissionsOnStoreCreation { get { return configuration.ContainsKey("DefaultLinuxPermissionsOnStoreCreation") ? configuration["DefaultLinuxPermissionsOnStoreCreation"] : DEFAULT_LINUX_PERMISSION_SETTING; } }
public static string DefaultOwnerOnStoreCreation { get { return configuration.ContainsKey("DefaultOwnerOnStoreCreation") ? configuration["DefaultOwnerOnStoreCreation"] : DEFAULT_OWNER_SETTING; } }
public static string DefaultSudoImpersonatedUser { get { return configuration.ContainsKey("DefaultSudoImpersonatedUser") ? configuration["DefaultSudoImpersonatedUser"] : DEFAULT_SUDO_IMPERSONATION_SETTING; } }
public static bool CreateCSROnDevice { get { return configuration.ContainsKey("CreateCSROnDevice") ? configuration["CreateCSROnDevice"]?.ToUpper() == "Y" : false; } }
public static string TempFilePathForODKG { get { return configuration.ContainsKey("TempFilePathForODKG") ? configuration["TempFilePathForODKG"] : string.Empty; } }
public static FileTransferProtocolEnum FileTransferProtocol
{
get
Expand Down
2 changes: 1 addition & 1 deletion RemoteFile/Discovery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace Keyfactor.Extensions.Orchestrator.RemoteFile
public class Discovery: IDiscoveryJobExtension
{
public IPAMSecretResolver _resolver;
public string ExtensionName => "";
public string ExtensionName => "Keyfactor.Extensions.Orchestrator.RemoteFile.Discovery";

public Discovery(IPAMSecretResolver resolver)
{
Expand Down
Binary file removed RemoteFile/External References/Renci.SshNet.dll
Binary file not shown.
Binary file not shown.
24 changes: 24 additions & 0 deletions RemoteFile/ImplementedStoreTypes/DER/Reenrollment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2021 Keyfactor
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
// and limitations under the License.

using Keyfactor.Orchestrators.Extensions.Interfaces;

namespace Keyfactor.Extensions.Orchestrator.RemoteFile.DER
{
public class Reenrollment : ReenrollmentBase
{
internal override ICertificateStoreSerializer GetCertificateStoreSerializer(string storeProperties)
{
return new DERCertificateStoreSerializer(storeProperties);
}

public Reenrollment(IPAMSecretResolver resolver)
{
_resolver = resolver;
}
}
}
120 changes: 75 additions & 45 deletions RemoteFile/ImplementedStoreTypes/JKS/JKSCertificateStoreSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Collections.Generic;
using Keyfactor.Extensions.Orchestrator.RemoteFile.RemoteHandlers;
using Keyfactor.Extensions.Orchestrator.RemoteFile.Models;
using Keyfactor.Extensions.Orchestrator.RemoteFile.PKCS12;

using Keyfactor.Logging;

Expand All @@ -30,6 +31,8 @@ public JKSCertificateStoreSerializer(string storeProperties)
logger = LogHandler.GetClassLogger(this.GetType());
}

private bool IsTypeJKS { get; set; }

public Pkcs12Store DeserializeRemoteCertificateStore(byte[] storeContents, string storePath, string storePassword, IRemoteHandler remoteHandler, bool isInventory)
{
logger.MethodEntry(LogLevel.Debug);
Expand All @@ -38,42 +41,58 @@ public Pkcs12Store DeserializeRemoteCertificateStore(byte[] storeContents, strin
Pkcs12Store pkcs12Store = storeBuilder.Build();
Pkcs12Store pkcs12StoreNew = storeBuilder.Build();

JksStore jksStore = new JksStore();

using (MemoryStream ms = new MemoryStream(storeContents))
{
jksStore.Load(ms, string.IsNullOrEmpty(storePassword) ? new char[0] : storePassword.ToCharArray());
IsTypeJKS = new JksStore().Probe(ms);
}

foreach (string alias in jksStore.Aliases)
if (IsTypeJKS)
{
if (jksStore.IsKeyEntry(alias))
logger.LogDebug("Store is of type JKS");
JksStore jksStore = new JksStore();

using (MemoryStream ms = new MemoryStream(storeContents))
{
AsymmetricKeyParameter keyParam = jksStore.GetKey(alias, string.IsNullOrEmpty(storePassword) ? new char[0] : storePassword.ToCharArray());
AsymmetricKeyEntry keyEntry = new AsymmetricKeyEntry(keyParam);
ms.Position = 0;
jksStore.Load(ms, string.IsNullOrEmpty(storePassword) ? new char[0] : storePassword.ToCharArray());
}

X509Certificate[] certificateChain = jksStore.GetCertificateChain(alias);
List<X509CertificateEntry> certificateChainEntries = new List<X509CertificateEntry>();
foreach (X509Certificate certificate in certificateChain)
foreach (string alias in jksStore.Aliases)
{
if (jksStore.IsKeyEntry(alias))
{
certificateChainEntries.Add(new X509CertificateEntry(certificate));
}
AsymmetricKeyParameter keyParam = jksStore.GetKey(alias, string.IsNullOrEmpty(storePassword) ? new char[0] : storePassword.ToCharArray());
AsymmetricKeyEntry keyEntry = new AsymmetricKeyEntry(keyParam);

pkcs12Store.SetKeyEntry(alias, keyEntry, certificateChainEntries.ToArray());
}
else
{
pkcs12Store.SetCertificateEntry(alias, new X509CertificateEntry(jksStore.GetCertificate(alias)));
X509Certificate[] certificateChain = jksStore.GetCertificateChain(alias);
List<X509CertificateEntry> certificateChainEntries = new List<X509CertificateEntry>();
foreach (X509Certificate certificate in certificateChain)
{
certificateChainEntries.Add(new X509CertificateEntry(certificate));
}

pkcs12Store.SetKeyEntry(alias, keyEntry, certificateChainEntries.ToArray());
}
else
{
pkcs12Store.SetCertificateEntry(alias, new X509CertificateEntry(jksStore.GetCertificate(alias)));
}
}
}

// Second Pkcs12Store necessary because of an obscure BC bug where creating a Pkcs12Store without .Load (code above using "Set" methods only) does not set all internal hashtables necessary to avoid an error later
// when processing store.
MemoryStream ms2 = new MemoryStream();
pkcs12Store.Save(ms2, string.IsNullOrEmpty(storePassword) ? new char[0] : storePassword.ToCharArray(), new Org.BouncyCastle.Security.SecureRandom());
ms2.Position = 0;
// Second Pkcs12Store necessary because of an obscure BC bug where creating a Pkcs12Store without .Load (code above using "Set" methods only) does not set all internal hashtables necessary to avoid an error later
// when processing store.
MemoryStream ms2 = new MemoryStream();
pkcs12Store.Save(ms2, string.IsNullOrEmpty(storePassword) ? new char[0] : storePassword.ToCharArray(), new Org.BouncyCastle.Security.SecureRandom());
ms2.Position = 0;

pkcs12StoreNew.Load(ms2, string.IsNullOrEmpty(storePassword) ? new char[0] : storePassword.ToCharArray());
pkcs12StoreNew.Load(ms2, string.IsNullOrEmpty(storePassword) ? new char[0] : storePassword.ToCharArray());
}
else
{
logger.LogDebug("Store is of type PKCS12");
PKCS12CertificateStoreSerializer pkcs12Serializer = new PKCS12CertificateStoreSerializer(string.Empty);
pkcs12StoreNew = pkcs12Serializer.DeserializeRemoteCertificateStore(storeContents, storePath, storePassword, remoteHandler, isInventory);
}

logger.MethodExit(LogLevel.Debug);
return pkcs12StoreNew;
Expand All @@ -83,39 +102,50 @@ public List<SerializedStoreInfo> SerializeRemoteCertificateStore(Pkcs12Store cer
{
logger.MethodEntry(LogLevel.Debug);

JksStore jksStore = new JksStore();
List<SerializedStoreInfo> storeInfo = new List<SerializedStoreInfo>();

foreach (string alias in certificateStore.Aliases)
if (IsTypeJKS)
{
if (certificateStore.IsKeyEntry(alias))
JksStore jksStore = new JksStore();

foreach (string alias in certificateStore.Aliases)
{
AsymmetricKeyEntry keyEntry = certificateStore.GetKey(alias);
X509CertificateEntry[] certificateChain = certificateStore.GetCertificateChain(alias);
if (certificateStore.IsKeyEntry(alias))
{
AsymmetricKeyEntry keyEntry = certificateStore.GetKey(alias);
X509CertificateEntry[] certificateChain = certificateStore.GetCertificateChain(alias);

List<X509Certificate> certificates = new List<X509Certificate>();
foreach (X509CertificateEntry certificateEntry in certificateChain)
List<X509Certificate> certificates = new List<X509Certificate>();
foreach (X509CertificateEntry certificateEntry in certificateChain)
{
certificates.Add(certificateEntry.Certificate);
}

jksStore.SetKeyEntry(alias, keyEntry.Key, string.IsNullOrEmpty(storePassword) ? new char[0] : storePassword.ToCharArray(), certificates.ToArray());
}
else
{
certificates.Add(certificateEntry.Certificate);
jksStore.SetCertificateEntry(alias, certificateStore.GetCertificate(alias).Certificate);
}

jksStore.SetKeyEntry(alias, keyEntry.Key, string.IsNullOrEmpty(storePassword) ? new char[0] : storePassword.ToCharArray(), certificates.ToArray());
}
else

using (MemoryStream outStream = new MemoryStream())
{
jksStore.SetCertificateEntry(alias, certificateStore.GetCertificate(alias).Certificate);
jksStore.Save(outStream, string.IsNullOrEmpty(storePassword) ? new char[0] : storePassword.ToCharArray());

storeInfo.Add(new SerializedStoreInfo() { FilePath = storePath + storeFileName, Contents = outStream.ToArray() });

logger.MethodExit(LogLevel.Debug);
return storeInfo;
}
}

using (MemoryStream outStream = new MemoryStream())
else
{
jksStore.Save(outStream, string.IsNullOrEmpty(storePassword) ? new char[0] : storePassword.ToCharArray());

List<SerializedStoreInfo> storeInfo = new List<SerializedStoreInfo>();
storeInfo.Add(new SerializedStoreInfo() { FilePath = storePath + storeFileName, Contents = outStream.ToArray() });

logger.MethodExit(LogLevel.Debug);
return storeInfo;
PKCS12CertificateStoreSerializer pkcs12Serializer = new PKCS12CertificateStoreSerializer(string.Empty);
storeInfo = pkcs12Serializer.SerializeRemoteCertificateStore(certificateStore, storePath, storeFileName, storePassword, remoteHandler);
}

return storeInfo;
}

public string GetPrivateKeyPath()
Expand Down
24 changes: 24 additions & 0 deletions RemoteFile/ImplementedStoreTypes/JKS/Reenrollment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2021 Keyfactor
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
// and limitations under the License.

using Keyfactor.Orchestrators.Extensions.Interfaces;

namespace Keyfactor.Extensions.Orchestrator.RemoteFile.JKS
{
public class Reenrollment : ReenrollmentBase
{
internal override ICertificateStoreSerializer GetCertificateStoreSerializer(string storeProperties)
{
return new JKSCertificateStoreSerializer(storeProperties);
}

public Reenrollment(IPAMSecretResolver resolver)
{
_resolver = resolver;
}
}
}
24 changes: 24 additions & 0 deletions RemoteFile/ImplementedStoreTypes/KDB/Reenrollment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2021 Keyfactor
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
// and limitations under the License.

using Keyfactor.Orchestrators.Extensions.Interfaces;

namespace Keyfactor.Extensions.Orchestrator.RemoteFile.KDB
{
public class Reenrollment : ReenrollmentBase
{
internal override ICertificateStoreSerializer GetCertificateStoreSerializer(string storeProperties)
{
return new KDBCertificateStoreSerializer(storeProperties);
}

public Reenrollment(IPAMSecretResolver resolver)
{
_resolver = resolver;
}
}
}
25 changes: 25 additions & 0 deletions RemoteFile/ImplementedStoreTypes/OraWlt/Reenrollment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2021 Keyfactor
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
// and limitations under the License.

using Keyfactor.Extensions.Orchestrator.RemoteFile.KDB;
using Keyfactor.Orchestrators.Extensions.Interfaces;

namespace Keyfactor.Extensions.Orchestrator.RemoteFile.OraWlt
{
public class Reenrollment : ReenrollmentBase
{
internal override ICertificateStoreSerializer GetCertificateStoreSerializer(string storeProperties)
{
return new OraWltCertificateStoreSerializer(storeProperties);
}

public Reenrollment(IPAMSecretResolver resolver)
{
_resolver = resolver;
}
}
}
25 changes: 25 additions & 0 deletions RemoteFile/ImplementedStoreTypes/PEM/Reenrollment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2021 Keyfactor
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
// and limitations under the License.

using Keyfactor.Extensions.Orchestrator.RemoteFile.PEM;
using Keyfactor.Orchestrators.Extensions.Interfaces;

namespace Keyfactor.Extensions.Orchestrator.RemoteFile.PEM
{
public class Reenrollment : ReenrollmentBase
{
internal override ICertificateStoreSerializer GetCertificateStoreSerializer(string storeProperties)
{
return new PEMCertificateStoreSerializer(storeProperties);
}

public Reenrollment(IPAMSecretResolver resolver)
{
_resolver = resolver;
}
}
}
24 changes: 24 additions & 0 deletions RemoteFile/ImplementedStoreTypes/PKCS12/Reenrollment.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2021 Keyfactor
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
// and limitations under the License.

using Keyfactor.Orchestrators.Extensions.Interfaces;

namespace Keyfactor.Extensions.Orchestrator.RemoteFile.PKCS12
{
public class Reenrollment : ReenrollmentBase
{
internal override ICertificateStoreSerializer GetCertificateStoreSerializer(string storeProperties)
{
return new PKCS12CertificateStoreSerializer(storeProperties);
}

public Reenrollment(IPAMSecretResolver resolver)
{
_resolver = resolver;
}
}
}
2 changes: 1 addition & 1 deletion RemoteFile/InventoryBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace Keyfactor.Extensions.Orchestrator.RemoteFile
{
public abstract class InventoryBase : RemoteFileJobTypeBase, IInventoryJobExtension
{
public string ExtensionName => string.Empty;
public string ExtensionName => "Keyfactor.Extensions.Orchestrator.RemoteFile.Inventory";

RemoteCertificateStore certificateStore = new RemoteCertificateStore();

Expand Down
Loading
Loading