diff --git a/AxisIPCamera/Client/AxisHttpClient.cs b/AxisIPCamera/Client/AxisHttpClient.cs
index a135476..7f594dc 100644
--- a/AxisIPCamera/Client/AxisHttpClient.cs
+++ b/AxisIPCamera/Client/AxisHttpClient.cs
@@ -232,7 +232,7 @@ public CertificateData ListCertificates()
///
/// Gets the default keystore configured on the device.
///
- /// Keystore Enum
+ /// Keystore struct
public Constants.Keystore GetDefaultKeystore()
{
try
diff --git a/AxisIPCamera/Inventory.cs b/AxisIPCamera/Inventory.cs
index 5b83643..ca579c9 100644
--- a/AxisIPCamera/Inventory.cs
+++ b/AxisIPCamera/Inventory.cs
@@ -8,6 +8,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Text.RegularExpressions;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
@@ -47,7 +48,8 @@ public JobResult ProcessJob(InventoryJobConfiguration config, SubmitInventoryUpd
_logger.MethodEntry();
_logger.LogTrace($"Begin Inventory for Client Machine {config.CertificateStoreDetails.ClientMachine}...");
- _logger.LogDebug($"Inventory Config: {JsonConvert.SerializeObject(config)}");
+ string jsonConfig = JsonConvert.SerializeObject(config);
+ _logger.LogDebug($"Inventory Config: {jsonConfig.Replace(config.ServerPassword,"**********")}");
_logger.LogTrace("Create HTTPS client to connect to device");
var client = new AxisHttpClient(config, config.CertificateStoreDetails, Resolver);
@@ -63,7 +65,7 @@ public JobResult ProcessJob(InventoryJobConfiguration config, SubmitInventoryUpd
// Get the default keystore
_logger.LogTrace("Retrieve the default keystore");
Constants.Keystore defaultKeystore = client.GetDefaultKeystore();
- string defaultKeystoreString = Enum.GetName(typeof(Constants.Keystore), defaultKeystore);
+ string defaultKeystoreString = defaultKeystore.ToString();
_logger.LogDebug($"Inventory - Default keystore: {defaultKeystoreString}");
// Create new list of client certs that are only tied to the default keystore
diff --git a/AxisIPCamera/Management.cs b/AxisIPCamera/Management.cs
index d458123..357e4f3 100644
--- a/AxisIPCamera/Management.cs
+++ b/AxisIPCamera/Management.cs
@@ -77,7 +77,8 @@ public JobResult ProcessJob(ManagementJobConfiguration config)
// to determine if job should overwrite an existing certificate in the store, for example a renewal.
// Retrieve management config from Command
- _logger.LogDebug($"Management Config {JsonConvert.SerializeObject(config)}");
+ string jsonConfig = JsonConvert.SerializeObject(config);
+ _logger.LogDebug($"Management Config: {jsonConfig.Replace(config.ServerPassword,"**********")}");
_logger.LogDebug($"Client Machine: {config.CertificateStoreDetails.ClientMachine}");
// Get needed information from config
diff --git a/AxisIPCamera/Model/Certificate.cs b/AxisIPCamera/Model/Certificate.cs
index 1c3846e..977d8a2 100644
--- a/AxisIPCamera/Model/Certificate.cs
+++ b/AxisIPCamera/Model/Certificate.cs
@@ -28,7 +28,7 @@ public class Certificate
{
[JsonProperty("alias")] public string Alias { get; set; }
[JsonProperty("certificate")] public string CertAsPem { get; set; }
- [JsonProperty("keystore")] public Constants.Keystore Keystore { get; set; }
+ [JsonProperty("keystore")] public Constants.Keystore Keystore { get; init; }
public Constants.CertificateUsage Binding { get; set; } = Constants.CertificateUsage.Other;
}
diff --git a/AxisIPCamera/Model/Constants.cs b/AxisIPCamera/Model/Constants.cs
index fcf276e..2f182e0 100644
--- a/AxisIPCamera/Model/Constants.cs
+++ b/AxisIPCamera/Model/Constants.cs
@@ -7,6 +7,7 @@
using System;
using System.IO;
+using Newtonsoft.Json;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;
@@ -55,11 +56,15 @@ public enum CertificateUsage
Undefined
}
- // ** NOTE: There may be more keystore types depending on the Axis camera model
- public enum Keystore
+ /** NOTE: Keystore IDs are device-specific and not stable across Axis camera models.
+ * New camera/firmware can introduce new Keystore IDs. Cameras can also have multiple
+ * keystores of the same type (i.e. SE0, SE1, TPM0, TPM1, etc.)
+ * Therefore, treat the Keystore ID as an opaque string, not a fixed enum.
+ */
+ [JsonConverter(typeof(KeystoreJsonConverter))]
+ public readonly record struct Keystore(string Value)
{
- TEE0, // Trusted Environment
- SE0 // Secure Element
+ public override string ToString() => Value;
}
public enum ApiType
@@ -212,5 +217,35 @@ public static void ValidateCsr(string csrPem)
throw new Exception($"CSR Validation failed: {ex.Message}");
}
}
+
+ ///
+ /// Custom JSON converter to tell Newtonsoft how to parse the record struct 'Keystore' type.
+ ///
+ private sealed class KeystoreJsonConverter : JsonConverter
+ {
+ public override Keystore ReadJson(
+ JsonReader reader,
+ Type objectType,
+ Keystore existingValue,
+ bool hasExistingValue,
+ JsonSerializer serializer)
+ {
+ if (reader.TokenType == JsonToken.String)
+ {
+ return new Keystore(reader.Value!.ToString()!);
+ }
+
+ throw new JsonSerializationException(
+ $"Unexpected token {reader.TokenType} when parsing Keystore");
+ }
+
+ public override void WriteJson(
+ JsonWriter writer,
+ Keystore value,
+ JsonSerializer serializer)
+ {
+ writer.WriteValue(value.Value);
+ }
+ }
}
}
diff --git a/AxisIPCamera/Reenrollment.cs b/AxisIPCamera/Reenrollment.cs
index 996361c..afd519b 100644
--- a/AxisIPCamera/Reenrollment.cs
+++ b/AxisIPCamera/Reenrollment.cs
@@ -42,7 +42,8 @@ public JobResult ProcessJob(ReenrollmentJobConfiguration config, SubmitReenrollm
_logger.MethodEntry();
_logger.LogTrace($"Begin Reenrollment for Client Machine {config.CertificateStoreDetails.ClientMachine}");
- _logger.LogDebug($"Reenrollment Config: {JsonConvert.SerializeObject(config)}");
+ string jsonConfig = JsonConvert.SerializeObject(config);
+ _logger.LogDebug($"Reenrollment Config: {jsonConfig.Replace(config.ServerPassword,"**********")}");
// Log each key-value pair in the Job Properties for debugging
_logger.LogDebug("Begin Job Properties ---");
@@ -109,7 +110,7 @@ public JobResult ProcessJob(ReenrollmentJobConfiguration config, SubmitReenrollm
// Get the default keystore
_logger.LogTrace("Retrieve the default keystore");
Constants.Keystore defaultKeystore = client.GetDefaultKeystore();
- string defaultKeystoreString = Enum.GetName(typeof(Constants.Keystore), defaultKeystore);
+ string defaultKeystoreString = defaultKeystore.ToString();
_logger.LogDebug($"Reenrollment - Default keystore: {defaultKeystoreString}");
_logger.LogTrace("Generating self-signed cert with private key on device");
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 035dc64..12153e6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+v1.0.2
+- fix(logs): Removed logging of plaintext cert store Server Password
+- fix(keystore): Updated Keystore type to be dynamic instead of a fixed Enum to allow compatibility across different cameras/firmware
+
v1.0.1
- chore(docs): Add screenshots to docs
diff --git a/README.md b/README.md
index 108bece..4e275e1 100644
--- a/README.md
+++ b/README.md
@@ -187,6 +187,37 @@ the Keyfactor Command Portal

+
+ ###### Server Username
+ Enter the username of the configured "service" user on the camera
+
+
+ > [!IMPORTANT]
+ > This field is created by the `Needs Server` on the Basic tab, do not create this field manually.
+
+
+
+
+ ###### Server Password
+ Enter the password of the configured "service" user on the camera
+
+
+ > [!IMPORTANT]
+ > This field is created by the `Needs Server` on the Basic tab, do not create this field manually.
+
+
+
+
+ ###### Use SSL
+ Select True or False depending on if SSL (HTTPS) should be used to communicate with the camera. This should always be "True"
+
+ 
+ 
+
+
+
+
+
##### Entry Parameters Tab
| Name | Display Name | Description | Type | Default Value | Entry has a private key | Adding an entry | Removing an entry | Reenrolling an entry |
@@ -197,21 +228,29 @@ the Keyfactor Command Portal

+
+ ##### Certificate Usage
+ The Certificate Usage to assign to the cert after enrollment. Can be left 'Other' to be assigned later.
+
+ 
+ 
+
+
+
## Installation
1. **Download the latest AXIS IP Camera Universal Orchestrator extension from GitHub.**
- Navigate to the [AXIS IP Camera Universal Orchestrator extension GitHub version page](https://github.com/Keyfactor/axis-ipcamera-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.
+ Navigate to the [AXIS IP Camera Universal Orchestrator extension GitHub version page](https://github.com/Keyfactor/axis-ipcamera-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.
| Universal Orchestrator Version | Latest .NET version installed on the Universal Orchestrator server | `rollForward` condition in `Orchestrator.runtimeconfig.json` | `axis-ipcamera-orchestrator` .NET version to download |
| --------- | ----------- | ----------- | ----------- |
| Older than `11.0.0` | | | `net6.0` |
| Between `11.0.0` and `11.5.1` (inclusive) | `net6.0` | | `net6.0` |
- | Between `11.0.0` and `11.5.1` (inclusive) | `net8.0` | `Disable` | `net6.0` |
- | Between `11.0.0` and `11.5.1` (inclusive) | `net8.0` | `LatestMajor` | `net8.0` |
- | `11.6` _and_ newer | `net8.0` | | `net8.0` |
+ | Between `11.0.0` and `11.5.1` (inclusive) | `net8.0` | `Disable` | `net6.0` || Between `11.0.0` and `11.5.1` (inclusive) | `net8.0` | `LatestMajor` | `net8.0` |
+ | `11.6` _and_ newer | `net8.0` | | `net8.0` |
Unzip the archive containing extension assemblies to a known location.
diff --git a/integration-manifest.json b/integration-manifest.json
index c5f483a..4c1144a 100644
--- a/integration-manifest.json
+++ b/integration-manifest.json
@@ -9,6 +9,7 @@
"update_catalog": true,
"link_github": true,
"description": "The Axis IP Camera Orchestrator Extension is used to inventory, manage Trust certs, and enroll for client certificates that can be bound to endpoints.",
+ "short_description": "The Axis IP Camera Orchestrator Extension is used to inventory, manage Trust certs, and enroll for client certificates that can be bound to endpoints.",
"about": {
"orchestrator": {
"UOFramework": "10.1",
@@ -90,3 +91,4 @@
}
}
}
+