using System;
using System.Collections.Generic;
using System.Linq;
using Opc.Ua;
using Serilog;
namespace ZB.MOM.WW.OtOpcUa.Host.OpcUa
{
///
/// Maps configured security profile names to OPC UA instances.
///
public static class SecurityProfileResolver
{
private static readonly ILogger Log = Serilog.Log.ForContext(typeof(SecurityProfileResolver));
private static readonly Dictionary KnownProfiles =
new(StringComparer.OrdinalIgnoreCase)
{
["None"] = new ServerSecurityPolicy
{
SecurityMode = MessageSecurityMode.None,
SecurityPolicyUri = SecurityPolicies.None
},
["Basic256Sha256-Sign"] = new ServerSecurityPolicy
{
SecurityMode = MessageSecurityMode.Sign,
SecurityPolicyUri = SecurityPolicies.Basic256Sha256
},
["Basic256Sha256-SignAndEncrypt"] = new ServerSecurityPolicy
{
SecurityMode = MessageSecurityMode.SignAndEncrypt,
SecurityPolicyUri = SecurityPolicies.Basic256Sha256
},
["Aes128_Sha256_RsaOaep-Sign"] = new ServerSecurityPolicy
{
SecurityMode = MessageSecurityMode.Sign,
SecurityPolicyUri = SecurityPolicies.Aes128_Sha256_RsaOaep
},
["Aes128_Sha256_RsaOaep-SignAndEncrypt"] = new ServerSecurityPolicy
{
SecurityMode = MessageSecurityMode.SignAndEncrypt,
SecurityPolicyUri = SecurityPolicies.Aes128_Sha256_RsaOaep
},
["Aes256_Sha256_RsaPss-Sign"] = new ServerSecurityPolicy
{
SecurityMode = MessageSecurityMode.Sign,
SecurityPolicyUri = SecurityPolicies.Aes256_Sha256_RsaPss
},
["Aes256_Sha256_RsaPss-SignAndEncrypt"] = new ServerSecurityPolicy
{
SecurityMode = MessageSecurityMode.SignAndEncrypt,
SecurityPolicyUri = SecurityPolicies.Aes256_Sha256_RsaPss
}
};
///
/// Gets the list of valid profile names for validation and documentation.
///
public static IReadOnlyCollection ValidProfileNames => KnownProfiles.Keys.ToList().AsReadOnly();
///
/// Resolves the configured profile names to entries.
/// Unknown names are skipped with a warning. An empty or fully-invalid list falls back to None.
///
/// The profile names from configuration.
/// A deduplicated list of server security policies.
public static List Resolve(IReadOnlyCollection profileNames)
{
var resolved = new List();
var seen = new HashSet(StringComparer.OrdinalIgnoreCase);
foreach (var name in profileNames ?? Array.Empty())
{
if (string.IsNullOrWhiteSpace(name))
continue;
var trimmed = name.Trim();
if (!seen.Add(trimmed))
{
Log.Debug("Skipping duplicate security profile: {Profile}", trimmed);
continue;
}
if (KnownProfiles.TryGetValue(trimmed, out var policy))
resolved.Add(policy);
else
Log.Warning("Unknown security profile '{Profile}' — skipping. Valid profiles: {ValidProfiles}",
trimmed, string.Join(", ", KnownProfiles.Keys));
}
if (resolved.Count == 0)
{
Log.Warning("No valid security profiles configured — falling back to None");
resolved.Add(KnownProfiles["None"]);
}
return resolved;
}
}
}