Implement Secrets Management System: Gitea Actions + User-Secrets (AGENTS.md v16.0)
ci / backend (push) Failing after 0s
Build & Test with Secrets / build (push) Failing after 2s
ci / static (push) Failing after 7s
Build & Test with Secrets / security-scan (push) Successful in 5s
ci / frontend (push) Failing after 1m3s
Build & Test with Secrets / frontend (push) Failing after 1m1s
Build & Test with Secrets / notification (push) Failing after 1s
ci / backend (push) Failing after 0s
Build & Test with Secrets / build (push) Failing after 2s
ci / static (push) Failing after 7s
Build & Test with Secrets / security-scan (push) Successful in 5s
ci / frontend (push) Failing after 1m3s
Build & Test with Secrets / frontend (push) Failing after 1m1s
Build & Test with Secrets / notification (push) Failing after 1s
## Changes
### Security Infrastructure
- **Program.cs**: ResolveSecret() helper for secure secret resolution
- Priority: environment variables (CI/CD) → user-secrets (local) → appsettings (fallback)
- Validates all required secrets at startup (fail-fast)
- **ExternalApiOptions.cs**: Type-safe configuration for external APIs
- KRX OpenAPI (Korea Exchange market data)
- OpenDart API (financial disclosures)
- KIS API (trading & orders)
- Injected via IOptions<T> dependency injection
- **appsettings.json**: Safe placeholders (${VAR_NAME}) instead of hardcoded secrets
- Never stores actual credentials
- Production uses environment variable substitution
### CI/CD Integration
- **.gitea/workflows/secrets-injection.yml**: Automated secret injection
- Receives secrets from Gitea Actions Secrets
- Injects as environment variables at build time
- Masks secrets in logs
- No secrets stored in artifacts
### Local Development
- **docs/SECRETS_LOCAL_DEVELOPMENT.md**: Complete setup guide
- One-time user-secrets initialization
- How to store/update secrets locally
- Troubleshooting for common issues
- **SECRETS_CONFIGURATION_SUMMARY.md**: Architecture & security properties
- Secret resolution priority
- Usage patterns in application code
- Security audit checklist
- Rotation procedures
## Security Properties
✅ Secrets never hardcoded in code
✅ Secrets never committed to git
✅ Secrets never logged or exposed in traces
✅ Secrets never stored in CI artifacts
✅ Local isolation via ~/.microsoft/usersecrets/
✅ CI/CD isolation via Gitea Actions Secrets (encrypted)
✅ Rotation support (update secret → next build uses new value)
## Compliance
- Follows AGENTS.md v16.0 security guardrails
- No magic numbers or hardcoded API keys
- All external API keys managed through centralized options
- Type-safe dependency injection eliminates string-based configuration
## Next Steps
1. Local dev: Run `dotnet user-secrets init` and configure
2. CI/CD: Add secrets to Gitea Actions Secrets
3. Verify: `dotnet run` should work without "secret is required" errors
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
namespace KArtSell.Host.Configuration;
|
||||
|
||||
/// <summary>
|
||||
/// External API configuration options (KRX, OpenDart, KIS)
|
||||
/// Secrets are injected at runtime via environment variables or user-secrets.
|
||||
/// </summary>
|
||||
public class ExternalApiOptions
|
||||
{
|
||||
public const string SectionName = "ExternalApis";
|
||||
|
||||
public KrxApiSettings KrxOpenApi { get; set; } = new();
|
||||
public OpenDartApiSettings OpenDart { get; set; } = new();
|
||||
public KisApiSettings Kis { get; set; } = new();
|
||||
|
||||
public class KrxApiSettings
|
||||
{
|
||||
public string ApiKey { get; set; } = string.Empty;
|
||||
public string BaseUrl { get; set; } = "https://openapi.krx.co.kr";
|
||||
}
|
||||
|
||||
public class OpenDartApiSettings
|
||||
{
|
||||
public string ApiKey { get; set; } = string.Empty;
|
||||
public string BaseUrl { get; set; } = "https://opendart.fss.or.kr/api";
|
||||
}
|
||||
|
||||
public class KisApiSettings
|
||||
{
|
||||
public string ApiKey { get; set; } = string.Empty;
|
||||
public string SecretKey { get; set; } = string.Empty;
|
||||
public string BaseUrl { get; set; } = "https://openapivts.koreainvestment.com:29443";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user