Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
b828576
feat(http): add a longer timeout for checking commit status
irby Feb 17, 2026
37e37f8
Update generated docs
Feb 17, 2026
cebdfe9
feat: add logic to validate alias length. improve logging
irby Feb 19, 2026
0282804
Update generated docs
Feb 19, 2026
dd6396c
chore(actions): bump starter-workflow to v4
irby Feb 27, 2026
995712e
Update generated docs
Feb 27, 2026
d4b2f5f
chore(docs): format CHANGELOG
irby Feb 27, 2026
5eb2426
Release: 2.5.1
indrora Mar 3, 2026
434747f
Merge 2.5.1 to main (#40)
indrora Mar 16, 2026
b8d667a
feat(tests): add unit tests for inventory
irby Jun 9, 2026
0be5055
feat(tests): add unit tests for management job
irby Jun 9, 2026
70cb737
feat(mgmt): separate template stack, device group commits into mgmt l…
irby Jun 10, 2026
b9ad41c
chore: refactor tests and remove unused functions
irby Jun 10, 2026
2f60fb5
chore: refactor code to be more async, moving the sync blocker to the…
irby Jun 10, 2026
20240f1
chore: refactor, update logging, etc.
irby Jun 10, 2026
b1bae55
Update generated docs
Jun 10, 2026
2e59b98
chore: update docs
irby Jun 10, 2026
d513454
Update generated docs
Jun 10, 2026
6169e52
Merge branch 'release-2.5' into feat/AB#84928/improved-handling-of-de…
irby Jun 10, 2026
91bcfd3
chore(tests): add unit tests around multiple device groups
irby Jun 25, 2026
6b4f555
feat(template_stacks): add support for multiple template stacks
irby Jun 26, 2026
756ff1d
feat: update workflow to fail if config commit fails, and fail if dev…
irby Jul 8, 2026
456fa13
feat(cert_store): add a PushFailureBehavior property to control the j…
irby Jul 9, 2026
1d1e03e
chore(docs): update docs with new property documented, document the d…
irby Jul 9, 2026
1d1bad8
Update generated docs
Jul 9, 2026
0fa49ae
chore: compile .net 10, use v5 workflow
irby Jul 9, 2026
2594d65
docs: auto-generate README and documentation [skip ci]
github-actions[bot] Jul 9, 2026
da7eb9c
chore: update docs
irby Jul 9, 2026
7a6fe04
docs: auto-generate README and documentation [skip ci]
github-actions[bot] Jul 9, 2026
ccebb23
chore(docs): document which versions of PAN-OS have been tested against
irby Jul 13, 2026
09b025e
docs: auto-generate README and documentation [skip ci]
github-actions[bot] Jul 13, 2026
97a7401
fix: pem parsing newline issue
irby Jul 20, 2026
02e7845
docs: auto-generate README and documentation [skip ci]
github-actions[bot] Jul 20, 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
40 changes: 40 additions & 0 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
run-name: Build and Test Solution - ${{ github.sha }}
name: Build and Test Solution

on:
pull_request:
types: [opened, synchronize, reopened]

jobs:
build-and-test-solution:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Setup .NET 6
uses: actions/setup-dotnet@v4
with:
dotnet-version: '6.0.x'

- name: Setup .NET 8
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'

- name: Setup .NET 10
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'

- name: Add Keyfactor NuGet Source
run: dotnet nuget add source https://nuget.pkg.github.com/Keyfactor/index.json -n github -u ${{ github.actor }} -p ${{ secrets.V2BUILDTOKEN }} --store-password-in-clear-text

- name: Restore Dependencies
run: dotnet restore

- name: Build solution
run: dotnet build --no-restore --configuration Release

- name: Run Unit Tests
run: dotnet test --configuration Release --no-build --filter "Category!=Integration"
5 changes: 2 additions & 3 deletions .github/workflows/keyfactor-starter-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ on:

jobs:
call-starter-workflow:
uses: keyfactor/actions/.github/workflows/starter.yml@v3
uses: keyfactor/actions/.github/workflows/starter.yml@v5
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 }}
scan_token: ${{ secrets.SAST_TOKEN }}
42 changes: 31 additions & 11 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,67 @@
2.5.0
# 2.6.0
Features:
- Added a `PushFailureBehavior` store property that controls the job result when Panorama fails
to push to a device group, template, or template stack. Defaults to `Failure`, which triggers
a retry; set to `Warning` to mark the job complete and log the failure instead. All configured
targets are always attempted, even if one fails.
- Added a .NET 10 build target to the release.
- The `TemplateStack` store property now accepts a semicolon-delimited list, allowing a single
management job to push to multiple template stacks.

Fixes:
- The integration now correctly returns `Failure` when committing the running configuration to Panorama fails.
Previously this was reported as `Warning`, which prevented Keyfactor from retrying the job.

# 2.5.1
Features:
- Add validation logic for certificate alias length. If targeting Firewall directly, alias length must be less than 64 characters. If targeting Panorama, alias length must be less than 32 characters. This is to prevent errors when pushing certificates to Palo Alto.
- Increased timeout for checking on job status from 10 minutes to 60 minutes.
- Improved error handling and logging for commit operations, including more detailed error messages when commits fail.

# 2.5.0
Features:
- Add support for multiple Device Groups. You can now specify a comma-delimited list of Device Groups for your Certificate Store. i.e. `Group 1;Group 2;Group 3`.
- Improved support for validating commit changes are successfully pushed from Panorama to Firewall.

2.4.0
# 2.4.0
* .Net 6 and .Net 8 Build Support
* Documentation Updates

2.3.1
# 2.3.1
* Fixed issue where trace logs had extra info in them
* Fixed issue with chain support when pushing certs to palo

2.3.0
# 2.3.0
* Added support for Template Only Commits
* Added support for Template Stack Commits
* Added support for ingoring Trusted Default Certs on inventory to speed up the inventory job

2.2.1
# 2.2.1
* Fixed URL Encoding on Palo Username and Pwd that caused invalid credentials error

2.2.0
# 2.2.0
* Removed support for binding cert to new binding location, can only update certs that are previously bound
* Support for replacing certs on all binding locations both Panorama and Firewalls as long as it was there before
* Support for Virtual Systems on Firewalls, tested with only Azure Virtual Version of Firewall
* Support for Virtual Systems on Panorama Templates

2.1.1
# 2.1.1
* Bug - Add Renew Failure Object Reference Error when Adding/Renewing a cert.

2.1.0
# 2.1.0
* Support for Pan Level Certficates
* Support for Pushing Entire Certificate Chain to Panorama
* Auto Detection of Trusted Root Certificates
* Fix Inventory Check For Private Key from Dummy to Anything

2.0.1
# 2.0.1
* Fix Epoch Time in Model from int to long to prevent inventory errors

2.0.0
# 2.0.0
* Support for Panorama or Firewall connectivity
* Commits changes to the Individual Firewall
* Support for Panorama push to firewalls

1.0.3
# 1.0.3
* Added PAM Support for Orchestrator

42 changes: 35 additions & 7 deletions PaloAlto.IntegrationTests/BaseIntegrationTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2025 Keyfactor
// Copyright 2026 Keyfactor
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -12,20 +12,48 @@
// See the License for the specific language governing permissions and
// limitations under the License.

using Keyfactor.Extensions.Orchestrator.PaloAlto.Factories;
using Keyfactor.Extensions.Orchestrator.PaloAlto.Jobs;
using Keyfactor.Orchestrators.Common.Enums;
using Keyfactor.Orchestrators.Extensions;
using Keyfactor.Orchestrators.Extensions.Interfaces;
using Microsoft.Extensions.Logging;
using MartinCostello.Logging.XUnit;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Newtonsoft.Json;
using PaloAlto.IntegrationTests.Models;
using Xunit;
using Xunit.Abstractions;

namespace PaloAlto.IntegrationTests;

[Trait("Category", "Integration")]
public abstract class BaseIntegrationTest
{
protected readonly string MockCertificatePassword = "sldfklsdfsldjfk";
private readonly IClientLoggerFactory _loggerFactory;
private readonly IPaloAltoClientFactory _clientFactory;

protected BaseIntegrationTest(ITestOutputHelper output)
{
var services = new ServiceCollection()
.AddLogging(b => b
.AddProvider(new XUnitLoggerProvider(output, new XUnitLoggerOptions()))
.SetMinimumLevel(LogLevel.Debug))
.BuildServiceProvider();

var loggerFactory = services.GetRequiredService<ILoggerFactory>();
var loggerFactoryMock = new Mock<IClientLoggerFactory>();

loggerFactoryMock
.Setup(f => f.CreateLogger<It.IsAnyType>())
.Returns(loggerFactory.CreateLogger<It.IsAnyType>());

// Use actual Palo Alto client for integration tests
_clientFactory = new PaloAltoClientFactory(loggerFactoryMock.Object);
_loggerFactory = loggerFactoryMock.Object;
}

protected void AssertJobSuccess(JobResult result, string context)
{
Expand All @@ -35,7 +63,7 @@ protected void AssertJobSuccess(JobResult result, string context)
protected void AssertJobFailure(JobResult result, string expectedError)
{
Assert.Equal(OrchestratorJobStatusJobResult.Failure, result.Result);
Assert.Equal(expectedError, result.FailureMessage);
Assert.Contains(expectedError, result.FailureMessage);
}

protected JobResult ProcessManagementAddJob(TestManagementJobConfigurationProperties props)
Expand All @@ -62,7 +90,7 @@ protected JobResult ProcessInventoryJob(TestInventoryJobConfigurationProperties
mgmtSecretResolver
.Setup(m => m.Resolve(It.Is<string>(s => s == config.ServerPassword)))
.Returns(() => config.ServerPassword);
var inventory = new Inventory(mgmtSecretResolver.Object);
var inventory = new Inventory(mgmtSecretResolver.Object, _clientFactory, _loggerFactory);
return inventory.ProcessJob(config, _ => true);
}

Expand All @@ -75,7 +103,7 @@ private JobResult ProcessManagementJob(ManagementJobConfiguration config)
mgmtSecretResolver
.Setup(m => m.Resolve(It.Is<string>(s => s == config.ServerPassword)))
.Returns(() => config.ServerPassword);
var mgmt = new Management(mgmtSecretResolver.Object);
var mgmt = new Management(mgmtSecretResolver.Object, _clientFactory, _loggerFactory);
return mgmt.ProcessJob(config);
}

Expand All @@ -89,7 +117,7 @@ private ManagementJobConfiguration GetManagementAddJobConfiguration(TestManageme
ClientMachine = "ClientMachineGoesHere",
StorePath = "TemplateNameGoesHere",
StorePassword = null,
Properties = null, // TODO: Fill this out in the next steps
Properties = null, // Properties filled out on a separate step
Type = 105,
},
OperationType = CertStoreOperationType.Add, // 2
Expand Down Expand Up @@ -149,7 +177,7 @@ private ManagementJobConfiguration GetManagementRemoveJobConfiguration(TestManag
ClientMachine = "ClientMachineGoesHere",
StorePath = "TemplateNameGoesHere",
StorePassword = null,
Properties = null, // TODO: Fill this out in the next steps
Properties = null, // Properties filled out on a separate step
Type = 105,
},
OperationType = CertStoreOperationType.Remove, // 3
Expand Down Expand Up @@ -511,7 +539,7 @@ private InventoryJobConfiguration GetInventoryJobConfiguration(TestInventoryJobC
StorePath = "TemplatePathGoesHere",
StorePassword = "",
Type = 105,
Properties = null, // TODO: Fill this out in the next steps
Properties = null, // Properties filled out on a separate step
},
JobCancelled = false,
ServerError = null,
Expand Down
9 changes: 8 additions & 1 deletion PaloAlto.IntegrationTests/InventoryIntegrationTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2025 Keyfactor
// Copyright 2026 Keyfactor
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -12,13 +12,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.

using Keyfactor.Extensions.Orchestrator.PaloAlto.Jobs;
using PaloAlto.IntegrationTests.Models;
using Xunit;
using Xunit.Abstractions;

namespace PaloAlto.IntegrationTests;

public class InventoryIntegrationTests : BaseIntegrationTest
{
public InventoryIntegrationTests(ITestOutputHelper output) : base(output)
{

}

#region Firewall Tests

// Test Case 6 repeats across Management + Inventory. Keeping number in place for parity.
Expand Down
Loading