feat(auth)!: ScadaBridge retire SQL Server ApiKey entity + ApprovedApiKeyIds + legacy hashing; EF migration RetireInboundApiKeyStore; re-issue runbook + CHANGELOG (re-arch C5/E) — BREAKING: X-API-Key -> Bearer sbk_, keys re-issued
This commit is contained in:
@@ -1,68 +0,0 @@
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Types.InboundApi;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.Commons.Entities.InboundApi;
|
||||
|
||||
/// <summary>
|
||||
/// An inbound-API bearer credential. Per ConfigurationDatabase-012 the plaintext key
|
||||
/// is never persisted: the entity stores only <see cref="KeyHash"/>, a deterministic
|
||||
/// keyed hash of the key (HMAC-SHA256 with a server-side pepper). The plaintext is
|
||||
/// generated at creation, shown to the operator exactly once, and then discarded.
|
||||
/// </summary>
|
||||
public class ApiKey
|
||||
{
|
||||
/// <summary>Database primary key.</summary>
|
||||
public int Id { get; set; }
|
||||
/// <summary>Display name for the API key.</summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Deterministic keyed hash of the API key value. This is the only form of the
|
||||
/// credential persisted; the plaintext key is never stored. Authentication hashes
|
||||
/// the presented candidate with the same scheme and compares against this value.
|
||||
/// </summary>
|
||||
public string KeyHash { get; set; }
|
||||
|
||||
/// <summary>When false, the key is rejected even if the hash matches.</summary>
|
||||
public bool IsEnabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates an API key from a plaintext value, immediately hashing it with the
|
||||
/// unpeppered default hasher (<see cref="ApiKeyHasher.Default"/>) so the entity
|
||||
/// never holds the plaintext. Production code paths that have a configured pepper
|
||||
/// should use <see cref="FromHash(string, string)"/> with a peppered hash instead.
|
||||
/// </summary>
|
||||
/// <param name="name">Display name for the API key.</param>
|
||||
/// <param name="keyValue">Plaintext key value; hashed immediately and never stored.</param>
|
||||
public ApiKey(string name, string keyValue)
|
||||
{
|
||||
Name = name ?? throw new ArgumentNullException(nameof(name));
|
||||
if (keyValue is null) throw new ArgumentNullException(nameof(keyValue));
|
||||
KeyHash = ApiKeyHasher.Default.Hash(keyValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parameterless constructor for the EF Core materializer. Application code uses
|
||||
/// <see cref="ApiKey(string, string)"/> or <see cref="FromHash(string, string)"/>.
|
||||
/// </summary>
|
||||
private ApiKey()
|
||||
{
|
||||
Name = string.Empty;
|
||||
KeyHash = string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an API key from an already-computed key hash. Used by the creation
|
||||
/// path, which generates a random key, hashes it with the configured (peppered)
|
||||
/// <see cref="IApiKeyHasher"/>, and stores only the resulting hash.
|
||||
/// </summary>
|
||||
/// <param name="name">Display name for the API key.</param>
|
||||
/// <param name="keyHash">Pre-computed keyed hash of the API key value.</param>
|
||||
public static ApiKey FromHash(string name, string keyHash)
|
||||
{
|
||||
return new ApiKey
|
||||
{
|
||||
Name = name ?? throw new ArgumentNullException(nameof(name)),
|
||||
KeyHash = keyHash ?? throw new ArgumentNullException(nameof(keyHash)),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,6 @@ public class ApiMethod
|
||||
public string Name { get; set; }
|
||||
/// <summary>Gets or sets the C# script body executed when the method is invoked.</summary>
|
||||
public string Script { get; set; }
|
||||
/// <summary>Gets or sets the JSON-serialised list of API key IDs approved for this method, or <c>null</c> for unrestricted.</summary>
|
||||
public string? ApprovedApiKeyIds { get; set; }
|
||||
/// <summary>Gets or sets the JSON Schema describing the accepted parameters, or <c>null</c> if the method takes no parameters.</summary>
|
||||
public string? ParameterDefinitions { get; set; }
|
||||
/// <summary>Gets or sets the JSON Schema describing the return type, or <c>null</c> if the method returns nothing.</summary>
|
||||
|
||||
Reference in New Issue
Block a user