Initial commit (history squashed)
This commit is contained in:
21
src/StellaOps.Cryptography/AGENTS.md
Normal file
21
src/StellaOps.Cryptography/AGENTS.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Team 8 — Security Guild (Authority & Shared Crypto)
|
||||
|
||||
## Role
|
||||
|
||||
Team 8 owns the end-to-end security posture for StellaOps Authority and its consumers. That includes password hashing policy, audit/event hygiene, rate-limit & lockout rules, revocation distribution, and sovereign cryptography abstractions that allow alternative algorithm suites (e.g., GOST) without touching feature code.
|
||||
|
||||
## Operational Boundaries
|
||||
|
||||
- Primary workspace: `src/StellaOps.Cryptography`, `src/StellaOps.Authority.Plugin.Standard`, `src/StellaOps.Authority.Storage.Mongo`, and Authority host (`src/StellaOps.Authority/StellaOps.Authority`).
|
||||
- Coordinate cross-module changes via TASKS.md updates and PR descriptions.
|
||||
- Never bypass deterministic behaviour (sorted keys, stable timestamps).
|
||||
- Tests live alongside owning projects (`*.Tests`). Extend goldens instead of rewriting.
|
||||
|
||||
## Expectations
|
||||
|
||||
- Default to Argon2id (Konscious) for password hashing; PBKDF2 only for legacy verification with transparent rehash on success.
|
||||
- Emit structured security events with minimal PII and clear correlation IDs.
|
||||
- Rate-limit `/token` and bootstrap endpoints once CORE8 hooks are available.
|
||||
- Deliver offline revocation bundles signed with detached JWS and provide a verification script.
|
||||
- Maintain `docs/security/authority-threat-model.md` and ensure mitigations are tracked.
|
||||
- All crypto consumption flows through `StellaOps.Cryptography` abstractions to enable sovereign crypto providers.
|
||||
44
src/StellaOps.Cryptography/CryptoProvider.cs
Normal file
44
src/StellaOps.Cryptography/CryptoProvider.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace StellaOps.Cryptography;
|
||||
|
||||
/// <summary>
|
||||
/// High-level cryptographic capabilities supported by StellaOps providers.
|
||||
/// </summary>
|
||||
public enum CryptoCapability
|
||||
{
|
||||
PasswordHashing,
|
||||
Signing,
|
||||
Verification,
|
||||
SymmetricEncryption,
|
||||
KeyDerivation
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifies a stored key or certificate handle.
|
||||
/// </summary>
|
||||
public sealed record CryptoKeyReference(string KeyId, string? ProviderHint = null);
|
||||
|
||||
/// <summary>
|
||||
/// Contract implemented by crypto providers (BCL, CryptoPro, OpenSSL, etc.).
|
||||
/// </summary>
|
||||
public interface ICryptoProvider
|
||||
{
|
||||
string Name { get; }
|
||||
|
||||
bool Supports(CryptoCapability capability, string algorithmId);
|
||||
|
||||
IPasswordHasher GetPasswordHasher(string algorithmId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registry managing provider discovery and policy selection.
|
||||
/// </summary>
|
||||
public interface ICryptoProviderRegistry
|
||||
{
|
||||
IReadOnlyCollection<ICryptoProvider> Providers { get; }
|
||||
|
||||
bool TryResolve(string preferredProvider, out ICryptoProvider provider);
|
||||
|
||||
ICryptoProvider ResolveOrThrow(CryptoCapability capability, string algorithmId);
|
||||
}
|
||||
81
src/StellaOps.Cryptography/PasswordHashing.cs
Normal file
81
src/StellaOps.Cryptography/PasswordHashing.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
|
||||
namespace StellaOps.Cryptography;
|
||||
|
||||
/// <summary>
|
||||
/// Supported password hashing algorithms.
|
||||
/// </summary>
|
||||
public enum PasswordHashAlgorithm
|
||||
{
|
||||
Argon2id,
|
||||
Pbkdf2
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Options describing password hashing requirements.
|
||||
/// Values follow OWASP baseline guidance by default.
|
||||
/// </summary>
|
||||
public sealed record PasswordHashOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithm to use when hashing new passwords.
|
||||
/// </summary>
|
||||
public PasswordHashAlgorithm Algorithm { get; init; } = PasswordHashAlgorithm.Argon2id;
|
||||
|
||||
/// <summary>
|
||||
/// Memory cost in KiB (default 19 MiB).
|
||||
/// </summary>
|
||||
public int MemorySizeInKib { get; init; } = 19 * 1024;
|
||||
|
||||
/// <summary>
|
||||
/// Iteration count / time cost.
|
||||
/// </summary>
|
||||
public int Iterations { get; init; } = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Parallelism / degree of concurrency.
|
||||
/// </summary>
|
||||
public int Parallelism { get; init; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Validates the option values and throws when invalid.
|
||||
/// </summary>
|
||||
public void Validate()
|
||||
{
|
||||
if (MemorySizeInKib <= 0)
|
||||
{
|
||||
throw new InvalidOperationException("Password hashing memory cost must be greater than zero.");
|
||||
}
|
||||
|
||||
if (Iterations <= 0)
|
||||
{
|
||||
throw new InvalidOperationException("Password hashing iteration count must be greater than zero.");
|
||||
}
|
||||
|
||||
if (Parallelism <= 0)
|
||||
{
|
||||
throw new InvalidOperationException("Password hashing parallelism must be greater than zero.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstraction for password hashing implementations.
|
||||
/// </summary>
|
||||
public interface IPasswordHasher
|
||||
{
|
||||
/// <summary>
|
||||
/// Produces an encoded hash for the supplied password.
|
||||
/// </summary>
|
||||
string Hash(string password, PasswordHashOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the supplied password against a stored hash.
|
||||
/// </summary>
|
||||
bool Verify(string password, string encodedHash);
|
||||
|
||||
/// <summary>
|
||||
/// Detects when an existing encoded hash no longer satisfies the desired options.
|
||||
/// </summary>
|
||||
bool NeedsRehash(string encodedHash, PasswordHashOptions desired);
|
||||
}
|
||||
9
src/StellaOps.Cryptography/StellaOps.Cryptography.csproj
Normal file
9
src/StellaOps.Cryptography/StellaOps.Cryptography.csproj
Normal file
@@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
25
src/StellaOps.Cryptography/TASKS.md
Normal file
25
src/StellaOps.Cryptography/TASKS.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Team 8 — Security Guild Task Board (UTC 2025-10-10)
|
||||
|
||||
| ID | Status | Owner | Description | Dependencies | Exit Criteria |
|
||||
|----|--------|-------|-------------|--------------|---------------|
|
||||
| SEC1.A | TODO | Security Guild | Introduce `Argon2idPasswordHasher` backed by Konscious defaults. Wire options into `StandardPluginOptions` (`PasswordHashOptions`) and `StellaOpsAuthorityOptions.Security.PasswordHashing`. | PLG3, CORE3 | ✅ Hashes emit PHC string `$argon2id$v=19$m=19456,t=2,p=1$...`; ✅ `NeedsRehash` promotes PBKDF2 → Argon2; ✅ Integration tests cover tamper, legacy rehash, perf p95 < 250 ms. |
|
||||
| SEC1.B | TODO | Security Guild | Add compile-time switch to enable libsodium/Core variants later (`STELLAOPS_CRYPTO_SODIUM`). Document build variable. | SEC1.A | ✅ Conditional compilation path compiles; ✅ README snippet in `docs/security/password-hashing.md`. |
|
||||
| SEC2.A | TODO | Security Guild + Core | Define audit event contract (`AuthEventRecord`) with subject/client/scope/IP/outcome/correlationId and PII tags. | CORE5–CORE7 | ✅ Contract shipped in `StellaOps.Cryptography` (or shared abstractions); ✅ Docs in `docs/security/audit-events.md`. |
|
||||
| SEC2.B | TODO | Security Guild | Emit audit records from OpenIddict handlers (password + client creds) and bootstrap APIs. Persist via `IAuthorityLoginAttemptStore`. | SEC2.A | ✅ Tests assert three flows (success/failure/lockout); ✅ Serilog output contains correlationId + PII tagging; ✅ Mongo store holds summary rows. |
|
||||
| SEC3.A | BLOCKED (CORE8) | Security Guild + Core | Configure ASP.NET rate limiter (`AddRateLimiter`) with fixed-window policy keyed by IP + `client_id`. Apply to `/token` and `/internal/*`. | CORE8 completion | ✅ Middleware active; ✅ Configurable limits via options; ✅ Integration test hits 429. |
|
||||
| SEC3.B | TODO | Security Guild | Document lockout + rate-limit tuning guidance and escalation thresholds. | SEC3.A | ✅ Section in `docs/security/rate-limits.md`; ✅ Includes SOC alert recommendations. |
|
||||
| SEC4.A | TODO | Security Guild + DevOps | Define revocation JSON schema (`revocation_bundle.schema.json`) and detached JWS workflow. | CORE9, OPS3 | ✅ Schema + sample committed; ✅ CLI command `stellaops auth revoke export` scaffolded with acceptance tests; ✅ Verification script + docs. |
|
||||
| SEC4.B | TODO | Security Guild | Integrate signing keys with crypto provider abstraction (initially ES256 via BCL). | SEC4.A, D5 | ✅ `ICryptoProvider.GetSigner` stub + default BCL signer; ✅ Unit tests verifying signature roundtrip. |
|
||||
| SEC5.A | TODO | Security Guild | Author STRIDE threat model (`docs/security/authority-threat-model.md`) covering token, bootstrap, revocation, CLI, plugin surfaces. | All SEC1–SEC4 in progress | ✅ DFDs + trust boundaries drawn; ✅ Risk table with owners/actions; ✅ Follow-up backlog issues created. |
|
||||
| D5.A | TODO | Security Guild | Flesh out `StellaOps.Cryptography` provider registry, policy, and DI helpers enabling sovereign crypto selection. | SEC1.A, SEC4.B | ✅ `ICryptoProviderRegistry` implementation with provider selection rules; ✅ `StellaOps.Cryptography.DependencyInjection` extensions; ✅ Tests covering fallback ordering. |
|
||||
|
||||
## Notes
|
||||
- Target Argon2 parameters follow OWASP Cheat Sheet (memory ≈ 19 MiB, iterations 2, parallelism 1). Allow overrides via configuration.
|
||||
- When CORE8 lands, pair with Team 2 to expose request context information required by the rate limiter (client_id enrichment).
|
||||
- Revocation bundle must be consumable offline; include issue timestamp, signing key metadata, and reasons.
|
||||
- All crypto usage in Authority code should funnel through the new abstractions (`ICryptoProvider`), enabling future CryptoPro/OpenSSL providers.
|
||||
|
||||
## Done Definition
|
||||
- Code merges include unit/integration tests and documentation updates.
|
||||
- `TASKS.md` status transitions (TODO → DOING → DONE/BLOCKED) must happen in the same PR as the work.
|
||||
- Prior to marking DONE: run `dotnet test` for touched solutions and attach excerpt to PR description.
|
||||
Reference in New Issue
Block a user