Переход на использование переменных окружения для секретов
Безопасность: - Секреты (токены JWT, пароль БД) теперь читаются из переменных окружения - Удалены секретные данные из application.yaml - Добавлен .env.example для документации - .env уже в .gitignore Изменения: - Обновлен config.go для загрузки переменных окружения - Добавлена библиотека godotenv для удобной работы с .env - Добавлена валидация обязательных переменных окружения - Поддержка переопределения любых настроек через env Обязательные переменные окружения: - DB_PASSWORD - пароль базы данных - ACCESS_TOKEN_SECRET - секрет для access токенов - REFRESH_TOKEN_SECRET - секрет для refresh токенов Опциональные переопределения: - DB_HOST, DB_PORT, DB_NAME, DB_USER - ACCESS_TOKEN_TTL_MINUTES, REFRESH_TOKEN_TTL_MINUTES - SERVER_PORT Документация: - Добавлен README.md с полной документацией API - Описание структуры проекта - Инструкции по настройке и запуску - Примеры использования API 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -18,6 +21,7 @@ type ServerConfig struct {
|
||||
|
||||
type DatabaseConfig struct {
|
||||
Username string `yaml:"username" json:"username"`
|
||||
Password string // Из переменной окружения, не из YAML
|
||||
Host string `yaml:"host" json:"host"`
|
||||
Port string `yaml:"port" json:"port"`
|
||||
Sslmode string `yaml:"sslmode" json:"sslmode"`
|
||||
@@ -25,8 +29,12 @@ type DatabaseConfig struct {
|
||||
}
|
||||
|
||||
func LoadConfig(absolutePath string) (*Config, error) {
|
||||
// Загружаем .env файл (игнорируем ошибку, если файла нет)
|
||||
_ = godotenv.Load()
|
||||
|
||||
config := &Config{}
|
||||
|
||||
// Читаем базовую конфигурацию из YAML (без секретов)
|
||||
file, err := os.Open(absolutePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -38,5 +46,73 @@ func LoadConfig(absolutePath string) (*Config, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Переопределяем секретные данные из переменных окружения
|
||||
if err := loadFromEnv(config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// loadFromEnv загружает секретные данные из переменных окружения
|
||||
func loadFromEnv(config *Config) error {
|
||||
// Пароль БД (обязательный)
|
||||
dbPassword := os.Getenv("DB_PASSWORD")
|
||||
if dbPassword == "" {
|
||||
return fmt.Errorf("DB_PASSWORD environment variable is required")
|
||||
}
|
||||
config.DB.Password = dbPassword
|
||||
|
||||
// Access Token Secret (обязательный)
|
||||
accessTokenSecret := os.Getenv("ACCESS_TOKEN_SECRET")
|
||||
if accessTokenSecret == "" {
|
||||
return fmt.Errorf("ACCESS_TOKEN_SECRET environment variable is required")
|
||||
}
|
||||
config.Token.AccessToken.SecretWord = accessTokenSecret
|
||||
|
||||
// Refresh Token Secret (обязательный)
|
||||
refreshTokenSecret := os.Getenv("REFRESH_TOKEN_SECRET")
|
||||
if refreshTokenSecret == "" {
|
||||
return fmt.Errorf("REFRESH_TOKEN_SECRET environment variable is required")
|
||||
}
|
||||
config.Token.RefreshToken.SecretWord = refreshTokenSecret
|
||||
|
||||
// Опциональные переопределения (если заданы в env)
|
||||
if accessTTL := os.Getenv("ACCESS_TOKEN_TTL_MINUTES"); accessTTL != "" {
|
||||
ttl, err := strconv.Atoi(accessTTL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid ACCESS_TOKEN_TTL_MINUTES: %w", err)
|
||||
}
|
||||
config.Token.AccessToken.TTLInMinutes = ttl
|
||||
}
|
||||
|
||||
if refreshTTL := os.Getenv("REFRESH_TOKEN_TTL_MINUTES"); refreshTTL != "" {
|
||||
ttl, err := strconv.Atoi(refreshTTL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid REFRESH_TOKEN_TTL_MINUTES: %w", err)
|
||||
}
|
||||
config.Token.RefreshToken.TTLInMinutes = ttl
|
||||
}
|
||||
|
||||
if dbHost := os.Getenv("DB_HOST"); dbHost != "" {
|
||||
config.DB.Host = dbHost
|
||||
}
|
||||
|
||||
if dbPort := os.Getenv("DB_PORT"); dbPort != "" {
|
||||
config.DB.Port = dbPort
|
||||
}
|
||||
|
||||
if dbName := os.Getenv("DB_NAME"); dbName != "" {
|
||||
config.DB.DBname = dbName
|
||||
}
|
||||
|
||||
if dbUser := os.Getenv("DB_USER"); dbUser != "" {
|
||||
config.DB.Username = dbUser
|
||||
}
|
||||
|
||||
if serverPort := os.Getenv("SERVER_PORT"); serverPort != "" {
|
||||
config.Server.Port = serverPort
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user