Files
confgen/app/tests/test_secrets.py
7000pctAUTO 84172b2d7b
Some checks failed
CI / test (push) Has been cancelled
CI / build (push) Has been cancelled
Add test suite for confgen
2026-02-01 20:51:51 +00:00

140 lines
4.9 KiB
Python

"""Tests for secrets interpolation."""
import os
import pytest
from unittest.mock import patch
from src.confgen.secrets import SecretsResolver
class TestSecretsResolver:
"""Tests for SecretsResolver."""
def setup_method(self):
"""Set up test fixtures."""
self.resolver = SecretsResolver()
def test_resolve_env_var(self):
"""Test resolving environment variable placeholders."""
os.environ["TEST_SECRET"] = "my_secret_value"
content = "password: {{env.TEST_SECRET}}"
result = self.resolver.resolve(content)
assert "password: my_secret_value" in result
del os.environ["TEST_SECRET"]
def test_resolve_multiple_env_vars(self):
"""Test resolving multiple environment variables."""
os.environ["DB_HOST"] = "localhost"
os.environ["DB_PORT"] = "5432"
content = "host: {{env.DB_HOST}}\nport: {{env.DB_PORT}}"
result = self.resolver.resolve(content)
assert "host: localhost" in result
assert "port: 5432" in result
del os.environ["DB_HOST"]
del os.environ["DB_PORT"]
def test_resolve_missing_env_var_raises_error(self):
"""Test that missing environment variable raises an error."""
content = "password: {{env.NONEXISTENT_SECRET}}"
with pytest.raises(ValueError, match="Environment variable 'NONEXISTENT_SECRET' not found"):
self.resolver.resolve(content)
def test_resolve_with_prefixed_env_var(self):
"""Test resolving environment variables with CONFGEN_ prefix."""
os.environ["CONFGEN_MY_SECRET"] = "prefixed_secret"
content = "password: {{env.MY_SECRET}}"
result = self.resolver.resolve(content)
assert "password: prefixed_secret" in result
del os.environ["CONFGEN_MY_SECRET"]
def test_get_secret_names(self):
"""Test extracting secret names from content."""
content = """
password: {{env.DB_PASSWORD}}
api_key: {{env.API_KEY}}
token: {{vault.SECRET_TOKEN}}
"""
names = self.resolver.get_secret_names(content)
assert "DB_PASSWORD" in names
assert "API_KEY" in names
assert "SECRET_TOKEN" in names
def test_is_secret_placeholder(self):
"""Test detecting secret placeholders."""
assert self.resolver.is_secret_placeholder("{{env.SECRET_KEY}}") is True
assert self.resolver.is_secret_placeholder("{{vault.SECRET_KEY}}") is True
assert self.resolver.is_secret_placeholder("{{APP_NAME}}") is False
def test_check_secret_availability(self):
"""Test checking which secrets are available."""
os.environ["AVAILABLE_SECRET"] = "value"
content = "p1: {{env.AVAILABLE_SECRET}}\np2: {{env.UNAVAILABLE_SECRET}}"
availability = self.resolver.check_secret_availability(content)
assert availability["AVAILABLE_SECRET"] is True
assert availability["UNAVAILABLE_SECRET"] is False
del os.environ["AVAILABLE_SECRET"]
def test_resolve_with_no_secrets(self):
"""Test resolving content without secrets."""
content = "app_name: {{APP_NAME}}\nport: {{PORT}}"
variables = {"APP_NAME": "myapp", "PORT": "8080"}
from src.confgen.template import TemplateEngine
engine = TemplateEngine()
result = engine.render(content, variables)
assert result == "app_name: myapp\nport: 8080"
def test_resolve_vault_secret_without_config(self):
"""Test that vault secrets without config raise an error."""
content = "api_key: {{vault.SECRET_API_KEY}}"
with pytest.raises(ValueError, match="Vault not configured"):
self.resolver.resolve(content)
@patch("src.confgen.secrets.SecretsResolver._get_from_vault")
def test_resolve_vault_secret_with_config(self, mock_get):
"""Test resolving vault secrets when configured."""
os.environ["CONFGEN_VAULT_URL"] = "http://localhost:8200"
os.environ["CONFGEN_VAULT_TOKEN"] = "test-token"
mock_get.return_value = "vault_secret_value"
content = "api_key: {{vault.SECRET_API_KEY}}"
result = self.resolver.resolve(content)
assert "api_key: vault_secret_value" in result
del os.environ["CONFGEN_VAULT_URL"]
del os.environ["CONFGEN_VAULT_TOKEN"]
def test_resolve_mixed_placeholders(self):
"""Test resolving mixed variable and secret placeholders."""
os.environ["DB_PASSWORD"] = "secret123"
content = """
app_name: {{APP_NAME}}
database:
host: {{DB_HOST}}
password: {{env.DB_PASSWORD}}
"""
from src.confgen.template import TemplateEngine
engine = TemplateEngine()
resolved = self.resolver.resolve(content)
rendered = engine.render(resolved, {"APP_NAME": "myapp", "DB_HOST": "localhost"})
assert "app_name: myapp" in rendered
assert "host: localhost" in rendered
assert "password: secret123" in rendered
del os.environ["DB_PASSWORD"]