diff --git a/docs/opc-publisher/commandline.md b/docs/opc-publisher/commandline.md
index 823c94540e..268177509c 100644
--- a/docs/opc-publisher/commandline.md
+++ b/docs/opc-publisher/commandline.md
@@ -18,7 +18,6 @@ When both environment variable and CLI argument are provided, the command line o
╚██████╔╝██║ ╚██████╗ ██║ ╚██████╔╝██████╔╝███████╗██║███████║██║ ██║███████╗██║ ██║
╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
2.9.4 (.NET 8.0.1/win-x64/OPC Stack 1.5.373.3)
-
General
-------
@@ -67,6 +66,11 @@ General
reports its runtime state using a restart
message.
Default: `False` (disabled)
+ --api-key, --ApiKey=VALUE
+ Sets the api key that must be used to authenticate
+ calls on the publisher REST endpoint.
+ Default: `not set` (Key will be generated if not
+ available)
--doa, --disableopenapi, --DisableOpenApiEndpoint[=VALUE]
Disable the OPC Publisher Open API endpoint
exposed by the built-in HTTP server.
diff --git a/src/Azure.IIoT.OpcUa.Publisher.Module/src/Runtime/CommandLine.cs b/src/Azure.IIoT.OpcUa.Publisher.Module/src/Runtime/CommandLine.cs
index 1d48c8eb40..31d7c8a4ca 100644
--- a/src/Azure.IIoT.OpcUa.Publisher.Module/src/Runtime/CommandLine.cs
+++ b/src/Azure.IIoT.OpcUa.Publisher.Module/src/Runtime/CommandLine.cs
@@ -81,6 +81,9 @@ public CommandLine(string[] args, CommandLineLogger? logger = null)
{ $"rs|runtimestatereporting:|{PublisherConfig.EnableRuntimeStateReportingKey}:",
"Enable that when publisher starts or restarts it reports its runtime state using a restart message.\nDefault: `False` (disabled)\n",
(bool? b) => this[PublisherConfig.EnableRuntimeStateReportingKey] = b?.ToString() ?? "True"},
+ { $"api-key=|{PublisherConfig.ApiKeyOverrideKey}=",
+ "Sets the api key that must be used to authenticate calls on the publisher REST endpoint.\nDefault: `not set` (Key will be generated if not available) \n",
+ s => this[PublisherConfig.ApiKeyOverrideKey] = s},
{ $"doa|disableopenapi:|{PublisherConfig.DisableOpenApiEndpointKey}:",
"Disable the OPC Publisher Open API endpoint exposed by the built-in HTTP server.\nDefault: `False` (enabled).\n",
(bool? b) => this[PublisherConfig.DisableOpenApiEndpointKey] = b?.ToString() ?? "True" },
diff --git a/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi.csproj b/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi.csproj
index 06dfa80aba..8f1dfd407c 100644
--- a/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi.csproj
+++ b/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi/src/Azure.IIoT.OpcUa.Publisher.Service.WebApi.csproj
@@ -20,7 +20,7 @@
-
+
diff --git a/src/Azure.IIoT.OpcUa.Publisher/src/Runtime/PublisherConfig.cs b/src/Azure.IIoT.OpcUa.Publisher/src/Runtime/PublisherConfig.cs
index 2abbc0fc56..b2abdffe19 100644
--- a/src/Azure.IIoT.OpcUa.Publisher/src/Runtime/PublisherConfig.cs
+++ b/src/Azure.IIoT.OpcUa.Publisher/src/Runtime/PublisherConfig.cs
@@ -63,6 +63,7 @@ public sealed class PublisherConfig : PostConfigureOptionBase
public const string RenewTlsCertificateOnStartupKey = "RenewTlsCertificateOnStartup";
public const string DefaultTransportKey = "DefaultTransport";
public const string DefaultQualityOfServiceKey = "DefaultQualityOfService";
+ public const string ApiKeyOverrideKey = "ApiKey";
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
///
@@ -380,6 +381,11 @@ public override void PostConfigure(string? name, PublisherOptions options)
}
options.DefaultNamespaceFormat = namespaceFormat;
}
+
+ if (options.ApiKeyOverride == null)
+ {
+ options.ApiKeyOverride = GetStringOrDefault(ApiKeyOverrideKey);
+ }
}
///
diff --git a/src/Azure.IIoT.OpcUa.Publisher/src/Runtime/PublisherOptions.cs b/src/Azure.IIoT.OpcUa.Publisher/src/Runtime/PublisherOptions.cs
index 8094325082..f266529bca 100644
--- a/src/Azure.IIoT.OpcUa.Publisher/src/Runtime/PublisherOptions.cs
+++ b/src/Azure.IIoT.OpcUa.Publisher/src/Runtime/PublisherOptions.cs
@@ -199,5 +199,10 @@ public sealed class PublisherOptions
/// Scale test option
///
public int? ScaleTestCount { get; set; }
+
+ ///
+ /// Allow setting or overriding the current api key
+ ///
+ public string? ApiKeyOverride { get; set; }
}
}
diff --git a/src/Azure.IIoT.OpcUa.Publisher/src/Services/RuntimeStateReporter.cs b/src/Azure.IIoT.OpcUa.Publisher/src/Services/RuntimeStateReporter.cs
index c3c5133ad3..d4947a1c19 100644
--- a/src/Azure.IIoT.OpcUa.Publisher/src/Services/RuntimeStateReporter.cs
+++ b/src/Azure.IIoT.OpcUa.Publisher/src/Services/RuntimeStateReporter.cs
@@ -172,9 +172,21 @@ private async Task UpdateApiKeyAndCertificateAsync()
ApiKey = (string?)apiKeyStore.State[OpcUa.Constants.TwinPropertyApiKeyKey];
_logger.LogInformation("Api Key exists in {Store} store...", apiKeyStore.Name);
}
- else
+
+ if (!string.IsNullOrWhiteSpace(_options.Value.ApiKeyOverride) &&
+ ApiKey != _options.Value.ApiKeyOverride)
+ {
+ Debug.Assert(_stores.Count > 0);
+ _logger.LogInformation("Using Api Key provided in configuration...");
+ ApiKey = _options.Value.ApiKeyOverride;
+
+ _stores[0].State.Add(OpcUa.Constants.TwinPropertyApiKeyKey, ApiKey);
+ }
+
+ if (string.IsNullOrWhiteSpace(ApiKey))
{
Debug.Assert(_stores.Count > 0);
+
_logger.LogInformation("Generating new Api Key in {Store} store...",
_stores[0].Name);
ApiKey = RandomNumberGenerator.GetBytes(20).ToBase64String();