Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
a1c23f6
200 day renewal fixes
bhillkeyfactor Apr 7, 2026
ea18abf
Update generated docs
Apr 7, 2026
a742e03
Improved logging .net 10 support
bhillkeyfactor Apr 8, 2026
fba58ac
Removed Template Sync Logic
bhillkeyfactor Apr 8, 2026
58177df
Update generated docs
Apr 8, 2026
b8d74db
fixed template mapping issue
bhillkeyfactor Apr 8, 2026
ddf1330
Merge branch '200dayfixes' of https://github.com/Keyfactor/cscglobal-…
bhillkeyfactor Apr 8, 2026
0b6f8a5
product fixes
bhillkeyfactor Apr 8, 2026
445eb57
Update generated docs
Apr 8, 2026
8f098a9
fixed renewal issue
bhillkeyfactor Apr 8, 2026
77b42cd
documentation fixes
bhillkeyfactor Apr 8, 2026
204367d
Update generated docs
Apr 8, 2026
ff2f4c5
DNS Changes
bhillkeyfactor May 22, 2026
b138670
Update generated docs
May 22, 2026
84d48a8
dns code updates
bhillkeyfactor May 26, 2026
448f167
Update generated docs
May 26, 2026
eb39fcf
change type
bhillkeyfactor May 26, 2026
fe49f01
Merge branch 'feature/dns-plugins' of https://github.com/Keyfactor/cs…
bhillkeyfactor May 26, 2026
3ba367b
Update generated docs
May 26, 2026
65454d0
fixed mismatch
bhillkeyfactor May 26, 2026
0127331
Use 'cname' validation type for CSC CNAME DCV
bhillkeyfactor May 26, 2026
5ea38b4
Update generated docs
May 26, 2026
73f7ddd
added polling to grab cert
bhillkeyfactor May 27, 2026
95e9337
Update generated docs
May 27, 2026
cfcc069
Merge branch 'release-2.0' into feature/dns-plugins
bhillkeyfactor Jul 14, 2026
b016c6c
Update integration-manifest.json
bhillkeyfactor Jul 14, 2026
cc97504
Update CSCGlobalCAPlugin.csproj
bhillkeyfactor Jul 14, 2026
4d9ff86
Update CSCGlobalCAPlugin.csproj
bhillkeyfactor Jul 14, 2026
78f95a3
Update keyfactor-bootstrap-workflow-v3.yml
bhillkeyfactor Jul 14, 2026
979379b
docs: auto-generate README and documentation [skip ci]
github-actions[bot] Jul 14, 2026
a1275f6
Add Enabled CA connection flag
bhillkeyfactor Jul 14, 2026
c034180
docs: auto-generate README and documentation [skip ci]
github-actions[bot] Jul 14, 2026
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 .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"permissions": {
"allow": [
"Bash(git fetch:*)",
"Bash(git checkout:*)"
]
}
}
11 changes: 9 additions & 2 deletions .github/workflows/keyfactor-bootstrap-workflow-v3.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,17 @@ on:

jobs:
call-starter-workflow:
uses: keyfactor/actions/.github/workflows/starter.yml@v3.1.2
uses: keyfactor/actions/.github/workflows/starter.yml@v5
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 }}
564 changes: 335 additions & 229 deletions README.md

Large diffs are not rendered by default.

1,252 changes: 1,102 additions & 150 deletions cscglobal-caplugin/CSCGlobalCAPlugin.cs

Large diffs are not rendered by default.

16 changes: 4 additions & 12 deletions cscglobal-caplugin/CSCGlobalCAPlugin.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<PropertyGroup>
<AppendTargetFrameworkToOutputPath>true</AppendTargetFrameworkToOutputPath>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<TargetFrameworks>net10.0</TargetFrameworks>
<RootNamespace>Keyfactor.Extensions.CAPlugin.CSCGlobal</RootNamespace>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<ImplicitUsings>enable</ImplicitUsings>
Expand All @@ -16,24 +16,16 @@
<Exec Condition="'$(Configuration)'=='DebugAndPush'" Command="PowerShell -ExecutionPolicy Bypass -File &quot;C:\Users\mkachkaev\source\repos\scripts\SyncScriptCSC.ps1&quot;&#xA;" />
</Target>


<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<PackageReference Include="Keyfactor.AnyGateway.IAnyCAPlugin" Version="3.1.0" />
<ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
<PackageReference Include="Keyfactor.AnyGateway.IAnyCAPlugin" Version="3.3.0" />
<PackageReference Include="Keyfactor.PKI" Version="8.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
<PackageReference Include="Keyfactor.AnyGateway.IAnyCAPlugin" Version="3.1.0" />
<PackageReference Include="Keyfactor.PKI" Version="6.3.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
</ItemGroup>


<ItemGroup>
<None Update="manifest.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
</Project>
269 changes: 216 additions & 53 deletions cscglobal-caplugin/Client/CscGlobalClient.cs

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions cscglobal-caplugin/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ namespace Keyfactor.Extensions.CAPlugin.CSCGlobal;

public class Constants
{
public static string Enabled = "Enabled";
public static string CscGlobalUrl = "CscGlobalUrl";
public static string CscGlobalApiKey = "ApiKey";
public static string BearerToken = "BearerToken";
public static string DefaultPageSize = "DefaultPageSize";
public static string TemplateSync = "TemplateSync";
public static string SyncFilterDays = "SyncFilterDays";
public static string RenewalWindowDays = "RenewalWindowDays";
public static string DcvPollTimeoutSeconds = "DcvPollTimeoutSeconds";
}

public class ProductIDs
Expand All @@ -26,8 +28,8 @@ public class ProductIDs
"CSC TrustedSecure UC Certificate",
"CSC TrustedSecure Premium Wildcard Certificate",
"CSC TrustedSecure Domain Validated SSL",
"CSC TrustedSecure Domain Validated Wildcard SSL",
"CSC TrustedSecure Domain Validated UC Certificate"
"CSC Trusted Secure Domain Validated Wildcard SSL",
"CSC Trusted Secure Domain Validated UC Certificate"
};
}

Expand Down
241 changes: 241 additions & 0 deletions cscglobal-caplugin/FlowLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
// 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 System.Diagnostics;
using System.Text;
using Microsoft.Extensions.Logging;

namespace Keyfactor.Extensions.CAPlugin.CSCGlobal;

public enum FlowStepStatus
{
Success,
Failed,
Skipped,
InProgress
}

public class FlowStep
{
public string Name { get; set; }
public FlowStepStatus Status { get; set; }
public string Detail { get; set; }
public long ElapsedMs { get; set; }
public List<FlowStep> Children { get; } = new();
}

/// <summary>
/// Tracks high-level operation flow and renders a visual step diagram to Trace logs.
/// Usage:
/// using var flow = new FlowLogger(logger, "Enroll-New");
/// flow.Step("ParseCSR");
/// flow.Step("ValidateCSR", () => { ... });
/// flow.Fail("CreateOrder", "API returned 400");
/// // flow renders automatically on Dispose
/// </summary>
public sealed class FlowLogger : IDisposable
{
private readonly ILogger _logger;
private readonly string _flowName;
private readonly Stopwatch _totalTimer;
private readonly List<FlowStep> _steps = new();
private FlowStep _currentParent;
private bool _disposed;

public FlowLogger(ILogger logger, string flowName)
{
_logger = logger;
_flowName = flowName;
_totalTimer = Stopwatch.StartNew();
_logger.LogTrace("===== FLOW START: {FlowName} =====", _flowName);
}

/// <summary>Record a completed step.</summary>
public FlowLogger Step(string name, string detail = null)
{
var step = new FlowStep { Name = name, Status = FlowStepStatus.Success, Detail = detail };
AddStep(step);
_logger.LogTrace(" [{FlowName}] {StepName} ... OK{Detail}",
_flowName, name, detail != null ? $" ({detail})" : "");
return this;
}

/// <summary>Record a step that executes an action and times it.</summary>
public FlowLogger Step(string name, Action action, string detail = null)
{
var sw = Stopwatch.StartNew();
var step = new FlowStep { Name = name, Detail = detail };
try
{
_logger.LogTrace(" [{FlowName}] {StepName} ...", _flowName, name);
action();
sw.Stop();
step.Status = FlowStepStatus.Success;
step.ElapsedMs = sw.ElapsedMilliseconds;
AddStep(step);
_logger.LogTrace(" [{FlowName}] {StepName} ... OK ({Elapsed}ms){Detail}",
_flowName, name, sw.ElapsedMilliseconds, detail != null ? $" {detail}" : "");
}
catch (Exception ex)
{
sw.Stop();
step.Status = FlowStepStatus.Failed;
step.ElapsedMs = sw.ElapsedMilliseconds;
step.Detail = ex.Message;
AddStep(step);
_logger.LogTrace(" [{FlowName}] {StepName} ... FAILED ({Elapsed}ms): {Error}",
_flowName, name, sw.ElapsedMilliseconds, ex.Message);
throw;
}
return this;
}

/// <summary>Record an async step that executes and times it.</summary>
public async Task<FlowLogger> StepAsync(string name, Func<Task> action, string detail = null)
{
var sw = Stopwatch.StartNew();
var step = new FlowStep { Name = name, Detail = detail };
try
{
_logger.LogTrace(" [{FlowName}] {StepName} ...", _flowName, name);
await action();
sw.Stop();
step.Status = FlowStepStatus.Success;
step.ElapsedMs = sw.ElapsedMilliseconds;
AddStep(step);
_logger.LogTrace(" [{FlowName}] {StepName} ... OK ({Elapsed}ms){Detail}",
_flowName, name, sw.ElapsedMilliseconds, detail != null ? $" {detail}" : "");
}
catch (Exception ex)
{
sw.Stop();
step.Status = FlowStepStatus.Failed;
step.ElapsedMs = sw.ElapsedMilliseconds;
step.Detail = ex.Message;
AddStep(step);
_logger.LogTrace(" [{FlowName}] {StepName} ... FAILED ({Elapsed}ms): {Error}",
_flowName, name, sw.ElapsedMilliseconds, ex.Message);
throw;
}
return this;
}

/// <summary>Record a failed step without throwing.</summary>
public FlowLogger Fail(string name, string reason = null)
{
var step = new FlowStep { Name = name, Status = FlowStepStatus.Failed, Detail = reason };
AddStep(step);
_logger.LogTrace(" [{FlowName}] {StepName} ... FAILED{Reason}",
_flowName, name, reason != null ? $": {reason}" : "");
return this;
}

/// <summary>Record a skipped step.</summary>
public FlowLogger Skip(string name, string reason = null)
{
var step = new FlowStep { Name = name, Status = FlowStepStatus.Skipped, Detail = reason };
AddStep(step);
_logger.LogTrace(" [{FlowName}] {StepName} ... SKIPPED{Reason}",
_flowName, name, reason != null ? $": {reason}" : "");
return this;
}

/// <summary>Start a branch (group of child steps).</summary>
public FlowLogger Branch(string name)
{
var step = new FlowStep { Name = name, Status = FlowStepStatus.InProgress };
AddStep(step);
_currentParent = step;
_logger.LogTrace(" [{FlowName}] >> Branch: {BranchName}", _flowName, name);
return this;
}

/// <summary>End the current branch.</summary>
public FlowLogger EndBranch()
{
_currentParent = null;
return this;
}

private void AddStep(FlowStep step)
{
if (_currentParent != null)
_currentParent.Children.Add(step);
else
_steps.Add(step);
}

/// <summary>Render the visual flow diagram to Trace log.</summary>
private string RenderFlow()
{
var sb = new StringBuilder();
sb.AppendLine();
sb.AppendLine($" ===== FLOW: {_flowName} ({_totalTimer.ElapsedMilliseconds}ms total) =====");
sb.AppendLine();

for (var i = 0; i < _steps.Count; i++)
{
var step = _steps[i];
var icon = GetStatusIcon(step.Status);
var elapsed = step.ElapsedMs > 0 ? $" ({step.ElapsedMs}ms)" : "";
var detail = !string.IsNullOrEmpty(step.Detail) ? $" [{step.Detail}]" : "";

sb.AppendLine($" {icon} {step.Name}{elapsed}{detail}");

// Render children (branch)
if (step.Children.Count > 0)
{
for (var j = 0; j < step.Children.Count; j++)
{
var child = step.Children[j];
var childIcon = GetStatusIcon(child.Status);
var childElapsed = child.ElapsedMs > 0 ? $" ({child.ElapsedMs}ms)" : "";
var childDetail = !string.IsNullOrEmpty(child.Detail) ? $" [{child.Detail}]" : "";
var connector = j < step.Children.Count - 1 ? "| " : " ";
sb.AppendLine($" |");
sb.AppendLine($" +-- {childIcon} {child.Name}{childElapsed}{childDetail}");
}
}

// Connector between top-level steps
if (i < _steps.Count - 1)
{
sb.AppendLine(" |");
sb.AppendLine(" v");
}
}

sb.AppendLine();

// Final status line
var finalStatus = _steps.Count > 0 && _steps.Last().Status == FlowStepStatus.Failed
? "FAILED" : _steps.Any(s => s.Status == FlowStepStatus.Failed) ? "PARTIAL FAILURE" : "SUCCESS";
sb.AppendLine($" ===== FLOW RESULT: {finalStatus} =====");

return sb.ToString();
}

private static string GetStatusIcon(FlowStepStatus status)
{
return status switch
{
FlowStepStatus.Success => "[OK]",
FlowStepStatus.Failed => "[FAIL]",
FlowStepStatus.Skipped => "[SKIP]",
FlowStepStatus.InProgress => "[...]",
_ => "[?]"
};
}

public void Dispose()
{
if (_disposed) return;
_disposed = true;
_totalTimer.Stop();
_logger.LogTrace(RenderFlow());
}
}
Loading