Skip to content

Commit 0a56fa5

Browse files
Manage secrets outside of server_config.json
1 parent 09f27e7 commit 0a56fa5

3 files changed

Lines changed: 50 additions & 3 deletions

File tree

docs/web/server_config.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,15 @@ By default the server will use the value from your host configured by the
115115
## Authentication
116116
For authentication configuration options and which options can be reloaded see
117117
the [Authentication](authentication.md) documentation.
118+
119+
## Secrets
120+
Optionally, one can store sensitive data (e.g., passwords, secret tokens) outside
121+
of `server_config.json`. To do this, create a separate `secrets.json` file
122+
in the server's *workspace* folder. In `server_config.json`, replace sensitive data
123+
with `$SECRET:NAME_OF_SECRET$`.
124+
Then, secrets can be defined in `secrets.json`, as an example:
125+
```json
126+
{
127+
"NAME_OF_SECRET": "MySecurePassword123"
128+
}
129+
```

web/server/codechecker_server/server.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,9 +1127,12 @@ def start_server(config_directory, package_data, port, config_sql_server,
11271127
"created at '%s'", server_cfg_file)
11281128
shutil.copyfile(example_cfg_file, server_cfg_file)
11291129

1130+
secrets_file = os.path.join(config_directory, 'secrets.json')
1131+
11301132
try:
11311133
manager = session_manager.SessionManager(
11321134
server_cfg_file,
1135+
secrets_file,
11331136
force_auth)
11341137

11351138
except IOError as ioerr:
@@ -1138,8 +1141,7 @@ def start_server(config_directory, package_data, port, config_sql_server,
11381141
"is missing or can not be read!")
11391142
sys.exit(1)
11401143
except ValueError as verr:
1141-
LOG.debug(verr)
1142-
LOG.error("The server's configuration file is invalid!")
1144+
LOG.error(verr)
11431145
sys.exit(1)
11441146

11451147
if not skip_db_cleanup:

web/server/codechecker_server/session_manager.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ class SessionManager:
163163
CodeChecker server.
164164
"""
165165

166-
def __init__(self, configuration_file, force_auth=False):
166+
def __init__(self, configuration_file, secrets_file, force_auth=False):
167167
"""
168168
Initialise a new Session Manager on the server.
169169
@@ -176,6 +176,7 @@ def __init__(self, configuration_file, force_auth=False):
176176
self.__logins_since_prune = 0
177177
self.__sessions = []
178178
self.__configuration_file = configuration_file
179+
self.__secrets_file = secrets_file
179180

180181
self.scfg_dict = self.__get_config_dict()
181182

@@ -409,6 +410,38 @@ def __get_config_dict(self):
409410
# have been parsed from it.
410411
raise ValueError("Server configuration file was invalid, or "
411412
"empty.")
413+
414+
LOG.debug(self.__secrets_file)
415+
if os.path.exists(self.__secrets_file):
416+
secrets_dict = load_json(self.__secrets_file, {})
417+
check_file_owner_rw(self.__secrets_file)
418+
else:
419+
secrets_dict = {}
420+
421+
secret_re = re.compile(r'^\$SECRET:[a-zA-Z0-9_-]+\$$')
422+
423+
def resolve_secrets_failed(var):
424+
if not os.path.exists(self.__secrets_file):
425+
LOG.error("Secrets were used in server configuration file, "
426+
f"but {self.__secrets_file} does not exist!")
427+
428+
raise ValueError(f"Secret '{var}' could not "
429+
"be resolved in server configuration file.")
430+
431+
def resolve_secrets(d):
432+
items = d.items() if isinstance(d, dict) else enumerate(d)
433+
434+
for k, v in items:
435+
if isinstance(v, dict) or isinstance(v, list):
436+
resolve_secrets(v)
437+
elif isinstance(v, str) and secret_re.search(v):
438+
secret_var = v.split(':')[1][:-1]
439+
if secret_var in secrets_dict:
440+
d[k] = secrets_dict[secret_var]
441+
else:
442+
resolve_secrets_failed(secret_var)
443+
444+
resolve_secrets(cfg_dict)
412445
return cfg_dict
413446

414447
def reload_config(self):

0 commit comments

Comments
 (0)