diff --git a/.github/workflows/keyfactor-merge-store-types.yml b/.github/workflows/keyfactor-merge-store-types.yml deleted file mode 100644 index c70659f..0000000 --- a/.github/workflows/keyfactor-merge-store-types.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Keyfactor Merge Cert Store Types -on: [workflow_dispatch] - -jobs: - get-manifest-properties: - runs-on: windows-latest - outputs: - update_catalog: ${{ steps.read-json.outputs.update_catalog }} - integration_type: ${{ steps.read-json.outputs.integration_type }} - steps: - - uses: actions/checkout@v3 - - name: Store json - id: read-json - shell: pwsh - run: | - $json = Get-Content integration-manifest.json | ConvertFrom-Json - $myvar = $json.update_catalog - echo "update_catalog=$myvar" | Out-File -FilePath $Env:GITHUB_OUTPUT -Encoding utf8 -Append - $myvar = $json.integration_type - echo "integration_type=$myvar" | Out-File -FilePath $Env:GITHUB_OUTPUT -Encoding utf8 -Append - - call-update-store-types-workflow: - needs: get-manifest-properties - if: needs.get-manifest-properties.outputs.integration_type == 'orchestrator' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') - uses: Keyfactor/actions/.github/workflows/update-store-types.yml@main - secrets: - token: ${{ secrets.UPDATE_STORE_TYPES }} diff --git a/.github/workflows/keyfactor-starter-workflow.yml b/.github/workflows/keyfactor-starter-workflow.yml index 81fd2d0..6d8de53 100644 --- a/.github/workflows/keyfactor-starter-workflow.yml +++ b/.github/workflows/keyfactor-starter-workflow.yml @@ -1,44 +1,19 @@ -name: Starter Workflow -on: [workflow_dispatch, push, pull_request] +name: Keyfactor Bootstrap Workflow -jobs: - call-create-github-release-workflow: - uses: Keyfactor/actions/.github/workflows/github-release.yml@main - - get-manifest-properties: - runs-on: windows-latest - outputs: - update_catalog: ${{ steps.read-json.outputs.prop }} - steps: - - uses: actions/checkout@v3 - - name: Read json - id: read-json - shell: pwsh - run: | - $json = Get-Content integration-manifest.json | ConvertFrom-Json - echo "::set-output name=prop::$(echo $json.update_catalog)" +on: + workflow_dispatch: + pull_request: + types: [opened, closed, synchronize, edited, reopened] + push: + create: + branches: + - 'release-*.*' - call-dotnet-build-and-release-workflow: - needs: [call-create-github-release-workflow] - uses: Keyfactor/actions/.github/workflows/dotnet-build-and-release.yml@main - with: - release_version: ${{ needs.call-create-github-release-workflow.outputs.release_version }} - release_url: ${{ needs.call-create-github-release-workflow.outputs.release_url }} - release_dir: IISU/bin/Release/net6.0 - secrets: - token: ${{ secrets.PRIVATE_PACKAGE_ACCESS }} - - call-generate-readme-workflow: - if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' - uses: Keyfactor/actions/.github/workflows/generate-readme.yml@main +jobs: + call-starter-workflow: + uses: keyfactor/actions/.github/workflows/starter.yml@v2 secrets: - token: ${{ secrets.APPROVE_README_PUSH }} - - call-update-catalog-workflow: - needs: get-manifest-properties - if: needs.get-manifest-properties.outputs.update_catalog == 'True' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') - uses: Keyfactor/actions/.github/workflows/update-catalog.yml@main - secrets: - token: ${{ secrets.SDK_SYNC_PAT }} - - + token: ${{ secrets.V2BUILDTOKEN}} + APPROVE_README_PUSH: ${{ secrets.APPROVE_README_PUSH}} + gpg_key: ${{ secrets.KF_GPG_PRIVATE_KEY }} + gpg_pass: ${{ secrets.KF_GPG_PASSPHRASE }} diff --git a/CHANGELOG.md b/CHANGELOG.md index c5bf3d0..f2927ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ +2.3.1 +* Added additional error trapping for WinRM connections to allow actual error on failure. + 2.3.0 * Added Sql Server Binding Support - +* Modified WinCert Advanced PrivateKeyAllowed setting from Required to Optional + 2.2.2 * Removed empty constructor to resolve PAM provider error when using WinCert store types diff --git a/IISU/ClientPSCertStoreManager.cs b/IISU/ClientPSCertStoreManager.cs index ba0972a..35d0cb8 100644 --- a/IISU/ClientPSCertStoreManager.cs +++ b/IISU/ClientPSCertStoreManager.cs @@ -65,9 +65,8 @@ public JobResult AddCertificate(string certificateContents, string privateKeyPas X509KeyStorageFlags.Exportable ); - _logger.LogTrace($"X509 Cert Created With Subject: {x509Cert.SubjectName}"); - _logger.LogTrace( - $"Begin Add for Cert Store {$@"\\{_runspace.ConnectionInfo.ComputerName}\{storePath}"}"); + _logger.LogDebug($"X509 Cert Created With Subject: {x509Cert.SubjectName}"); + _logger.LogDebug($"Begin Add for Cert Store {$@"\\{_runspace.ConnectionInfo.ComputerName}\{storePath}"}"); // Add Certificate var funcScript = @" @@ -83,12 +82,13 @@ function InstallPfxToMachineStore([byte[]]$bytes, [string]$password, [string]$st }"; ps.AddScript(funcScript).AddStatement(); - _logger.LogTrace("InstallPfxToMachineStore Statement Added..."); + _logger.LogDebug("InstallPfxToMachineStore Statement Added..."); ps.AddCommand("InstallPfxToMachineStore") .AddParameter("bytes", Convert.FromBase64String(certificateContents)) .AddParameter("password", privateKeyPassword) .AddParameter("storeName", $@"\\{_runspace.ConnectionInfo.ComputerName}\{storePath}"); + _logger.LogTrace("InstallPfxToMachineStore Command Added..."); foreach (var cmd in ps.Commands.Commands) @@ -100,6 +100,7 @@ function InstallPfxToMachineStore([byte[]]$bytes, [string]$password, [string]$st _logger.LogTrace("Invoking ps..."); ps.Invoke(); _logger.LogTrace("ps Invoked..."); + if (ps.HadErrors) { _logger.LogTrace("ps Has Errors"); @@ -119,6 +120,7 @@ function InstallPfxToMachineStore([byte[]]$bytes, [string]$password, [string]$st _logger.LogTrace("Clearing Commands..."); ps.Commands.Clear(); _logger.LogTrace("Commands Cleared.."); + _logger.LogInformation($"Certificate was successfully added to cert store: {storePath}"); return new JobResult { @@ -129,6 +131,8 @@ function InstallPfxToMachineStore([byte[]]$bytes, [string]$password, [string]$st } catch (Exception e) { + _logger.LogError($"Error Occurred in ClientPSCertStoreManager.AddCertificate(): {e.Message}"); + return new JobResult { Result = OrchestratorJobStatusJobResult.Failure, diff --git a/IISU/ImplementedStoreTypes/Win/Management.cs b/IISU/ImplementedStoreTypes/Win/Management.cs index c79a485..dbd6ed6 100644 --- a/IISU/ImplementedStoreTypes/Win/Management.cs +++ b/IISU/ImplementedStoreTypes/Win/Management.cs @@ -119,26 +119,22 @@ private JobResult performAddition(ManagementJobConfiguration config) string storePath = config.CertificateStoreDetails.StorePath; long jobNumber = config.JobHistoryId; - // Setup a new connection to the client machine - //var connectionInfo = new WSManConnectionInfo(new Uri($"{certStoreDetails?.WinRmProtocol}://{config.CertificateStoreDetails.ClientMachine}:{certStoreDetails?.WinRmPort}/wsman")); - //_logger.LogTrace($"WinRm URL: {certStoreDetails?.WinRmProtocol}://{config.CertificateStoreDetails.ClientMachine}:{certStoreDetails?.WinRmPort}/wsman"); - if (storePath != null) { - _logger.LogTrace($"Attempting to get licenses from cert path: {storePath})"); + _logger.LogInformation($"Attempting to add certificate to cert store: {storePath}"); ClientPSCertStoreManager manager = new ClientPSCertStoreManager(_logger, myRunspace, jobNumber); - JobResult result = manager.AddCertificate(certificateContents, privateKeyPassword, storePath); - - _logger.LogTrace($"Certificate was successfully added to cert store: {storePath})"); + return manager.AddCertificate(certificateContents, privateKeyPassword, storePath); } - - return new JobResult + else { - Result = OrchestratorJobStatusJobResult.Success, - JobHistoryId = config.JobHistoryId, - FailureMessage = "" - }; + return new JobResult + { + Result = OrchestratorJobStatusJobResult.Failure, + JobHistoryId = config.JobHistoryId, + FailureMessage = "Store Path is empty or null." + }; + } } catch (Exception e) { diff --git a/README.md b/README.md index 3b05b52..11df329 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ + # WinCertStore Orchestrator The Windows Certificate Store Orchestrator Extension implements two certificate store types. 1) “WinCert” which manages certificates in a Windows local machine store, and 2) “IISU” which manages certificates and their bindings in a Windows local machine store that are bound to Internet Information Server (IIS) websites. These extensions replace the now deprecated “IIS” cert store type that ships with Keyfactor Command. The “IISU” extension also replaces the “IISBin” certificate store type from prior versions of this repository. This orchestrator extension is in the process of being renamed from “IIS Orchestrator” as it now supports certificates that are not in use by IIS. #### Integration status: Production - Ready for use in production environments. - ## About the Keyfactor Universal Orchestrator Extension This repository contains a Universal Orchestrator Extension which is a plugin to the Keyfactor Universal Orchestrator. Within the Keyfactor Platform, Orchestrators are used to manage “certificate stores” — collections of certificates and roots of trust that are found within and used by various applications. @@ -13,23 +13,22 @@ The Universal Orchestrator is part of the Keyfactor software distribution and is The Universal Orchestrator is the successor to the Windows Orchestrator. This Orchestrator Extension plugin only works with the Universal Orchestrator and does not work with the Windows Orchestrator. - ## Support for WinCertStore Orchestrator -WinCertStore Orchestrator is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket with your Keyfactor representative. +WinCertStore Orchestrator is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com ###### To report a problem or suggest a new feature, use the **[Issues](../../issues)** tab. If you want to contribute actual bug fixes or proposed enhancements, use the **[Pull requests](../../pulls)** tab. - --- +--- + ## Keyfactor Version Supported The minimum version of the Keyfactor Universal Orchestrator Framework needed to run this version of the extension is 10.1 - ## Platform Specific Notes The Keyfactor Universal Orchestrator may be installed on either Windows or Linux based platforms. The certificate operations supported by a capability may vary based what platform the capability is installed on. The table below indicates what capabilities are supported based on which platform the encompassing Universal Orchestrator is running. @@ -124,6 +123,27 @@ In version 2.0 of the IIS Orchestrator, the certificate store type has been rena **Note: If Looking to use GMSA Accounts to run the Service Kefyactor Command 10.2 or greater is required for No Value checkbox to work** +## Security and Permission Considerations +From an official support point of view, Local Administrator permissions are required on the target server. Some customers have been successful with using other accounts and granting rights to the underlying certificate and private key stores. Due to complexities with the interactions between Group Policy, WinRM, User Account Control, and other unpredictable customer environmental factors, Keyfactor cannot provide assistance with using accounts other than the local administrator account. + +For customers wishing to use something other than the local administrator account, the following information may be helpful: + +* The WinCert extensions (WinCert, IISU, WinSQL) create a WinRM (remote PowerShell) session to the target server in order to manipulate the Windows Certificate Stores, perform binding (in the case of the IISU extension), or to access the registry (in the case of the WinSQL extension). + +* When the WinRM session is created, the certificate store credentials are used if they have been specified, otherwise the WinRM session is created in the context of the Universal Orchestrator (UO) Service account (which potentially could be the network service account, a regular account, or a GMSA account) + +* WinRM needs to be properly set up between the server hosting the UO and the target server. This means that a WinRM client running on the UO server when running in the context of the UO service account needs to be able to create a session on the target server using the configured credentials of the target server and any PowerShell commands running on the remote session need to have appropriate permissions. + +* Even though a given account may be in the administrators group or have administrative privledges on the target system and may be able to execute certificate and binding operations when running locally, the same account may not work when being used via WinRM. User Account Control (UAC) can get in the way and filter out administrative privledges. UAC / WinRM configuration has a LocalAccountTokenFilterPolicy setting that can be adjusted to not filter out administrative privledges for remote users, but enabling this may have other security ramifications. + +* The following list may not be exhaustive, but in general the account (when running under a remote WinRM session) needs permissions to: + - Instantiate and open a .NET X509Certificates.X509Store object for the target certificate store and be able to read and write both the certificates and related private keys. Note that ACL permissions on the stores and private keys are separate. + - Use the Import-Certificate, Get-WebSite, Get-WebBinding, and New-WebBinding PowerShell CmdLets. + - Create and delete temporary files. + - Execute certreq commands. + - Access any Cryptographic Service Provider (CSP) referenced in re-enrollment jobs. + - Read and Write values in the registry (HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server) when performing SQL Server certificate binding. + ## Creating New Certificate Store Types Currently this orchestrator handles two extensions: IISU for IIS servers with bound certificates and WinCert for general Windows Certificates. Below describes how each of these certificate store types are created and configured. @@ -155,7 +175,7 @@ CONFIG ELEMENT | VALUE | DESCRIPTION Store Path Type | Multiple Choice | Determines what restrictions are applied to the store path field when configuring a new store. Store Path Value | My,WebHosting | Comma separated list of options configure multiple choice. This, combined with the hostname, will determine the location used for the certificate store management and inventory. Supports Custom Alias | Forbidden | Determines if an individual entry within a store can have a custom Alias. -Private Keys | Required | This determines if Keyfactor can send the private key associated with a certificate to the store. Required because IIS certificates without private keys would be useless. +Private Keys | Required | This determines if Keyfactor can send the private key associated with a certificate to the store. Required because IIS certificates without private keys would be invalid. PFX Password Style | Default or Custom | "Default" - PFX password is randomly generated, "Custom" - PFX password may be specified when the enrollment job is created (Requires the *Allow Custom Password* application setting to be enabled.) ![](images/IISUCertStoreAdv.png) @@ -297,7 +317,7 @@ CONFIG ELEMENT | VALUE | DESCRIPTION --|--|-- Store Path Type | Freeform | Allows users to type in a valid certificate store. Supports Custom Alias | Forbidden | Determines if an individual entry within a store can have a custom Alias. -Private Keys | Required | This determines if Keyfactor can send the private key associated with a certificate to the store. Required because IIS certificates without private keys would be useless. +Private Keys | Optional | This determines if Keyfactor can send the private key associated with a certificate to the store. Typically the personal store would have private keys, whereas trusted root would not. PFX Password Style | Default or Custom | "Default" - PFX password is randomly generated, "Custom" - PFX password may be specified when the enrollment job is created (Requires the *Allow Custom Password* application setting to be enabled.) ![](images/WinCertAdvanced.png) diff --git a/images/WinCertAdvanced.png b/images/WinCertAdvanced.png index feef117..ff66e5c 100644 Binary files a/images/WinCertAdvanced.png and b/images/WinCertAdvanced.png differ diff --git a/integration-manifest.json b/integration-manifest.json index f558b94..1418235 100644 --- a/integration-manifest.json +++ b/integration-manifest.json @@ -4,6 +4,7 @@ "name": "WinCertStore Orchestrator", "status": "production", "link_github": true, + "release_dir": "IISU/bin/Release/net6.0", "update_catalog": true, "support_level": "kf-supported", "description": "The Windows Certificate Store Orchestrator Extension implements two certificate store types. 1) “WinCert” which manages certificates in a Windows local machine store, and 2) “IISU” which manages certificates and their bindings in a Windows local machine store that are bound to Internet Information Server (IIS) websites. These extensions replace the now deprecated “IIS” cert store type that ships with Keyfactor Command. The “IISU” extension also replaces the “IISBin” certificate store type from prior versions of this repository. This orchestrator extension is in the process of being renamed from “IIS Orchestrator” as it now supports certificates that are not in use by IIS.", @@ -11,6 +12,7 @@ "orchestrator": { "UOFramework": "10.1", "pam_support": true, + "keyfactor_platform_version": "9.10", "win": { "supportsCreateStore": false, "supportsDiscovery": false, @@ -415,4 +417,4 @@ ] } } -} \ No newline at end of file +} diff --git a/readme_source.md b/readme_source.md index 02a6d47..50c296f 100644 --- a/readme_source.md +++ b/readme_source.md @@ -23,6 +23,27 @@ In version 2.0 of the IIS Orchestrator, the certificate store type has been rena **Note: If Looking to use GMSA Accounts to run the Service Kefyactor Command 10.2 or greater is required for No Value checkbox to work** +## Security and Permission Considerations +From an official support point of view, Local Administrator permissions are required on the target server. Some customers have been successful with using other accounts and granting rights to the underlying certificate and private key stores. Due to complexities with the interactions between Group Policy, WinRM, User Account Control, and other unpredictable customer environmental factors, Keyfactor cannot provide assistance with using accounts other than the local administrator account. + +For customers wishing to use something other than the local administrator account, the following information may be helpful: + +* The WinCert extensions (WinCert, IISU, WinSQL) create a WinRM (remote PowerShell) session to the target server in order to manipulate the Windows Certificate Stores, perform binding (in the case of the IISU extension), or to access the registry (in the case of the WinSQL extension). + +* When the WinRM session is created, the certificate store credentials are used if they have been specified, otherwise the WinRM session is created in the context of the Universal Orchestrator (UO) Service account (which potentially could be the network service account, a regular account, or a GMSA account) + +* WinRM needs to be properly set up between the server hosting the UO and the target server. This means that a WinRM client running on the UO server when running in the context of the UO service account needs to be able to create a session on the target server using the configured credentials of the target server and any PowerShell commands running on the remote session need to have appropriate permissions. + +* Even though a given account may be in the administrators group or have administrative privledges on the target system and may be able to execute certificate and binding operations when running locally, the same account may not work when being used via WinRM. User Account Control (UAC) can get in the way and filter out administrative privledges. UAC / WinRM configuration has a LocalAccountTokenFilterPolicy setting that can be adjusted to not filter out administrative privledges for remote users, but enabling this may have other security ramifications. + +* The following list may not be exhaustive, but in general the account (when running under a remote WinRM session) needs permissions to: + - Instantiate and open a .NET X509Certificates.X509Store object for the target certificate store and be able to read and write both the certificates and related private keys. Note that ACL permissions on the stores and private keys are separate. + - Use the Import-Certificate, Get-WebSite, Get-WebBinding, and New-WebBinding PowerShell CmdLets. + - Create and delete temporary files. + - Execute certreq commands. + - Access any Cryptographic Service Provider (CSP) referenced in re-enrollment jobs. + - Read and Write values in the registry (HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server) when performing SQL Server certificate binding. + ## Creating New Certificate Store Types Currently this orchestrator handles two extensions: IISU for IIS servers with bound certificates and WinCert for general Windows Certificates. Below describes how each of these certificate store types are created and configured. @@ -54,7 +75,7 @@ CONFIG ELEMENT | VALUE | DESCRIPTION Store Path Type | Multiple Choice | Determines what restrictions are applied to the store path field when configuring a new store. Store Path Value | My,WebHosting | Comma separated list of options configure multiple choice. This, combined with the hostname, will determine the location used for the certificate store management and inventory. Supports Custom Alias | Forbidden | Determines if an individual entry within a store can have a custom Alias. -Private Keys | Required | This determines if Keyfactor can send the private key associated with a certificate to the store. Required because IIS certificates without private keys would be useless. +Private Keys | Required | This determines if Keyfactor can send the private key associated with a certificate to the store. Required because IIS certificates without private keys would be invalid. PFX Password Style | Default or Custom | "Default" - PFX password is randomly generated, "Custom" - PFX password may be specified when the enrollment job is created (Requires the *Allow Custom Password* application setting to be enabled.) ![](images/IISUCertStoreAdv.png) @@ -196,7 +217,7 @@ CONFIG ELEMENT | VALUE | DESCRIPTION --|--|-- Store Path Type | Freeform | Allows users to type in a valid certificate store. Supports Custom Alias | Forbidden | Determines if an individual entry within a store can have a custom Alias. -Private Keys | Required | This determines if Keyfactor can send the private key associated with a certificate to the store. Required because IIS certificates without private keys would be useless. +Private Keys | Optional | This determines if Keyfactor can send the private key associated with a certificate to the store. Typically the personal store would have private keys, whereas trusted root would not. PFX Password Style | Default or Custom | "Default" - PFX password is randomly generated, "Custom" - PFX password may be specified when the enrollment job is created (Requires the *Allow Custom Password* application setting to be enabled.) ![](images/WinCertAdvanced.png)