Skip to content
Open
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/[email protected]
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 }}
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
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; }
}
}
4 changes: 2 additions & 2 deletions Fortigate/Fortigate.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<AppendTargetFrameworkToOutputPath>true</AppendTargetFrameworkToOutputPath>
Expand All @@ -8,7 +8,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BouncyCastle.Cryptography" Version="2.0.0" />
<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.2" />
<PackageReference Include="Keyfactor.Logging" Version="1.1.1" />
<PackageReference Include="Keyfactor.Orchestrators.IOrchestratorJobExtensions" Version="0.7.0" />

Expand Down
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 @@ -45,14 +46,15 @@
//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 49 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 49 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 49 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 49 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 update_certificate_api = "/api/v2/cmdb/certificate/local/";

Check warning on line 51 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.update_certificate_api' is assigned but its value is never used

Check warning on line 51 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.update_certificate_api' is assigned but its value is never used

Check warning on line 51 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.update_certificate_api' is assigned but its value is never used

Check warning on line 51 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.update_certificate_api' is assigned but its value is never used

//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 @@ -149,6 +151,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 @@ -170,9 +212,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 @@ -184,10 +227,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
Loading
Loading