Skip to main content

secrets-management

Never commit secrets, manage credentials securely using environment variables, vaults, and Hack23 ISMS key management policy

소스 정보

저장소
Hack23/cia
최근 소스 활동
2026년 2월 10일 22:35
감지된 SKILL.md 언어
영어
스타
241
포크
56

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
secrets-management
description
Never commit secrets, manage credentials securely using environment variables, vaults, and Hack23 ISMS key management policy
license
Apache-2.0
# Secrets Management Skill ## Purpose This skill ensures secure handling of sensitive credentials, API keys, database passwords, and cryptographic keys throughout the CIA platform's development and deployment lifecycle. It enforces zero-tolerance for hardcoded secrets and mandates proper secrets management practices. ## When to Use This Skill Apply this skill when: - ✅ Adding new external API integrations (Riksdagen, World Bank) - ✅ Configuring database connections - ✅ Implementing authentication mechanisms - ✅ Setting up CI/CD pipelines - ✅ Deploying to new environments - ✅ Rotating credentials after security incidents - ✅ Reviewing code that handles configuration Do NOT skip for: - ❌ Development/testing credentials (still use proper secrets management) - ❌ "Temporary" hardcoded values (they become permanent) - ❌ Internal-only APIs (still require proper secrets management) ## Golden Rules of Secrets Management ### Rule #1: Never Commit Secrets to Git **ABSOLUTELY FORBIDDEN:** ```java // ❌ NEVER DO THIS - Hardcoded credentials public class DatabaseConfig { private static final String DB_URL = "jdbc:postgresql://prod-db.example.com:5432/cia"; private static final String DB_USERNAME = "admin"; private static final String DB_PASSWORD = "SuperSecret123!"; // SECURITY VIOLATION! } // ❌ NEVER DO THIS - API keys in code public class RiksdagenClient { private static final String API_KEY = "sk_live_abc123def456"; // EXPOSED! } ``` **SECURE ALTERNATIVES:** ```java // ✅ CORRECT - Use environment variables @Configuration public class DatabaseConfig { @Value("${spring.datasource.url}") private String dbUrl; @Value("${spring.datasource.username}") private String dbUsername; @Value("${spring.datasource.password}") private String dbPassword; @Bean public DataSource dataSource() { HikariConfig config = new HikariConfig(); config.setJdbcUrl(dbUrl); config.setUsername(dbUsername); config.setPassword(dbPassword); return new HikariDataSource(config); } } // ✅ CORRECT - API keys from configuration @Service public class RiksdagenClient { private final String apiKey; public RiksdagenClient(@Value("${riksdagen.api.key}") String apiKey) { this.apiKey = apiKey; } } ``` ### Rule #2: Use Environment-Specific Configuration **Application Properties Structure:** ``` src/main/resources/ ├── application.yml # Defaults, no secrets ├── application-dev.yml # Development config ├── application-test.yml # Test config └── application-production.yml # Production config (secrets from env vars) ``` **application.yml (Safe to commit):** ```yaml spring: application: name: citizen-intelligence-agency datasource: # Values from environment variables url: ${DATABASE_URL:jdbc:postgresql://localhost:5432/cia_dev} username: ${DATABASE_USERNAME:cia_user} password: ${DATABASE_PASSWORD} # No default for passwords! jpa: hibernate: ddl-auto: validate show-sql: false riksdagen: api: base-url: https://data.riksdagen.se/api key: ${RIKSDAGEN_API_KEY} # Must be provided via environment worldbank: api: base-url: https://api.worldbank.org/v2 key: ${WORLDBANK_API_KEY:} # Optional, empty default security: jwt: secret: ${JWT_SECRET} # Must be cryptographically random expiration: 86400 # 24 hours in seconds ``` **application-production.yml (Also safe):** ```yaml spring: datasource: # Production settings, but actual values from env vars hikari: maximum-pool-size: 20 minimum-idle: 5 connection-timeout: 30000 logging: level: root: WARN com.hack23.cia: INFO file: name: /var/log/cia/application.log ``` ### Rule #3: Environment Variables in Deployment **Docker Compose (Development):** ```yaml version: '3.8' services: cia-app: image: hack23/cia:latest environment: # Never commit .env file with real secrets DATABASE_URL: ${DATABASE_URL} DATABASE_USERNAME: ${DATABASE_USERNAME} DATABASE_PASSWORD: ${DATABASE_PASSWORD} RIKSDAGEN_API_KEY: ${RIKSDAGEN_API_KEY} JWT_SECRET: ${JWT_SECRET} env_file: - .env # Git-ignored file with secrets ``` **.env.example (Safe to commit as template):** ```bash # CIA Application Secrets # Copy to .env and fill in actual values # NEVER commit .env file! DATABASE_URL=jdbc:postgresql://localhost:5432/cia DATABASE_USERNAME=cia_user DATABASE_PASSWORD=CHANGE_ME RIKSDAGEN_API_KEY=your_api_key_here WORLDBANK_API_KEY=your_api_key_here JWT_SECRET=generate_with_openssl_rand_base64_64 ``` **.gitignore (MUST include):** ```gitignore # Secrets and credentials .env .env.local .env.production *.key *.pem *.p12 *.jks secrets/ credentials/ encrypt.properties # IDE secrets .idea/dataSources.xml .vscode/settings.json ``` ### Rule #4: Secrets Rotation Strategy **Quarterly Rotation Schedule:** ``` Q1: Rotate database passwords Q2: Rotate API keys Q3: Rotate JWT secrets Q4: Rotate encryption keys ``` **Rotation Process:** ```bash # 1. Generate new secret NEW_DB_PASSWORD=$(openssl rand -base64 32) # 2. Update application configuration (zero-downtime) kubectl set env deployment/cia-app DATABASE_PASSWORD=$NEW_DB_PASSWORD # 3. Update database psql -h db.example.com -U admin -c "ALTER USER cia_user PASSWORD '$NEW_DB_PASSWORD';" # 4. Verify application health kubectl rollout status deployment/cia-app # 5. Revoke old secret # (Keep for 24 hours in case of rollback) # 6. Document rotation in change log echo "$(date): Rotated database password" >> /var/log/secrets-rotation.log ``` ## Secrets Detection and Prevention ### Pre-Commit Hooks **Install git-secrets:** ```bash # Install git-secrets brew install git-secrets # macOS # or sudo apt-get install git-secrets # Ubuntu # Setup in repository cd /path/to/cia git secrets --install git secrets --register-aws git secrets --add 'password\s*=\s*["\'][^"\']{8,}["\']' git secrets --add 'apikey\s*=\s*["\'][^"\']{16,}["\']' git secrets --add 'secret\s*=\s*["\'][^"\']{16,}["\']' ``` **Custom Pre-Commit Hook (.git/hooks/pre-commit):** ```bash #!/bin/bash echo "Scanning for secrets..." # Check for common secret patterns if git diff --cached | grep -iE '(password|secret|api_?key|token)\s*[:=]\s*["\047][^"\047]{8,}["\047]'; then echo "❌ ERROR: Potential secret detected in staged files!" echo "Please remove hardcoded secrets and use environment variables." exit 1 fi # Check for specific file types that shouldn't be committed if git diff --cached --name-only | grep -E '\.(key|pem|p12|jks)$'; then echo "❌ ERROR: Attempting to commit key/certificate file!" exit 1 fi # Check for .env files if git diff --cached --name-only | grep -E '^\.env(\.|$)'; then echo "❌ ERROR: Attempting to commit .env file!" exit 1 fi echo "✅ No secrets detected" exit 0 ``` ### GitHub Actions Secret Scanning **.github/workflows/secret-scan.yml:** ```yaml name: Secret Scanning on: push: branches: [ main, develop ] pull_request: branches: [ main ] jobs: gitleaks: name: Gitleaks Secret Scan runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Run Gitleaks uses: gitleaks/gitleaks-action@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} - name: Upload SARIF report if: failure() uses: github/codeql-action/upload-sarif@v3 with: sarif_file: results.sarif trufflehog: name: TruffleHog Secret Scan runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: TruffleHog Scan uses: trufflesecurity/trufflehog@main with: path: ./ base: ${{ github.event.repository.default_branch }} head: HEAD ``` ## Secure Secrets Storage Solutions ### AWS Secrets Manager (Recommended for Production) **Java Integration:** ```java @Configuration public class SecretsManagerConfig { @Bean public SecretsManagerClient secretsManagerClient() { return SecretsManagerClient.builder() .region(Region.EU_WEST_1) .build(); } } @Service public class SecretsService { @Autowired private SecretsManagerClient secretsManager; private final Map<String, String> secretsCache = new ConcurrentHashMap<>(); public String getSecret(String secretName) { return secretsCache.computeIfAbsent(secretName, this::fetchSecret); } private String fetchSecret(String secretName) { GetSecretValueRequest request = GetSecretValueRequest.builder() .secretId(secretName) .build(); GetSecretValueResponse response = secretsManager.getSecretValue(request); return response.secretString(); } // Refresh secrets every hour @Scheduled(fixedRate = 3600000) public void refreshSecrets() { secretsCache.clear(); } } @Configuration public class DatabaseConfigWithSecretsManager { @Autowired private SecretsService secretsService; @Bean public DataSource dataSource() { // Fetch database credentials from Secrets Manager String dbSecret = secretsService.getSecret("cia/production/database"); // Parse JSON secret JSONObject secretJson = new JSONObject(dbSecret); String username = secretJson.getString("username"); String password = secretJson.getString("password"); String host = secretJson.getString("host"); HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:postgresql://" + host + ":5432/cia"); config.setUsername(username); config.setPassword(password); return new HikariDataSource(config); } } ``` **Create Secret in AWS:** ```bash # Create database credentials secret aws secretsmanager create-secret \ --name cia/production/database \ --description "CIA Production Database Credentials" \ --secret-string '{ "username": "cia_prod_user", "password": "GeneratedSecurePassword123!", "host": "cia-prod-db.xyz.eu-west-1.rds.amazonaws.com", "port": "5432", "database": "cia_production" }' # Grant application IAM role access aws secretsmanager put-resource-policy \ --secret-id cia/production/database \ --resource-policy '{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": {"AWS": "arn:aws:iam::123456789:role/cia-app-role"}, "Action": "secretsmanager:GetSecretValue", "Resource": "*" }] }' ``` ### HashiCorp Vault (Alternative) **Java Integration:** ```java @Configuration public class VaultConfig { @Bean public VaultTemplate vaultTemplate() { VaultEndpoint endpoint = VaultEndpoint.create("vault.example.com", 8200); // Use token authentication (token from environment) TokenAuthentication authentication = new TokenAuthentication( System.getenv("VAULT_TOKEN") ); SslConfiguration ssl = SslConfiguration.forTrustStore( KeyStore.getInstance("PKCS12"), "changeit".toCharArray() ); return new VaultTemplate(endpoint, new ClientHttpRequestFactoryFactory().create( new ClientOptions(), ssl), authentication); } } @Service public class VaultSecretsService { @Autowired private VaultTemplate vaultTemplate; public String getDatabasePassword() { VaultResponse response = vaultTemplate .read("secret/data/cia/production/database"); return (String) response.getData().get("password"); } public Map<String, String> getRiksdagenApiConfig() { VaultResponse response = vaultTemplate .read("secret/data/cia/apis/riksdagen"); return response.getData(); } } ``` ### Spring Cloud Config Server (Encrypted Properties) **Config Server Setup:** ```yaml # bootstrap.yml spring: cloud: config: server: git: uri: https://github.com/Hack23/cia-config search-paths: '{application}' encrypt: enabled: true encrypt: key: ${CONFIG_SERVER_ENCRYPTION_KEY} ``` **Encrypted Properties:** ```yaml # cia-production.yml in config repo spring:
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기