fix(auth): C2 review — not-found throws (no spurious audit) on update/delete/set-methods, reject empty methods (unusable-key/stealth-disable), richer set-methods response, token advisory to stderr
This commit is contained in:
@@ -122,9 +122,10 @@ public static class SecurityCommands
|
||||
/// <summary>
|
||||
/// Renders the create-key response, surfacing the one-time bearer token prominently —
|
||||
/// it is the only moment the secret is available and cannot be retrieved afterwards.
|
||||
/// The advisory line is written to stderr so that piping stdout captures only the token.
|
||||
/// </summary>
|
||||
/// <param name="json">The JSON success body returned by the management API.</param>
|
||||
private static int PrintCreatedKey(string json)
|
||||
internal static int PrintCreatedKey(string json)
|
||||
{
|
||||
using var doc = System.Text.Json.JsonDocument.Parse(json);
|
||||
var root = doc.RootElement;
|
||||
@@ -133,7 +134,7 @@ public static class SecurityCommands
|
||||
|
||||
Console.WriteLine($"API key created. KeyId: {keyId}");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Save this token now — it will not be shown again:");
|
||||
Console.Error.WriteLine("Save this token now — it will not be shown again:");
|
||||
Console.WriteLine($" {token}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1315,6 +1315,9 @@ public class ManagementActor : ReceiveActor
|
||||
// peppered hash, and assembles the one-time bearer token (sbk_<keyId>_<secret>).
|
||||
// The token is shown to the operator only here, in the create response; it cannot
|
||||
// be retrieved later. No hash/secret is stored or returned by ScadaBridge.
|
||||
if (cmd.Methods is null || cmd.Methods.Count == 0)
|
||||
throw new ManagementCommandException("At least one method must be specified for an API key.");
|
||||
|
||||
var admin = sp.GetRequiredService<IInboundApiKeyAdmin>();
|
||||
var created = await admin.CreateAsync(cmd.Name, cmd.Methods);
|
||||
|
||||
@@ -1333,6 +1336,8 @@ public class ManagementActor : ReceiveActor
|
||||
{
|
||||
var admin = sp.GetRequiredService<IInboundApiKeyAdmin>();
|
||||
var deleted = await admin.DeleteAsync(cmd.KeyId);
|
||||
if (!deleted)
|
||||
throw new ManagementCommandException($"API key '{cmd.KeyId}' not found.");
|
||||
await AuditAsync(sp, user, "Delete", "ApiKey", cmd.KeyId, cmd.KeyId, null);
|
||||
return deleted;
|
||||
}
|
||||
@@ -1757,7 +1762,9 @@ public class ManagementActor : ReceiveActor
|
||||
{
|
||||
// Inbound-API key re-arch (C2): enable/disable via the shared seam (no secret change).
|
||||
var admin = sp.GetRequiredService<IInboundApiKeyAdmin>();
|
||||
await admin.SetEnabledAsync(cmd.KeyId, cmd.IsEnabled);
|
||||
var updated = await admin.SetEnabledAsync(cmd.KeyId, cmd.IsEnabled);
|
||||
if (!updated)
|
||||
throw new ManagementCommandException($"API key '{cmd.KeyId}' not found.");
|
||||
await AuditAsync(sp, user, "Update", "ApiKey", cmd.KeyId, cmd.KeyId,
|
||||
new { cmd.KeyId, cmd.IsEnabled });
|
||||
return new { cmd.KeyId, cmd.IsEnabled };
|
||||
@@ -1767,11 +1774,16 @@ public class ManagementActor : ReceiveActor
|
||||
{
|
||||
// Inbound-API key re-arch (C2): replace a key's method-scope set via the shared seam
|
||||
// (no secret change). The library is authoritative for the scope replacement.
|
||||
if (cmd.Methods is null || cmd.Methods.Count == 0)
|
||||
throw new ManagementCommandException("At least one method must be specified for an API key.");
|
||||
|
||||
var admin = sp.GetRequiredService<IInboundApiKeyAdmin>();
|
||||
var updated = await admin.SetMethodsAsync(cmd.KeyId, cmd.Methods);
|
||||
if (!updated)
|
||||
throw new ManagementCommandException($"API key '{cmd.KeyId}' not found.");
|
||||
await AuditAsync(sp, user, "Update", "ApiKey", cmd.KeyId, cmd.KeyId,
|
||||
new { cmd.KeyId, cmd.Methods });
|
||||
return updated;
|
||||
return new { cmd.KeyId, Methods = cmd.Methods };
|
||||
}
|
||||
|
||||
private static async Task<object?> HandleListScopeRules(IServiceProvider sp, ListScopeRulesCommand cmd)
|
||||
|
||||
Reference in New Issue
Block a user