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
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)

Check warning on line 58 in cscglobal-caplugin/FlowLogger.cs

View workflow job for this annotation

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

Cannot convert null literal to non-nullable reference type.

Check warning on line 58 in cscglobal-caplugin/FlowLogger.cs

View workflow job for this annotation

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

Cannot convert null literal to non-nullable reference type.

Check warning on line 58 in cscglobal-caplugin/FlowLogger.cs

View workflow job for this annotation

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

Cannot convert null literal to non-nullable reference type.
{
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)

Check warning on line 68 in cscglobal-caplugin/FlowLogger.cs

View workflow job for this annotation

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

Cannot convert null literal to non-nullable reference type.

Check warning on line 68 in cscglobal-caplugin/FlowLogger.cs

View workflow job for this annotation

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

Cannot convert null literal to non-nullable reference type.

Check warning on line 68 in cscglobal-caplugin/FlowLogger.cs

View workflow job for this annotation

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

Cannot convert null literal to non-nullable reference type.
{
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)

Check warning on line 98 in cscglobal-caplugin/FlowLogger.cs

View workflow job for this annotation

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

Cannot convert null literal to non-nullable reference type.

Check warning on line 98 in cscglobal-caplugin/FlowLogger.cs

View workflow job for this annotation

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

Cannot convert null literal to non-nullable reference type.

Check warning on line 98 in cscglobal-caplugin/FlowLogger.cs

View workflow job for this annotation

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

Cannot convert null literal to non-nullable reference type.
{
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)

Check warning on line 128 in cscglobal-caplugin/FlowLogger.cs

View workflow job for this annotation

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

Cannot convert null literal to non-nullable reference type.

Check warning on line 128 in cscglobal-caplugin/FlowLogger.cs

View workflow job for this annotation

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

Cannot convert null literal to non-nullable reference type.

Check warning on line 128 in cscglobal-caplugin/FlowLogger.cs

View workflow job for this annotation

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

Cannot convert null literal to non-nullable reference type.
{
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)

Check warning on line 138 in cscglobal-caplugin/FlowLogger.cs

View workflow job for this annotation

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

Cannot convert null literal to non-nullable reference type.

Check warning on line 138 in cscglobal-caplugin/FlowLogger.cs

View workflow job for this annotation

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

Cannot convert null literal to non-nullable reference type.

Check warning on line 138 in cscglobal-caplugin/FlowLogger.cs

View workflow job for this annotation

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

Cannot convert null literal to non-nullable reference type.
{
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
Loading