6
6
Tests:
7
7
- Retrieval of environment variables with defaults.
8
8
- Handling of missing required environment variables.
9
- - Config validation without exposing secret values.
9
+ - Secure handling of secrets using file-based and environment-based approaches.
10
+ - Validation of critical configuration settings.
11
+ - Proper loading of JWT private and public keys.
12
+ - Ensuring Redis and MongoDB configurations are correctly loaded.
10
13
11
14
Features:
12
15
- Uses `pytest-mock` to override environment variables.
13
- - Mocks private/public key file reads to avoid file system dependencies.
14
- - Ensures secure validation without printing sensitive information.
16
+ - Mocks file reading operations to avoid filesystem dependencies.
17
+ - Ensures security best practices for managing secrets and keys.
18
+ - Validates behavior when secrets are missing or invalid.
15
19
16
20
Author: FOX Techniques <[email protected] >
17
21
"""
18
22
19
23
import pytest
20
24
import os
21
25
from unittest .mock import patch , mock_open
22
- from janux_auth_gateway .config import get_env_variable , Config
26
+ from janux_auth_gateway .config import Config
27
+
28
+ # In your test file
29
+ from janux_auth_gateway .config import _read_secret , _read_jwt_key , _get_env_variable
23
30
24
31
25
32
def test_get_env_variable_with_existing_value (mocker ):
@@ -31,7 +38,7 @@ def test_get_env_variable_with_existing_value(mocker):
31
38
"""
32
39
mocker .patch .dict (os .environ , {"TEST_ENV_VAR" : "test_value" })
33
40
34
- assert get_env_variable ("TEST_ENV_VAR" ) == "test_value"
41
+ assert _get_env_variable ("TEST_ENV_VAR" ) == "test_value"
35
42
36
43
37
44
def test_get_env_variable_with_default_value ():
@@ -41,7 +48,7 @@ def test_get_env_variable_with_default_value():
41
48
Expected Outcome:
42
49
- The function should return the default value if the variable is not set.
43
50
"""
44
- assert get_env_variable ("NON_EXISTENT_VAR" , "default_value" ) == "default_value"
51
+ assert _get_env_variable ("NON_EXISTENT_VAR" , "default_value" ) == "default_value"
45
52
46
53
47
54
def test_get_env_variable_missing_without_default ():
@@ -52,10 +59,10 @@ def test_get_env_variable_missing_without_default():
52
59
- The function should raise a ValueError if no default is provided.
53
60
"""
54
61
with pytest .raises (ValueError , match = "Missing environment variable: 'MISSING_VAR'" ):
55
- get_env_variable ("MISSING_VAR" )
62
+ _get_env_variable ("MISSING_VAR" )
56
63
57
64
58
- @pytest .fixture ()
65
+ @pytest .fixture
59
66
def mock_config (mocker ):
60
67
"""
61
68
Mock the entire Config class properties without exposing secrets.
@@ -65,35 +72,34 @@ def mock_config(mocker):
65
72
{
66
73
"ENVIRONMENT" : "test" ,
67
74
"ALLOWED_ORIGINS" : "http://localhost,http://127.0.0.1" ,
68
- "CONTAINER" : "False" ,
69
- "AUTH_PRIVATE_KEY_PATH" : "/fake/private.pem" ,
70
- "AUTH_PUBLIC_KEY_PATH" : "/fake/public.pem" ,
71
75
"ACCESS_TOKEN_EXPIRE_MINUTES" : "30" ,
72
- "USER_TOKEN_URL" : "http://localhost/token" ,
73
- "ADMIN_TOKEN_URL" : "http://localhost/admin-token" ,
74
- "MONGO_URI" : "mongodb://localhost:27017/test_db" ,
75
- "MONGO_DATABASE_NAME" : "test_db" ,
76
- "ISSUER" : "JANUX-server" ,
77
- "AUDIENCE" : "JANUX-application" ,
78
- "MONGO_ADMIN_EMAIL" :
"[email protected] " ,
79
- "MONGO_ADMIN_PASSWORD" : "adminpassword" ,
80
- "MONGO_ADMIN_FULLNAME" : "Admin User" ,
81
- "MONGO_ADMIN_ROLE" : "super_admin" ,
82
- "MONGO_USER_EMAIL" :
"[email protected] " ,
83
- "MONGO_USER_PASSWORD" : "userpassword" ,
84
- "MONGO_USER_FULLNAME" : "Test User" ,
85
- "MONGO_USER_ROLE" : "user" ,
76
+ "TOKEN_ISSUER" : "JANUX-server" ,
77
+ "TOKEN_AUDIENCE" : "JANUX-application" ,
78
+ "USER_TOKEN_URL" : "/auth/login" ,
79
+ "ADMIN_TOKEN_URL" : "/auth/login" ,
86
80
"REDIS_HOST" : "localhost" ,
87
81
"REDIS_PORT" : "6379" ,
88
82
},
89
83
)
90
84
85
+ # Mock secrets
86
+ mocker .patch (
87
+ "janux_auth_gateway.config._read_secret" ,
88
+ side_effect = lambda key : f"mocked_{ key } " ,
89
+ )
90
+
91
+ # Mock JWT key reading
91
92
fake_private_key = "-----BEGIN PRIVATE KEY-----\n FAKEKEY\n -----END PRIVATE KEY-----"
92
93
fake_public_key = "-----BEGIN PUBLIC KEY-----\n FAKEKEY\n -----END PUBLIC KEY-----"
93
94
94
- mocker .patch ("builtins.open" , mock_open (read_data = fake_private_key ), create = True )
95
- with patch ("builtins.open" , mock_open (read_data = fake_public_key )):
96
- yield
95
+ mocker .patch (
96
+ "janux_auth_gateway.config._read_jwt_key" ,
97
+ side_effect = lambda key_type : (
98
+ fake_private_key if key_type == "private" else fake_public_key
99
+ ),
100
+ )
101
+
102
+ yield
97
103
98
104
99
105
def test_config_validation_success (mock_config ):
@@ -116,10 +122,12 @@ def test_config_validation_failure_invalid_keys(mocker):
116
122
Expected Outcome:
117
123
- Should raise a ValueError if private or public keys are invalid.
118
124
"""
119
- mocker .patch .object (Config , "PRIVATE_KEY " , "INVALID_KEY" )
120
- mocker .patch .object (Config , "PUBLIC_KEY " , "INVALID_KEY" )
125
+ mocker .patch .object (Config , "JWT_PRIVATE_KEY " , "INVALID_KEY" )
126
+ mocker .patch .object (Config , "JWT_PUBLIC_KEY " , "INVALID_KEY" )
121
127
122
- with pytest .raises (ValueError , match = "Invalid configuration for PRIVATE_KEY" ):
128
+ with pytest .raises (
129
+ ValueError , match = "Invalid or missing `jwt_private_key` for signing JWTs."
130
+ ):
123
131
Config .validate ()
124
132
125
133
@@ -128,56 +136,81 @@ def test_config_validation_failure_invalid_mongo_uri(mocker):
128
136
Test that Config.validate() raises an error if MongoDB URI is invalid.
129
137
130
138
Expected Outcome:
131
- - Should raise a ValueError if the MongoDB URI does not start with the expected prefix .
139
+ - Should raise a ValueError if the MongoDB URI is missing .
132
140
"""
133
- mocker .patch .object (Config , "MONGO_URI" , "invalid_uri " )
141
+ mocker .patch .object (Config , "MONGO_URI" , "" )
134
142
135
- with pytest .raises (ValueError , match = "Invalid configuration for MONGO_URI" ):
143
+ with pytest .raises (
144
+ ValueError , match = "Missing `mongo_uri` for database connection."
145
+ ):
136
146
Config .validate ()
137
147
138
148
139
- def test_config_missing_critical_vars (mocker ):
149
+ def test_config_missing_critical_secrets (mocker ):
140
150
"""
141
- Test that Config.validate() raises an error when a required variable is missing.
151
+ Test that Config.validate() raises an error when a required secret is missing.
142
152
143
153
Expected Outcome:
144
- - Should raise a ValueError when a critical variable like PRIVATE_KEY is missing.
154
+ - Should raise a ValueError when a critical secret is missing.
145
155
"""
146
- mocker .patch .object (Config , "PRIVATE_KEY " , "" )
156
+ mocker .patch .object (Config , "JANUX_ENCRYPTION_KEY " , "" )
147
157
148
- with pytest .raises (ValueError , match = "Invalid configuration for PRIVATE_KEY" ):
158
+ with pytest .raises (
159
+ ValueError , match = "Missing `janux_encryption_key` for encryption."
160
+ ):
149
161
Config .validate ()
150
162
151
163
152
- def test_config_redis_connection (mocker ):
164
+ def test_read_secret_from_file (mocker ):
153
165
"""
154
- Test that Redis host and port are set correctly .
166
+ Test that secrets are correctly read from files .
155
167
156
168
Expected Outcome:
157
- - Config should properly set REDIS_HOST and REDIS_PORT .
169
+ - The function should return the secret value from a file .
158
170
"""
159
- mocker . patch . object ( Config , "REDIS_HOST" , "fake_redis_host" )
160
- mocker . patch . object ( Config , "REDIS_PORT" , "6380" )
171
+ secret_value = "mocked_secret_value"
172
+ mock_open_file = mock_open ( read_data = secret_value )
161
173
162
- assert Config .REDIS_HOST == "fake_redis_host"
163
- assert Config .REDIS_PORT == "6380"
174
+ with patch ("builtins.open" , mock_open_file ):
175
+ with patch ("os.path.exists" , return_value = True ):
176
+ assert _read_secret ("test_secret" ) == secret_value
164
177
165
178
166
- def test_config_secure_admin_defaults ( mock_config ):
179
+ def test_read_secret_from_env ( mocker ):
167
180
"""
168
- Test that the default admin role is set correctly .
181
+ Test that secrets are read from environment variables if files are unavailable .
169
182
170
183
Expected Outcome:
171
- - Default admin role should be 'super_admin' .
184
+ - The function should return the secret value from environment variables .
172
185
"""
173
- assert Config .MONGO_ADMIN_ROLE == "super_admin"
186
+ mocker .patch .dict (os .environ , {"test_secret" : "mocked_secret_from_env" })
187
+
188
+ with patch ("os.path.exists" , return_value = False ):
189
+ assert _read_secret ("test_secret" ) == "mocked_secret_from_env"
190
+
191
+
192
+ def test_read_jwt_key_from_file (mocker ):
193
+ """
194
+ Test that JWT keys are correctly read from files.
195
+
196
+ Expected Outcome:
197
+ - The function should return the key content from a file.
198
+ """
199
+ jwt_key_value = "mocked_jwt_key"
200
+ mock_open_file = mock_open (read_data = jwt_key_value )
201
+
202
+ with patch ("builtins.open" , mock_open_file ):
203
+ with patch ("os.path.exists" , return_value = True ):
204
+ assert _read_jwt_key ("private" ) == jwt_key_value
174
205
175
206
176
- def test_config_secure_user_defaults ( mock_config ):
207
+ def test_read_jwt_key_missing ( mocker ):
177
208
"""
178
- Test that the default user role is set correctly .
209
+ Test that a ValueError is raised when no JWT key is found .
179
210
180
211
Expected Outcome:
181
- - Default user role should be 'user' .
212
+ - The function should raise a ValueError if no key file is found .
182
213
"""
183
- assert Config .MONGO_USER_ROLE == "user"
214
+ with patch ("os.path.exists" , return_value = False ):
215
+ with pytest .raises (ValueError , match = "No private key file found" ):
216
+ _read_jwt_key ("private" )
0 commit comments