Skip to content
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
13 changes: 10 additions & 3 deletions .github/workflows/keyfactor-starter-workflow.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Keyfactor Bootstrap Workflow
name: Keyfactor Bootstrap Workflow

on:
workflow_dispatch:
Expand All @@ -11,10 +11,17 @@ on:

jobs:
call-starter-workflow:
uses: keyfactor/actions/.github/workflows/starter.yml@3.1.2
uses: keyfactor/actions/.github/workflows/starter.yml@v4
with:
command_token_url: ${{ vars.COMMAND_TOKEN_URL }}
command_hostname: ${{ vars.COMMAND_HOSTNAME }}
command_base_api_path: ${{ vars.COMMAND_API_PATH }}
secrets:
token: ${{ secrets.V2BUILDTOKEN}}
APPROVE_README_PUSH: ${{ secrets.APPROVE_README_PUSH}}
gpg_key: ${{ secrets.KF_GPG_PRIVATE_KEY }}
gpg_pass: ${{ secrets.KF_GPG_PASSPHRASE }}
scan_token: ${{ secrets.SAST_TOKEN }}
entra_username: ${{ secrets.DOCTOOL_ENTRA_USERNAME }}
entra_password: ${{ secrets.DOCTOOL_ENTRA_PASSWD }}
command_client_id: ${{ secrets.COMMAND_CLIENT_ID }}
command_client_secret: ${{ secrets.COMMAND_CLIENT_SECRET }}
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
v1.3.0
v1.4.0
- Add ability to manage custom VDOMs. PLEASE NOTE this release contains a breaking change. Store Path MUST contain the value for the VDOM the certificate will be managing. `root` must be entered to manage the default 'root' VDOM.

v1.3.0
- Add support for renewing certificate bound to the HTTPS server

v1.2.0
- Allow for the management (renew/replace) of bound certificates

Expand Down
36 changes: 36 additions & 0 deletions Fortigate/Api/HttpsUsage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//Copyright 2023 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 Newtonsoft.Json;
using System.Text.Json.Serialization;

namespace Keyfactor.Extensions.Orchestrator.Fortigate.Api
{
public class HttpsUsage
{
[JsonProperty("admin-server-cert")]
public string AdminServerCert { get; set; }
}

public class HttpUsageRequest
{
[JsonProperty("admin-server-cert")]
public OriginKey AdminServerCert { get; set; }
}

public class OriginKey
{
[JsonProperty("q_origin_key")]
public string QOriginKey { get; set; }
}
}
59 changes: 55 additions & 4 deletions Fortigate/FortigateStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
using System.Text;
using System.Net.Http.Headers;
using Microsoft.Extensions.Logging;
using Org.BouncyCastle.Asn1.Ocsp;

namespace Keyfactor.Extensions.Orchestrator.Fortigate
{
Expand All @@ -46,13 +47,14 @@
//private static readonly string certificate_api = "/api/v2/cmdb/certificate/local";
private static readonly string import_certificate_api = "/api/v2/monitor/vpn-certificate/local/import";

private static readonly string get_certificate_api = "/api/v2/cmdb/certificate/local/";

Check warning on line 50 in Fortigate/FortigateStore.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

The field 'FortigateStore.get_certificate_api' is assigned but its value is never used

Check warning on line 50 in Fortigate/FortigateStore.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

The field 'FortigateStore.get_certificate_api' is assigned but its value is never used

Check warning on line 50 in Fortigate/FortigateStore.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

The field 'FortigateStore.get_certificate_api' is assigned but its value is never used

Check warning on line 50 in Fortigate/FortigateStore.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

The field 'FortigateStore.get_certificate_api' is assigned but its value is never used

Check warning on line 50 in Fortigate/FortigateStore.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

The field 'FortigateStore.get_certificate_api' is assigned but its value is never used

Check warning on line 50 in Fortigate/FortigateStore.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

The field 'FortigateStore.get_certificate_api' is assigned but its value is never used

Check warning on line 50 in Fortigate/FortigateStore.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

The field 'FortigateStore.get_certificate_api' is assigned but its value is never used

Check warning on line 50 in Fortigate/FortigateStore.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

The field 'FortigateStore.get_certificate_api' is assigned but its value is never used

Check warning on line 50 in Fortigate/FortigateStore.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

The field 'FortigateStore.get_certificate_api' is assigned but its value is never used

Check warning on line 50 in Fortigate/FortigateStore.cs

View workflow job for this annotation

GitHub Actions / call-starter-workflow / call-dotnet-build-and-release-workflow / dotnet-build-and-release

The field 'FortigateStore.get_certificate_api' is assigned but its value is never used
private static readonly string get_vdom_api = "/api/v2/cmdb/system/vdom/";

//api/v2/cmdb/vpn.certificate/local/test?vdom=root
private static readonly string delete_certificate_api = "/api/v2/cmdb/vpn.certificate/local/";

private static readonly string cert_usage_api = "/api/v2/monitor/system/object/usage";
private static readonly string https_usage_api = "/api/v2/cmdb/system/global";

private readonly HttpClientHandler handler = new HttpClientHandler()
{
Expand Down Expand Up @@ -152,6 +154,46 @@
}
}

public string HttpsServerUsage()
{
logger.MethodEntry(LogLevel.Debug);

try
{
var result = GetResource(https_usage_api, new Dictionary<String, String>());
return JsonConvert.DeserializeObject<FortigateResponse<HttpsUsage>>(result).results.AdminServerCert;
}
catch (Exception ex)
{
logger.LogError(FortigateException.FlattenExceptionMessages(ex, $"Error checking https bindings: "));
throw;
}
finally
{
logger.MethodExit(LogLevel.Debug);
}
}

public void UpdateHttpsServerUsage(string alias)
{
logger.MethodEntry(LogLevel.Debug);
HttpUsageRequest request = new HttpUsageRequest() { AdminServerCert = new OriginKey() { QOriginKey = alias } };

try
{
PutAsJson(https_usage_api, request, new Dictionary<string, string>());
}
catch (Exception ex)
{
logger.LogError(FortigateException.FlattenExceptionMessages(ex, $"Error updating https server binding: "));
throw;
}
finally
{
logger.MethodExit(LogLevel.Debug);
}
}

public void Insert(string alias, string cert, string privateKey, bool overwrite, string password = null)
{
logger.MethodEntry(LogLevel.Debug);
Expand All @@ -173,9 +215,10 @@

//check to see if it's in use
existingUsage = Usage(alias, certItem.q_type);
bool existingHttpsUsage = HttpsServerUsage() == alias;

//if it's currently in use
if (existingUsage != null && existingUsage.currently_using != null && existingUsage.currently_using.Length > 0)
if ((existingUsage != null && existingUsage.currently_using != null && existingUsage.currently_using.Length > 0) || existingHttpsUsage)
{
//if newAlias exists, end with error
if (byNewAlias.Length > 0)
Expand All @@ -187,10 +230,18 @@
logger.LogDebug("Inserting alias:" + newAlias);
Insert(newAlias, cert, privateKey, password);

foreach (var existingUsing in existingUsage.currently_using)
if (existingUsage != null && existingUsage.currently_using != null && existingUsage.currently_using.Length > 0)
{
foreach (var existingUsing in existingUsage.currently_using)
{
logger.LogDebug($"Update binding for path/name/attribute {existingUsing.path}/{existingUsing.name}/{existingUsing.attribute} for new alias {newAlias}");
UpdateUsage(newAlias, existingUsing.path, existingUsing.name, existingUsing.attribute);
}
}

if (existingHttpsUsage)
{
logger.LogDebug($"Update binding for path/name/attribute {existingUsing.path}/{existingUsing.name}/{existingUsing.attribute} for new alias {newAlias}");
UpdateUsage(newAlias, existingUsing.path, existingUsing.name, existingUsing.attribute);
UpdateHttpsServerUsage(newAlias);
}

logger.LogDebug("Deleting alias:" + alias);
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ The Fortigate Orchestrator Extension DOES NOT support the following use cases:
5. Certificate enrollment using the internal Fortigate CA (Keyfactor's "reenrollment" or "on device key generation" use case)

\* Because the Fortigate API does not allow for updating certificates in place, and to avoid temporary outages, when replacing local certificates that are bound, it is necessary to create a new name (alias) for the certificate. The new name is created using the first 8 characters of the previous name (larger names truncated due to Fortigate name length constraints) allong with a suffix comprised of "--" and a 15 character hash of the current date/time. The replaced certificate with the old name is then removed from the Fortigate instance. For example, a bound certificate with the name "CertName" would be replaced and the name would then be "CertName--8DD76A97A98E4C1". The existing bindings would remain in place with the new name. At no point during the management job would any of the bound objects be left without a valid certificate binding.
Currently, the ability to renew bound certificates is limited to these binding types:
- The HTTPS server certificate found under Global, System => Settings
- The VPN server certificate found under Root, VPN => SSL-VPN Settings



Expand Down Expand Up @@ -170,7 +173,7 @@ the Keyfactor Command Portal

1. **Download the latest Fortigate Universal Orchestrator extension from GitHub.**

Navigate to the [Fortigate Universal Orchestrator extension GitHub version page](https://github.com/Keyfactor/fortigate-orchestrator/releases/latest). Refer to the compatibility matrix below to determine the asset should be downloaded. Then, click the corresponding asset to download the zip archive.
Navigate to the [Fortigate Universal Orchestrator extension GitHub version page](https://github.com/Keyfactor/fortigate-orchestrator/releases/latest). Refer to the compatibility matrix below to determine whether the `net6.0` or `net8.0` asset should be downloaded. Then, click the corresponding asset to download the zip archive.

| Universal Orchestrator Version | Latest .NET version installed on the Universal Orchestrator server | `rollForward` condition in `Orchestrator.runtimeconfig.json` | `fortigate-orchestrator` .NET version to download |
| --------- | ----------- | ----------- | ----------- |
Expand Down
4 changes: 3 additions & 1 deletion docsource/content.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ The Fortigate Orchestrator Extension DOES NOT support the following use cases:
5. Certificate enrollment using the internal Fortigate CA (Keyfactor's "reenrollment" or "on device key generation" use case)

\* Because the Fortigate API does not allow for updating certificates in place, and to avoid temporary outages, when replacing local certificates that are bound, it is necessary to create a new name (alias) for the certificate. The new name is created using the first 8 characters of the previous name (larger names truncated due to Fortigate name length constraints) allong with a suffix comprised of "--" and a 15 character hash of the current date/time. The replaced certificate with the old name is then removed from the Fortigate instance. For example, a bound certificate with the name "CertName" would be replaced and the name would then be "CertName--8DD76A97A98E4C1". The existing bindings would remain in place with the new name. At no point during the management job would any of the bound objects be left without a valid certificate binding.

Currently, the ability to renew bound certificates is limited to these binding types:
- The HTTPS server certificate found under Global, System => Settings
- The VPN server certificate found under Root, VPN => SSL-VPN Settings

## Requirements

Expand Down
Binary file modified docsource/images/Fortigate-advanced-store-type-dialog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docsource/images/Fortigate-basic-store-type-dialog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docsource/images/Fortigate-custom-fields-store-type-dialog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading