diff --git a/.github/workflows/keyfactor-bootstrap-workflow.yml b/.github/workflows/keyfactor-bootstrap-workflow.yml new file mode 100644 index 0000000..6d8de53 --- /dev/null +++ b/.github/workflows/keyfactor-bootstrap-workflow.yml @@ -0,0 +1,19 @@ +name: Keyfactor Bootstrap Workflow + +on: + workflow_dispatch: + pull_request: + types: [opened, closed, synchronize, edited, reopened] + push: + create: + branches: + - 'release-*.*' + +jobs: + call-starter-workflow: + uses: keyfactor/actions/.github/workflows/starter.yml@v2 + secrets: + 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/.github/workflows/keyfactor-starter-workflow.yml b/.github/workflows/keyfactor-starter-workflow.yml deleted file mode 100644 index 3956f02..0000000 --- a/.github/workflows/keyfactor-starter-workflow.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: Starter Workflow -on: [workflow_dispatch, push, pull_request] - -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)" - - 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: Imperva/bin/Release # TODO: set build output directory to upload as a release, relative to checkout workspace - 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 - 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 }} diff --git a/CHANGELOG.md b/CHANGELOG.md index fbc3235..4340fb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,5 @@ +v1.0.1 +- Bug fix: Individual site timeouts will no longer end inventory but will instead skip that site and move on. Inventory in those cases will produce a warning that certificates could not be retrieved for one or more sites, but it will still return all retrieved certificates. + v1.0 - Initial Version diff --git a/Imperva/APIProcessor.cs b/Imperva/APIProcessor.cs index 94a45b8..8c9aef4 100644 --- a/Imperva/APIProcessor.cs +++ b/Imperva/APIProcessor.cs @@ -107,8 +107,14 @@ public List GetSites() return sites; } - public X509Certificate2 GetServerCertificateAsync(string url) + public X509Certificate2 GetServerCertificateAsync(string url, out bool hadError) { + ILogger logger = LogHandler.GetClassLogger(); + logger.MethodEntry(LogLevel.Debug); + logger.LogTrace($"Calling URL {url}"); + + hadError = false; + if (!url.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) url = "https://" + url; @@ -117,7 +123,9 @@ public X509Certificate2 GetServerCertificateAsync(string url) { ServerCertificateCustomValidationCallback = (_, cert, __, ___) => { + logger.LogTrace("Hit handler"); certificate = new X509Certificate2(cert.GetRawCertData()); + logger.LogTrace($"Cert returned: {cert.GetRawCertData()}"); return true; } }; @@ -128,8 +136,13 @@ public X509Certificate2 GetServerCertificateAsync(string url) { httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, url)).GetAwaiter().GetResult(); } - catch (HttpRequestException) { } + catch (Exception ex) + { + logger.LogError(ImpervaException.FlattenExceptionMessages(ex, $"Error retrieving certificate for {url}: ")); + hadError = true; + } + logger.MethodExit(LogLevel.Debug); return certificate; } #endregion diff --git a/Imperva/Inventory.cs b/Imperva/Inventory.cs index 9e68cda..9a83168 100644 --- a/Imperva/Inventory.cs +++ b/Imperva/Inventory.cs @@ -38,6 +38,7 @@ public JobResult ProcessJob(InventoryJobConfiguration config, SubmitInventoryUpd logger.LogDebug($"Store Path: {config.CertificateStoreDetails.StorePath}"); List inventoryItems = new List(); + bool oneOrMoreErrors = false; try { @@ -50,7 +51,10 @@ public JobResult ProcessJob(InventoryJobConfiguration config, SubmitInventoryUpd foreach(Site site in sites) { - X509Certificate2 certificate = api.GetServerCertificateAsync(site.Domain); + bool hadError = false; + X509Certificate2 certificate = api.GetServerCertificateAsync(site.Domain, out hadError); + if (hadError) + oneOrMoreErrors = true; if (certificate == null) continue; inventoryItems.Add(new CurrentInventoryItem() @@ -74,7 +78,10 @@ public JobResult ProcessJob(InventoryJobConfiguration config, SubmitInventoryUpd try { submitInventory.Invoke(inventoryItems); - return new JobResult() { Result = Keyfactor.Orchestrators.Common.Enums.OrchestratorJobStatusJobResult.Success, JobHistoryId = config.JobHistoryId }; + if (oneOrMoreErrors) + return new JobResult() { Result = Keyfactor.Orchestrators.Common.Enums.OrchestratorJobStatusJobResult.Warning, JobHistoryId = config.JobHistoryId, FailureMessage = "One or more certificates could not be returned. Please see the log for more details." }; + else + return new JobResult() { Result = Keyfactor.Orchestrators.Common.Enums.OrchestratorJobStatusJobResult.Success, JobHistoryId = config.JobHistoryId }; } catch (Exception ex) { diff --git a/Imperva/Management.cs b/Imperva/Management.cs index 79f0238..8c0d87f 100644 --- a/Imperva/Management.cs +++ b/Imperva/Management.cs @@ -60,7 +60,8 @@ public JobResult ProcessJob(ManagementJobConfiguration config) { case CertStoreOperationType.Add: - if (!config.Overwrite && api.GetServerCertificateAsync(site.Domain) != null) + bool hadError = false; + if (!config.Overwrite && api.GetServerCertificateAsync(site.Domain, out hadError) != null) return new JobResult() { Result = Keyfactor.Orchestrators.Common.Enums.OrchestratorJobStatusJobResult.Warning, JobHistoryId = config.JobHistoryId, FailureMessage = $"Overwrite is set to false but there is a certificate that already is bound to {config.JobCertificate.Alias}. Please set overwrite to true and reschedule the job to replace this certificate." }; api.AddCertificate(site.SiteID, config.JobCertificate.Contents, config.JobCertificate.PrivateKeyPassword); diff --git a/README.md b/README.md index 4dd21b7..380aa62 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ + # Imperva The Imperva Orchestrator Extension allows for the management of SSL certificates bound to web sites managed by the Imperva cloud-based firewall. @@ -12,18 +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 Imperva +Imperva 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. @@ -51,6 +56,11 @@ It is not necessary to use a PAM Provider for all of the secrets available above If a PAM Provider will be used for one of the fields above, start by referencing the [Keyfactor Integration Catalog](https://keyfactor.github.io/integrations-catalog/content/pam). The GitHub repo for the PAM Provider to be used contains important information such as the format of the `json` needed. What follows is an example but does not reflect the `json` values for all PAM Providers as they have different "instance" and "initialization" parameter names and values. +
General PAM Provider Configuration +

+ + + ### Example PAM Provider Setup To use a PAM Provider to resolve a field, in this example the __Server Password__ will be resolved by the `Hashicorp-Vault` provider, first install the PAM Provider extension from the [Keyfactor Integration Catalog](https://keyfactor.github.io/integrations-catalog/content/pam) on the Universal Orchestrator. @@ -77,6 +87,8 @@ To have the __Server Password__ field resolved by the `Hashicorp-Vault` provider ~~~ This text would be entered in as the value for the __Server Password__, instead of entering in the actual password. The Orchestrator will attempt to use the PAM Provider to retrieve the __Server Password__. If PAM should not be used, just directly enter in the value for the field. +

+
diff --git a/integration-manifest.json b/integration-manifest.json index 087993b..9f251cb 100644 --- a/integration-manifest.json +++ b/integration-manifest.json @@ -4,12 +4,15 @@ "name": "Imperva", "status": "production", "description": "The Imperva Orchestrator Extension allows for the management of SSL certificates bound to web sites managed by the Imperva cloud-based firewall.", - "link_github": true, + "release_dir": "Imperva/bin/Release", + "support_level": "kf-supported", "update_catalog": true, + "link_github": true, "about": { "orchestrator": { "UOFramework": "10.1", "pam_support": true, + "keyfactor_platform_version": "9.10", "win": { "supportsCreateStore": false, "supportsDiscovery": false, @@ -25,7 +28,33 @@ "supportsManagementRemove": true, "supportsReenrollment": false, "supportsInventory": true + }, + "store_types": { + "Imperva": { + "Name": "Imperva", + "ShortName": "Imperva", + "Capability": "Imperva", + "ServerRequired": false, + "BlueprintAllowed": false, + "CustomAliasAllowed": "Required", + "PowerShell": false, + "PrivateKeyAllowed": "Required", + "SupportedOperations": { + "Add": true, + "Create": false, + "Discovery": false, + "Enrollment": false, + "Remove": true + }, + "PasswordOptions": { + "Style": "Default", + "EntrySupported": false, + "StoreRequired": true + }, + "Properties": [], + "EntryParameters": [] + } } } } -} +} \ No newline at end of file