[teamai] Push 87 resource(s) from XingfenD
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
# Secrets Management Security Rules
|
||||
|
||||
Hardcoded secrets, credentials, and sensitive data in source code is a major security vulnerability.
|
||||
|
||||
**Rules:**
|
||||
|
||||
1. Secrets MUST be loaded from environment variables or secret managers.
|
||||
2. NEVER commit secrets to VCS.
|
||||
3. `.gitignore` MUST exclude secret files (`.env`, `*.key`, `*.pem`).
|
||||
|
||||
---
|
||||
|
||||
## Hardcoded Secrets and Credentials — Critical
|
||||
|
||||
**Bad:**
|
||||
|
||||
```go
|
||||
const (
|
||||
AWS_ACCESS_KEY = "AKIAIOSFODNN7EXAMPLE" // DON'T
|
||||
AWS_SECRET_KEY = "wJalrXUtnFEMI/K7MDENG" // DON'T
|
||||
DATABASE_PASSWORD = "SuperSecret123!" // DON'T
|
||||
JWT_SECRET = "my-super-secret-jwt-key" // DON'T
|
||||
)
|
||||
|
||||
var config = Config{
|
||||
APIKey: "abc123-xyz789-secret-key", // DON'T
|
||||
Secret: "my-super-secret-value", // DON'T
|
||||
DatabaseURL: "user:passw0rd!@localhost:5432/db", // DON'T
|
||||
}
|
||||
```
|
||||
|
||||
**Good:**
|
||||
|
||||
```go
|
||||
import "os"
|
||||
|
||||
type Config struct {
|
||||
AWSAccessKey string
|
||||
AWSSecretKey string
|
||||
DatabasePassword string
|
||||
JWTSecret string
|
||||
}
|
||||
|
||||
func LoadConfig() (*Config, error) {
|
||||
cfg := &Config{
|
||||
AWSAccessKey: os.Getenv("AWS_ACCESS_KEY_ID"),
|
||||
AWSSecretKey: os.Getenv("AWS_SECRET_ACCESS_KEY"),
|
||||
DatabasePassword: os.Getenv("DATABASE_PASSWORD"),
|
||||
JWTSecret: os.Getenv("JWT_SECRET"),
|
||||
}
|
||||
|
||||
if cfg.JWTSecret == "" {
|
||||
return nil, errors.New("JWT_SECRET is required")
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Hardcoded Database Passwords — Critical
|
||||
|
||||
**Bad:**
|
||||
|
||||
```go
|
||||
// MySQL
|
||||
dsn := "user:Password123!@tcp(localhost:3306)/dbname" // DON'T
|
||||
|
||||
// PostgreSQL
|
||||
dsn := "user=postgres password=P@ssw0rd! dbname=mydb host=localhost" // DON'T
|
||||
```
|
||||
|
||||
**Good:**
|
||||
|
||||
```go
|
||||
// MySQL
|
||||
func connectMySQL() (*sql.DB, error) {
|
||||
user := os.Getenv("DB_USER")
|
||||
password := os.Getenv("DB_PASSWORD")
|
||||
if password == "" {
|
||||
return nil, errors.New("DB_PASSWORD required")
|
||||
}
|
||||
host := getEnvWithDefault("DB_HOST", "localhost")
|
||||
port := getEnvWithDefault("DB_PORT", "3306")
|
||||
addr := net.JoinHostPort(host, port)
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s",
|
||||
user, password, addr, getEnvWithDefault("DB_NAME", "mydb"))
|
||||
return sql.Open("mysql", dsn)
|
||||
}
|
||||
|
||||
// PostgreSQL
|
||||
func connectPostgres() (*sql.DB, error) {
|
||||
connStr := os.Getenv("DATABASE_URL")
|
||||
if connStr == "" {
|
||||
return nil, errors.New("DATABASE_URL required")
|
||||
}
|
||||
return sql.Open("postgres", connStr)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Secrets Storage Best Practices
|
||||
|
||||
### Environment Variables
|
||||
|
||||
```go
|
||||
type EnvSecretLoader struct{}
|
||||
|
||||
func (l *EnvSecretLoader) Load(required []string) (map[string]string, error) {
|
||||
secrets := make(map[string]string)
|
||||
missing := []string{}
|
||||
for _, name := range required {
|
||||
value := os.Getenv(name)
|
||||
if value == "" {
|
||||
missing = append(missing, name)
|
||||
continue
|
||||
}
|
||||
secrets[name] = value
|
||||
}
|
||||
if len(missing) > 0 {
|
||||
return nil, fmt.Errorf("missing: %v", missing)
|
||||
}
|
||||
return secrets, nil
|
||||
}
|
||||
```
|
||||
|
||||
### Secret Managers
|
||||
|
||||
```go
|
||||
type SecretManager interface {
|
||||
GetSecret(name string) (string, error)
|
||||
}
|
||||
|
||||
// AWS Secrets Manager
|
||||
type AWSSecretsManager struct {
|
||||
client *secretsmanager.Client
|
||||
}
|
||||
|
||||
func (m *AWSSecretsManager) GetSecret(name string) (string, error) {
|
||||
result, err := m.client.GetSecretValue(context.TODO(), &secretsmanager.GetSecretValueInput{
|
||||
SecretId: aws.String(name),
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if result.SecretString != nil {
|
||||
return *result.SecretString, nil
|
||||
}
|
||||
return string(result.SecretBinary), nil
|
||||
}
|
||||
```
|
||||
|
||||
### .gitignore Patterns
|
||||
|
||||
```
|
||||
# Secrets
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
*.key
|
||||
*.pem
|
||||
*.p12
|
||||
*.pfx
|
||||
secrets/
|
||||
credentials/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Secret Detection Patterns
|
||||
|
||||
| Pattern | Example |
|
||||
| --------------- | ------------------------------- |
|
||||
| API Keys | `Key = "sk_live_..."` |
|
||||
| Passwords | `password = "..."` |
|
||||
| Tokens | `token = "..."` |
|
||||
| Private Keys | `BEGIN PRIVATE KEY` |
|
||||
| AWS Credentials | `AWS_ACCESS_KEY_ID = "AKIA..."` |
|
||||
| JWT Secrets | `jwtSecret = "..."` |
|
||||
|
||||
---
|
||||
|
||||
## CWE References
|
||||
|
||||
- **CWE-798**: Use of Hard-coded Credentials
|
||||
- **CWE-312**: Cleartext Storage of Sensitive Information
|
||||
- **CWE-532**: Insertion of Sensitive Information into Log File
|
||||
- **CWE-359**: Exposure of Private Personal Information
|
||||
Reference in New Issue
Block a user