secretsloader 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- secretsloader-0.1.0/PKG-INFO +89 -0
- secretsloader-0.1.0/README.md +60 -0
- secretsloader-0.1.0/pyproject.toml +47 -0
- secretsloader-0.1.0/secretsloader.egg-info/PKG-INFO +89 -0
- secretsloader-0.1.0/secretsloader.egg-info/SOURCES.txt +8 -0
- secretsloader-0.1.0/secretsloader.egg-info/dependency_links.txt +1 -0
- secretsloader-0.1.0/secretsloader.egg-info/requires.txt +8 -0
- secretsloader-0.1.0/secretsloader.egg-info/top_level.txt +1 -0
- secretsloader-0.1.0/secretsloader.py +243 -0
- secretsloader-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: secretsloader
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Load secrets from Infisical into environment variables
|
|
5
|
+
Author-email: Welington Souza <welington.souza@mprj.mp.br>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://gitlab-dti.mprj.mp.br/gadg/desenvolvimento/etl/secretsloader.git
|
|
8
|
+
Project-URL: Repository, https://gitlab-dti.mprj.mp.br/gadg/desenvolvimento/etl/secretsloader.git
|
|
9
|
+
Project-URL: Issues, https://gitlab-dti.mprj.mp.br/gadg/desenvolvimento/etl/secretsloader.git/issues
|
|
10
|
+
Keywords: infisical,secrets,environment,configuration
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Requires-Python: >=3.12.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
Requires-Dist: python-dotenv
|
|
23
|
+
Requires-Dist: infisical-python>=2.0.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest; extra == "dev"
|
|
26
|
+
Requires-Dist: ruff; extra == "dev"
|
|
27
|
+
Requires-Dist: build; extra == "dev"
|
|
28
|
+
Requires-Dist: twine; extra == "dev"
|
|
29
|
+
|
|
30
|
+
# secretsloader
|
|
31
|
+
|
|
32
|
+
Pacote para carregamento centralizado de secrets do Infisical em variáveis de ambiente.
|
|
33
|
+
|
|
34
|
+
## Instalação
|
|
35
|
+
|
|
36
|
+
### Usando pip
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install secretsloader
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Usando uv
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
uv add secretsloader
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Usando poetry
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
poetry add secretsloader
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Uso Básico
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from secretsloader import load_secrets
|
|
58
|
+
|
|
59
|
+
# Carregar secrets do Infisical para as variáveis de ambiente
|
|
60
|
+
load_secrets()
|
|
61
|
+
|
|
62
|
+
# Agora você pode acessar os secrets via os.environ
|
|
63
|
+
import os
|
|
64
|
+
|
|
65
|
+
db_password = os.getenv("DB_PASSWORD")
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Configuração
|
|
69
|
+
|
|
70
|
+
Configure as seguintes variáveis de ambiente (pode usar um arquivo `.env`):
|
|
71
|
+
|
|
72
|
+
```env
|
|
73
|
+
INFISICAL_SITE_URL=https://app.infisical.com
|
|
74
|
+
INFISICAL_TOKEN=seu_token_aqui
|
|
75
|
+
INFISICAL_PROJECT_ID=seu_project_id
|
|
76
|
+
INFISICAL_ENVIRONMENT_SLUG=dev
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Funcionalidades
|
|
80
|
+
|
|
81
|
+
- ✅ Carregamento automático de secrets do Infisical
|
|
82
|
+
- ✅ Retry automático em caso de falha
|
|
83
|
+
- ✅ Suporte a cache TTL
|
|
84
|
+
- ✅ Validação de variáveis obrigatórias
|
|
85
|
+
- ✅ Logging detalhado
|
|
86
|
+
|
|
87
|
+
## Documentação Completa
|
|
88
|
+
|
|
89
|
+
Para documentação detalhada, consulte [SECRETSLOADER_DOCUMENTATION.md](SECRETSLOADER_DOCUMENTATION.md)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# secretsloader
|
|
2
|
+
|
|
3
|
+
Pacote para carregamento centralizado de secrets do Infisical em variáveis de ambiente.
|
|
4
|
+
|
|
5
|
+
## Instalação
|
|
6
|
+
|
|
7
|
+
### Usando pip
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install secretsloader
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Usando uv
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
uv add secretsloader
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Usando poetry
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
poetry add secretsloader
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Uso Básico
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from secretsloader import load_secrets
|
|
29
|
+
|
|
30
|
+
# Carregar secrets do Infisical para as variáveis de ambiente
|
|
31
|
+
load_secrets()
|
|
32
|
+
|
|
33
|
+
# Agora você pode acessar os secrets via os.environ
|
|
34
|
+
import os
|
|
35
|
+
|
|
36
|
+
db_password = os.getenv("DB_PASSWORD")
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Configuração
|
|
40
|
+
|
|
41
|
+
Configure as seguintes variáveis de ambiente (pode usar um arquivo `.env`):
|
|
42
|
+
|
|
43
|
+
```env
|
|
44
|
+
INFISICAL_SITE_URL=https://app.infisical.com
|
|
45
|
+
INFISICAL_TOKEN=seu_token_aqui
|
|
46
|
+
INFISICAL_PROJECT_ID=seu_project_id
|
|
47
|
+
INFISICAL_ENVIRONMENT_SLUG=dev
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Funcionalidades
|
|
51
|
+
|
|
52
|
+
- ✅ Carregamento automático de secrets do Infisical
|
|
53
|
+
- ✅ Retry automático em caso de falha
|
|
54
|
+
- ✅ Suporte a cache TTL
|
|
55
|
+
- ✅ Validação de variáveis obrigatórias
|
|
56
|
+
- ✅ Logging detalhado
|
|
57
|
+
|
|
58
|
+
## Documentação Completa
|
|
59
|
+
|
|
60
|
+
Para documentação detalhada, consulte [SECRETSLOADER_DOCUMENTATION.md](SECRETSLOADER_DOCUMENTATION.md)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "secretsloader"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Load secrets from Infisical into environment variables"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.12.10"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Welington Souza", email = "welington.souza@mprj.mp.br"}
|
|
14
|
+
]
|
|
15
|
+
keywords = ["infisical", "secrets", "environment", "configuration"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.8",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
]
|
|
27
|
+
dependencies = [
|
|
28
|
+
"python-dotenv",
|
|
29
|
+
"infisical-python>=2.0.0",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
dev = ["pytest", "ruff", "build", "twine"]
|
|
34
|
+
|
|
35
|
+
[project.urls]
|
|
36
|
+
Homepage = "https://gitlab-dti.mprj.mp.br/gadg/desenvolvimento/etl/secretsloader.git"
|
|
37
|
+
Repository = "https://gitlab-dti.mprj.mp.br/gadg/desenvolvimento/etl/secretsloader.git"
|
|
38
|
+
Issues = "https://gitlab-dti.mprj.mp.br/gadg/desenvolvimento/etl/secretsloader.git/issues"
|
|
39
|
+
|
|
40
|
+
[tool.setuptools]
|
|
41
|
+
py-modules = ["secretsloader"]
|
|
42
|
+
|
|
43
|
+
[dependency-groups]
|
|
44
|
+
dev = [
|
|
45
|
+
"build>=1.4.0",
|
|
46
|
+
"twine>=6.2.0",
|
|
47
|
+
]
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: secretsloader
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Load secrets from Infisical into environment variables
|
|
5
|
+
Author-email: Welington Souza <welington.souza@mprj.mp.br>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://gitlab-dti.mprj.mp.br/gadg/desenvolvimento/etl/secretsloader.git
|
|
8
|
+
Project-URL: Repository, https://gitlab-dti.mprj.mp.br/gadg/desenvolvimento/etl/secretsloader.git
|
|
9
|
+
Project-URL: Issues, https://gitlab-dti.mprj.mp.br/gadg/desenvolvimento/etl/secretsloader.git/issues
|
|
10
|
+
Keywords: infisical,secrets,environment,configuration
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Requires-Python: >=3.12.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
Requires-Dist: python-dotenv
|
|
23
|
+
Requires-Dist: infisical-python>=2.0.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest; extra == "dev"
|
|
26
|
+
Requires-Dist: ruff; extra == "dev"
|
|
27
|
+
Requires-Dist: build; extra == "dev"
|
|
28
|
+
Requires-Dist: twine; extra == "dev"
|
|
29
|
+
|
|
30
|
+
# secretsloader
|
|
31
|
+
|
|
32
|
+
Pacote para carregamento centralizado de secrets do Infisical em variáveis de ambiente.
|
|
33
|
+
|
|
34
|
+
## Instalação
|
|
35
|
+
|
|
36
|
+
### Usando pip
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install secretsloader
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Usando uv
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
uv add secretsloader
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Usando poetry
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
poetry add secretsloader
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Uso Básico
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from secretsloader import load_secrets
|
|
58
|
+
|
|
59
|
+
# Carregar secrets do Infisical para as variáveis de ambiente
|
|
60
|
+
load_secrets()
|
|
61
|
+
|
|
62
|
+
# Agora você pode acessar os secrets via os.environ
|
|
63
|
+
import os
|
|
64
|
+
|
|
65
|
+
db_password = os.getenv("DB_PASSWORD")
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Configuração
|
|
69
|
+
|
|
70
|
+
Configure as seguintes variáveis de ambiente (pode usar um arquivo `.env`):
|
|
71
|
+
|
|
72
|
+
```env
|
|
73
|
+
INFISICAL_SITE_URL=https://app.infisical.com
|
|
74
|
+
INFISICAL_TOKEN=seu_token_aqui
|
|
75
|
+
INFISICAL_PROJECT_ID=seu_project_id
|
|
76
|
+
INFISICAL_ENVIRONMENT_SLUG=dev
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Funcionalidades
|
|
80
|
+
|
|
81
|
+
- ✅ Carregamento automático de secrets do Infisical
|
|
82
|
+
- ✅ Retry automático em caso de falha
|
|
83
|
+
- ✅ Suporte a cache TTL
|
|
84
|
+
- ✅ Validação de variáveis obrigatórias
|
|
85
|
+
- ✅ Logging detalhado
|
|
86
|
+
|
|
87
|
+
## Documentação Completa
|
|
88
|
+
|
|
89
|
+
Para documentação detalhada, consulte [SECRETSLOADER_DOCUMENTATION.md](SECRETSLOADER_DOCUMENTATION.md)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
secretsloader
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Module for loading secrets from Infisical into environment variables.
|
|
3
|
+
|
|
4
|
+
This module provides functionality to fetch secrets from Infisical and inject them
|
|
5
|
+
into the process environment variables, with proper error handling and retry logic.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import logging
|
|
10
|
+
import time
|
|
11
|
+
from typing import Optional, Dict, Any
|
|
12
|
+
from dotenv import load_dotenv
|
|
13
|
+
from infisical_sdk import InfisicalSDKClient
|
|
14
|
+
|
|
15
|
+
load_dotenv()
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
# Flag to ensure secrets are loaded only once
|
|
20
|
+
_secrets_loaded = False
|
|
21
|
+
|
|
22
|
+
# Required environment variables
|
|
23
|
+
REQUIRED_ENV_VARS = [
|
|
24
|
+
"INFISICAL_SITE_URL",
|
|
25
|
+
"INFISICAL_TOKEN",
|
|
26
|
+
"INFISICAL_PROJECT_ID",
|
|
27
|
+
"INFISICAL_ENVIRONMENT_SLUG",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class SecretsLoaderError(Exception):
|
|
32
|
+
"""Base exception for secrets loader errors."""
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class MissingEnvironmentVariableError(SecretsLoaderError):
|
|
37
|
+
"""Raised when required environment variables are missing."""
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class InfisicalConnectionError(SecretsLoaderError):
|
|
42
|
+
"""Raised when connection to Infisical fails."""
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def validate_environment_variables() -> None:
|
|
47
|
+
"""
|
|
48
|
+
Validate that all required environment variables are set.
|
|
49
|
+
|
|
50
|
+
Raises:
|
|
51
|
+
MissingEnvironmentVariableError: If any required environment variable is missing.
|
|
52
|
+
"""
|
|
53
|
+
missing_vars = [var for var in REQUIRED_ENV_VARS if not os.getenv(var)]
|
|
54
|
+
|
|
55
|
+
if missing_vars:
|
|
56
|
+
error_msg = f"Missing required environment variables: {', '.join(missing_vars)}"
|
|
57
|
+
logger.error(error_msg)
|
|
58
|
+
raise MissingEnvironmentVariableError(error_msg)
|
|
59
|
+
|
|
60
|
+
logger.debug("All required environment variables are present")
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def fetch_secrets_from_infisical(
|
|
64
|
+
max_retries: int = 3,
|
|
65
|
+
retry_delay: float = 1.0,
|
|
66
|
+
cache_ttl: Optional[int] = None
|
|
67
|
+
) -> Dict[str, str]:
|
|
68
|
+
"""
|
|
69
|
+
Fetch secrets from Infisical with retry logic.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
max_retries: Maximum number of retry attempts (default: 3)
|
|
73
|
+
retry_delay: Delay in seconds between retries (default: 1.0)
|
|
74
|
+
cache_ttl: Cache TTL in seconds, None to disable caching (default: None)
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
Dictionary mapping secret keys to secret values
|
|
78
|
+
|
|
79
|
+
Raises:
|
|
80
|
+
InfisicalConnectionError: If connection to Infisical fails after all retries
|
|
81
|
+
"""
|
|
82
|
+
last_exception = None
|
|
83
|
+
|
|
84
|
+
for attempt in range(1, max_retries + 1):
|
|
85
|
+
try:
|
|
86
|
+
logger.info(f"Attempting to connect to Infisical (attempt {attempt}/{max_retries})")
|
|
87
|
+
|
|
88
|
+
client = InfisicalSDKClient(
|
|
89
|
+
host=os.getenv("INFISICAL_SITE_URL"),
|
|
90
|
+
token=os.getenv("INFISICAL_TOKEN"),
|
|
91
|
+
cache_ttl=cache_ttl,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
secrets_response = client.secrets.list_secrets(
|
|
95
|
+
project_id=os.getenv("INFISICAL_PROJECT_ID"),
|
|
96
|
+
environment_slug=os.getenv("INFISICAL_ENVIRONMENT_SLUG"),
|
|
97
|
+
secret_path="/",
|
|
98
|
+
).to_dict()
|
|
99
|
+
|
|
100
|
+
secrets_dict = {}
|
|
101
|
+
for secret in secrets_response.get("secrets", []):
|
|
102
|
+
key = secret.get("secretKey")
|
|
103
|
+
value = secret.get("secretValue")
|
|
104
|
+
if key and value is not None:
|
|
105
|
+
secrets_dict[key] = value
|
|
106
|
+
|
|
107
|
+
logger.info(f"Successfully fetched {len(secrets_dict)} secrets from Infisical")
|
|
108
|
+
return secrets_dict
|
|
109
|
+
|
|
110
|
+
except Exception as e:
|
|
111
|
+
last_exception = e
|
|
112
|
+
logger.warning(
|
|
113
|
+
f"Failed to fetch secrets from Infisical (attempt {attempt}/{max_retries}): {e}"
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
if attempt < max_retries:
|
|
117
|
+
logger.info(f"Retrying in {retry_delay} seconds...")
|
|
118
|
+
time.sleep(retry_delay)
|
|
119
|
+
|
|
120
|
+
error_msg = f"Failed to connect to Infisical after {max_retries} attempts"
|
|
121
|
+
logger.error(f"{error_msg}: {last_exception}")
|
|
122
|
+
raise InfisicalConnectionError(error_msg) from last_exception
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def load_secrets(
|
|
126
|
+
override_existing: bool = False,
|
|
127
|
+
max_retries: int = 3,
|
|
128
|
+
retry_delay: float = 1.0,
|
|
129
|
+
cache_ttl: Optional[int] = None,
|
|
130
|
+
force_reload: bool = False
|
|
131
|
+
) -> int:
|
|
132
|
+
"""
|
|
133
|
+
Load secrets from Infisical into environment variables.
|
|
134
|
+
|
|
135
|
+
This function fetches secrets from Infisical and injects them into os.environ.
|
|
136
|
+
By default, it will only load secrets once per process lifetime.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
override_existing: If True, override existing environment variables (default: False)
|
|
140
|
+
max_retries: Maximum number of retry attempts for API calls (default: 3)
|
|
141
|
+
retry_delay: Delay in seconds between retries (default: 1.0)
|
|
142
|
+
cache_ttl: Cache TTL in seconds, None to disable caching (default: None)
|
|
143
|
+
force_reload: If True, bypass the single-load protection (default: False)
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
Number of secrets loaded into environment
|
|
147
|
+
|
|
148
|
+
Raises:
|
|
149
|
+
MissingEnvironmentVariableError: If required environment variables are missing
|
|
150
|
+
InfisicalConnectionError: If connection to Infisical fails
|
|
151
|
+
"""
|
|
152
|
+
global _secrets_loaded
|
|
153
|
+
|
|
154
|
+
if _secrets_loaded and not force_reload:
|
|
155
|
+
logger.info("Secrets already loaded, skipping reload")
|
|
156
|
+
return 0
|
|
157
|
+
|
|
158
|
+
logger.info("Starting secrets loading process")
|
|
159
|
+
|
|
160
|
+
# Validate environment variables
|
|
161
|
+
validate_environment_variables()
|
|
162
|
+
|
|
163
|
+
# Fetch secrets from Infisical
|
|
164
|
+
secrets_dict = fetch_secrets_from_infisical(
|
|
165
|
+
max_retries=max_retries,
|
|
166
|
+
retry_delay=retry_delay,
|
|
167
|
+
cache_ttl=cache_ttl
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
# Load secrets into environment
|
|
171
|
+
loaded_count = 0
|
|
172
|
+
skipped_count = 0
|
|
173
|
+
|
|
174
|
+
for key, value in secrets_dict.items():
|
|
175
|
+
if key in os.environ and not override_existing:
|
|
176
|
+
logger.debug(f"Skipping secret '{key}' (already exists in environment)")
|
|
177
|
+
skipped_count += 1
|
|
178
|
+
else:
|
|
179
|
+
os.environ[key] = value
|
|
180
|
+
loaded_count += 1
|
|
181
|
+
logger.debug(f"Loaded secret '{key}' into environment")
|
|
182
|
+
|
|
183
|
+
_secrets_loaded = True
|
|
184
|
+
|
|
185
|
+
logger.info(
|
|
186
|
+
f"Secrets loading complete: {loaded_count} loaded, {skipped_count} skipped"
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
return loaded_count
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def get_credentials(
|
|
193
|
+
override_existing: bool = False,
|
|
194
|
+
max_retries: int = 3,
|
|
195
|
+
retry_delay: float = 1.0,
|
|
196
|
+
cache_ttl: Optional[int] = None
|
|
197
|
+
) -> None:
|
|
198
|
+
"""
|
|
199
|
+
Legacy function for backward compatibility.
|
|
200
|
+
|
|
201
|
+
Loads secrets from Infisical into environment variables with fallback to local variables.
|
|
202
|
+
This function catches all exceptions and logs warnings instead of raising them.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
override_existing: If True, override existing environment variables (default: False)
|
|
206
|
+
max_retries: Maximum number of retry attempts for API calls (default: 3)
|
|
207
|
+
retry_delay: Delay in seconds between retries (default: 1.0)
|
|
208
|
+
cache_ttl: Cache TTL in seconds, None to disable caching (default: None)
|
|
209
|
+
"""
|
|
210
|
+
try:
|
|
211
|
+
load_secrets(
|
|
212
|
+
override_existing=override_existing,
|
|
213
|
+
max_retries=max_retries,
|
|
214
|
+
retry_delay=retry_delay,
|
|
215
|
+
cache_ttl=cache_ttl
|
|
216
|
+
)
|
|
217
|
+
except Exception as e:
|
|
218
|
+
logger.warning(f"Could not fetch secrets from Infisical: {e}")
|
|
219
|
+
logger.warning("Using local environment variables only")
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
if __name__ == "__main__":
|
|
223
|
+
# Configure logging for CLI usage
|
|
224
|
+
logging.basicConfig(
|
|
225
|
+
level=logging.INFO,
|
|
226
|
+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
try:
|
|
230
|
+
load_secrets()
|
|
231
|
+
# Example: print a specific environment variable
|
|
232
|
+
pg_host = os.environ.get("PG_HOST")
|
|
233
|
+
ora_user = os.environ.get("ORA_USER")
|
|
234
|
+
|
|
235
|
+
if pg_host:
|
|
236
|
+
print(f"PG_HOST: {pg_host}")
|
|
237
|
+
print(f"ORA_USER: {ora_user}")
|
|
238
|
+
|
|
239
|
+
else:
|
|
240
|
+
print("PG_HOST not found in environment")
|
|
241
|
+
except Exception as e:
|
|
242
|
+
logger.error(f"Failed to load secrets: {e}")
|
|
243
|
+
exit(1)
|