已开启
bugfux #202
bugfux #202
已开启
zzh创建于 2025年7月14日
共 10 个文件变更+82-38
@@ -13,7 +13,9 @@
13"""Command Line Interface"""13"""Command Line Interface"""
14 14 
15import argparse15import argparse
16+import functools
16import os17import os
18+import psycopg2
17 19 
18from dbmind import components as components_module20from dbmind import components as components_module
19from dbmind.common.exceptions import SetupError, ConfigSettingError21from dbmind.common.exceptions import SetupError, ConfigSettingError
@@ -28,6 +30,9 @@ from . import edbmind
28from . import setup30from . import setup
29 31 
30 32 
33+psycopg2.connect = functools.partial(psycopg2.connect, sslmode='prefer')
34+ 
35+ 
31def build_parser():36def build_parser():
32 actions = ['setup', 'start', 'stop', 'restart', 'reload']37 actions = ['setup', 'start', 'stop', 'restart', 'reload']
33 # Create the top-level parser to parse the common action.38 # Create the top-level parser to parse the common action.
@@ -17,12 +17,12 @@ from dbmind import constants
17from dbmind.cmd.configs.config_constants import (17from dbmind.cmd.configs.config_constants import (
18 ENCRYPTED_SIGNAL, check_config_validity, NULL_TYPE, IV_TABLE18 ENCRYPTED_SIGNAL, check_config_validity, NULL_TYPE, IV_TABLE
19)19)
20-from dbmind.cmd.configs.configurators import ReadonlyConfig, UpdateConfig20+from dbmind.cmd.configs.configurators import ReadonlyConfig, UpdateConfig, create_dynamic_configs, \
21-from dbmind.common import security, utils21+ get_config_security_keys
22+from dbmind.common import security
22from dbmind.common.exceptions import ConfigSettingError23from dbmind.common.exceptions import ConfigSettingError
23from dbmind.common.utils.cli import write_to_terminal24from dbmind.common.utils.cli import write_to_terminal
24from dbmind.metadatabase.dao.dynamic_config import dynamic_config_get, dynamic_config_set25from dbmind.metadatabase.dao.dynamic_config import dynamic_config_get, dynamic_config_set
25-from dbmind.metadatabase.ddl import create_dynamic_config_schema
26 26 
27 27 
28def load_sys_configs(confile):28def load_sys_configs(confile):
@@ -48,8 +48,7 @@ def set_config_parameter(confpath, section: str, option: str, value: str):
48 if 'password' in option:48 if 'password' in option:
49 # dynamic_config_xxx searches file from current working directory.49 # dynamic_config_xxx searches file from current working directory.
50 os.chdir(confpath)50 os.chdir(confpath)
51- s1 = dynamic_config_get(IV_TABLE, 'cipher_s1')51+ s1, s2 = get_config_security_keys(os.path.join(confpath, constants.CIPHER_S1))
52- s2 = dynamic_config_get(IV_TABLE, 'cipher_s2')
53 # Every time a new password is generated, update the IV.52 # Every time a new password is generated, update the IV.
54 iv = security.generate_an_iv()53 iv = security.generate_an_iv()
55 dynamic_config_set(IV_TABLE, '%s-%s' % (section, option), iv)54 dynamic_config_set(IV_TABLE, '%s-%s' % (section, option), iv)
@@ -74,26 +73,6 @@ def set_config_parameter(confpath, section: str, option: str, value: str):
74 write_to_terminal('Success to modify parameter %s-%s.' % (section, option), color='green')73 write_to_terminal('Success to modify parameter %s-%s.' % (section, option), color='green')
75 74 
76 75 
77-def create_dynamic_configs():
78- """Create dynamic configuration schema and
79- generate security keys."""
80- utils.cli.write_to_terminal(
81- 'Starting to generate a dynamic config file...',
82- color='green')
83- create_dynamic_config_schema()
84- s1_ = security.safe_random_string(16)
85- s2_ = security.safe_random_string(16)
86- dynamic_config_set(IV_TABLE, 'cipher_s1', s1_)
87- dynamic_config_set(IV_TABLE, 'cipher_s2', s2_)
88- return s1_, s2_
89- 
90- 
91-def get_config_security_keys():
92- s1 = dynamic_config_get(IV_TABLE, 'cipher_s1')
93- s2 = dynamic_config_get(IV_TABLE, 'cipher_s2')
94- return s1, s2
95- 
96- 
97def config_standardize_null_value(value):76def config_standardize_null_value(value):
98 # If not set default value,77 # If not set default value,
99 # the default value is null.78 # the default value is null.
@@ -19,7 +19,8 @@ from dbmind.cmd.configs.config_constants import (
19 SKIP_LIST, NULL_TYPE, ENCRYPTED_SIGNAL,19 SKIP_LIST, NULL_TYPE, ENCRYPTED_SIGNAL,
20 DBMIND_CONF_HEADER, IV_TABLE,20 DBMIND_CONF_HEADER, IV_TABLE,
21 check_config_validity)21 check_config_validity)
22-from dbmind.common import security22+from dbmind import constants
23+from dbmind.common import security, utils
23from dbmind.common.exceptions import (24from dbmind.common.exceptions import (
24 InvalidCredentialException, ConfigSettingError)25 InvalidCredentialException, ConfigSettingError)
25from dbmind.common.utils import (ExceptionCatcher,26from dbmind.common.utils import (ExceptionCatcher,
@@ -29,6 +30,7 @@ from dbmind.metadatabase.dao.dynamic_config import (
29 dynamic_configs_list, dynamic_category_configs_get)30 dynamic_configs_list, dynamic_category_configs_get)
30 31 
31from .base_configurator import BaseConfig32from .base_configurator import BaseConfig
33+from ...metadatabase.ddl import create_dynamic_config_schema
32 34 
33 35 
34class ReadonlyConfig(BaseConfig):36class ReadonlyConfig(BaseConfig):
@@ -50,6 +52,7 @@ class ReadonlyConfig(BaseConfig):
50 # Otherwise, it will cause the read configuration52 # Otherwise, it will cause the read configuration
51 # items to be wrong.53 # items to be wrong.
52 self._configs = ConfigParser(inline_comment_prefixes='#')54 self._configs = ConfigParser(inline_comment_prefixes='#')
55+ self.conf_dir = os.path.dirname(filepath)
53 with open(file=filepath, mode='r') as fp:56 with open(file=filepath, mode='r') as fp:
54 self._configs.read_file(fp)57 self._configs.read_file(fp)
55 58 
@@ -76,8 +79,7 @@ class ReadonlyConfig(BaseConfig):
76 if value == NULL_TYPE:79 if value == NULL_TYPE:
77 value = ''80 value = ''
78 if 'password' in option and value != '':81 if 'password' in option and value != '':
79- s1 = dynamic_config_get(IV_TABLE, 'cipher_s1')82+ s1, s2 = get_config_security_keys(os.path.join(self.conf_dir, constants.CIPHER_S1))
80- s2 = dynamic_config_get(IV_TABLE, 'cipher_s2')
81 iv = dynamic_config_get(IV_TABLE, '%s-%s' % (section, option))83 iv = dynamic_config_get(IV_TABLE, '%s-%s' % (section, option))
82 if value.startswith(ENCRYPTED_SIGNAL) and iv:84 if value.startswith(ENCRYPTED_SIGNAL) and iv:
83 real_value = value[len(ENCRYPTED_SIGNAL):]85 real_value = value[len(ENCRYPTED_SIGNAL):]
@@ -223,3 +225,25 @@ class DynamicConfig:
223 def get_category_values(category):225 def get_category_values(category):
224 return dynamic_category_configs_get(category)226 return dynamic_category_configs_get(category)
225 227 
228+def create_dynamic_configs(s1_file):
229+ """Create dynamic configuration schema and
230+ generate security keys."""
231+ utils.cli.write_to_terminal(
232+ 'Starting to generate a dynamic config file...',
233+ color='green')
234+ create_dynamic_config_schema()
235+ s1_ = security.safe_random_string(16)
236+ s2_ = security.safe_random_string(16)
237+ with open(s1_file, 'w') as file_h:
238+ file_h.write(s1_)
239+ dynamic_config_set(IV_TABLE, 'cipher_s2', s2_)
240+ return s1_, s2_
241+ 
242+ 
243+def get_config_security_keys(s1_file):
244+ if os.path.exists(s1_file):
245+ s1 = open(s1_file).read()
246+ else:
247+ s1 = dynamic_config_get(IV_TABLE, 'cipher_s1')
248+ s2 = dynamic_config_get(IV_TABLE, 'cipher_s2')
249+ return s1, s2
@@ -12,8 +12,10 @@
12# See the Mulan PSL v2 for more details.12# See the Mulan PSL v2 for more details.
13"""DBMind common functionality interface"""13"""DBMind common functionality interface"""
14 14 
15+import functools
15import logging16import logging
16import os17import os
18+import psycopg2
17import signal19import signal
18import sys20import sys
19import threading21import threading
@@ -316,6 +318,14 @@ class DBMindMain(Daemon):
316 # Initialize TSDB.318 # Initialize TSDB.
317 tsdb = init_tsdb_with_config()319 tsdb = init_tsdb_with_config()
318 320 
321+ # check sslmode for METADATABASE connection
322+ ssl_mode = global_vars.configs.get('METADATABASE', 'ssl_mode', fallback='prefer')
323+ if ssl_mode not in ['disable', 'prefer', 'verify-ca']:
324+ utils.cli.write_to_terminal(f"Error: ssl_mode only support disable or prefer or verify-ca mode."
325+ f" Please make sure the parameters meet the requirements.")
326+ return
327+ psycopg2.connect = functools.partial(psycopg2.connect, sslmode=ssl_mode)
328+ 
319 # Initialize RPC agent.329 # Initialize RPC agent.
320 init_rpc_with_config(tsdb)330 init_rpc_with_config(tsdb)
321 for p in utils.split(global_vars.configs.get('AGENT', 'password')):331 for p in utils.split(global_vars.configs.get('AGENT', 'password')):
@@ -22,13 +22,15 @@ from dbmind.cmd.configs.config_utils import (
22 config_set_value_encrypted_flag,22 config_set_value_encrypted_flag,
23 config_is_encrypted_value,23 config_is_encrypted_value,
24 config_standardize_null_value,24 config_standardize_null_value,
25- get_config_security_keys,25+ set_config_encryption_iv)
26- set_config_encryption_iv,26+from dbmind.cmd.configs.configurators import UpdateConfig, DynamicConfig, GenerationConfig, create_dynamic_configs, \
27- create_dynamic_configs)27+ get_config_security_keys
28-from dbmind.cmd.configs.configurators import UpdateConfig, DynamicConfig, GenerationConfig28+from dbmind.cmd.configs.config_constants import ENCRYPTED_SIGNAL
29from dbmind.common import utils, security29from dbmind.common import utils, security
30from dbmind.common.exceptions import SetupError, SQLExecutionError, DuplicateTableError30from dbmind.common.exceptions import SetupError, SQLExecutionError, DuplicateTableError
31+from dbmind.metadatabase.dao.dynamic_config import dynamic_config_get, dynamic_config_set
31from dbmind.metadatabase.ddl import create_metadatabase_schema, destroy_metadatabase32from dbmind.metadatabase.ddl import create_metadatabase_schema, destroy_metadatabase
33+from dbmind.metadatabase.schema.config_dynamic_params import IV_TABLE
32 34 
33 35 
34def initialize_and_check_config(confpath, interactive=False, quiet=False):36def initialize_and_check_config(confpath, interactive=False, quiet=False):
@@ -43,17 +45,17 @@ def initialize_and_check_config(confpath, interactive=False, quiet=False):
43 45 
44 if not os.path.exists(dynamic_config_path):46 if not os.path.exists(dynamic_config_path):
45 # If dynamic config file does not exist, create a new one.47 # If dynamic config file does not exist, create a new one.
46- s1, s2 = create_dynamic_configs()48+ s1, s2 = create_dynamic_configs(os.path.join(confpath, constants.CIPHER_S1))
47 else:49 else:
48 # If exists, need not create a new dynamic config file50 # If exists, need not create a new dynamic config file
49 # and directly load hash key s1 and s2 from it.51 # and directly load hash key s1 and s2 from it.
50- s1, s2 = get_config_security_keys()52+ s1, s2 = get_config_security_keys(os.path.join(confpath, constants.CIPHER_S1))
51 if not (s1 and s2):53 if not (s1 and s2):
52 # If s1 or s2 is invalid, it indicates that an broken event may occurred while generating54 # If s1 or s2 is invalid, it indicates that an broken event may occurred while generating
53 # the dynamic config file. Hence, the whole process of generation is unreliable and we have to55 # the dynamic config file. Hence, the whole process of generation is unreliable and we have to
54 # generate a new dynamic config file.56 # generate a new dynamic config file.
55 os.unlink(dynamic_config_path)57 os.unlink(dynamic_config_path)
56- s1, s2 = create_dynamic_configs()58+ s1, s2 = create_dynamic_configs(os.path.join(confpath, constants.CIPHER_S1))
57 59 
58 # Check some configurations and encrypt passwords.60 # Check some configurations and encrypt passwords.
59 with UpdateConfig(dbmind_conf_path) as config:61 with UpdateConfig(dbmind_conf_path) as config:
@@ -151,6 +153,16 @@ def setup_directory_interactive(confpath):
151 )153 )
152 utils.base.chmod_r(confpath, 0o700, 0o600)154 utils.base.chmod_r(confpath, 0o700, 0o600)
153 155 
156+ os.chdir(confpath)
157+ dynamic_config_path = os.path.join(confpath, constants.DYNAMIC_CONFIG)
158+ if not os.path.exists(dynamic_config_path):
159+ create_dynamic_configs(os.path.join(confpath, constants.CIPHER_S1))
160+ else:
161+ s1, s2 = get_config_security_keys(os.path.join(confpath, constants.CIPHER_S1))
162+ if not (s1 and s2):
163+ os.unlink(dynamic_config_path)
164+ create_dynamic_configs(os.path.join(confpath, constants.CIPHER_S1))
165+ 
154 utils.cli.write_to_terminal('Starting to configure...', color='green')166 utils.cli.write_to_terminal('Starting to configure...', color='green')
155 # Generate an initial configuration file.167 # Generate an initial configuration file.
156 with GenerationConfig(168 with GenerationConfig(
@@ -202,6 +214,16 @@ def setup_directory_interactive(confpath):
202 color='red'214 color='red'
203 )215 )
204 input_value = ''216 input_value = ''
217+ if 'password' in option and input_value != default_value:
218+ # dynamic_config_xxx searches file from current working directory.
219+ os.chdir(confpath)
220+ s1, s2 = get_config_security_keys(os.path.join(confpath, constants.CIPHER_S1))
221+ # Every time a new password is generated, update the IV.
222+ iv = security.generate_an_iv()
223+ dynamic_config_set(IV_TABLE, '%s-%s' % (section, option), iv)
224+ cipher = security.encrypt(s1, s2, iv, input_value)
225+ input_value = ENCRYPTED_SIGNAL + cipher
226+ 
205 config.set(section, option, '%s # %s' % (227 config.set(section, option, '%s # %s' % (
206 input_value, inline_comment))228 input_value, inline_comment))
207 except (KeyboardInterrupt, EOFError, ValueError):229 except (KeyboardInterrupt, EOFError, ValueError):
@@ -58,7 +58,7 @@ class HttpService:
58 """58 """
59 59 
60 def __init__(self, name=__name__):60 def __init__(self, name=__name__):
61- self.app = FastAPI(title=name)61+ self.app = FastAPI(title=name, openapi_url=None, docs_url=None, redoc_url=None)
62 self._server = None62 self._server = None
63 self.static_directory = None63 self.static_directory = None
64 self.need_to_exit = False64 self.need_to_exit = False
@@ -26,8 +26,7 @@ from dbmind.common.utils import dbmind_assert, write_to_terminal
26 26 
27_psycopg2_kwargs = dict(27_psycopg2_kwargs = dict(
28 options="-c session_timeout=15 -c search_path=public",28 options="-c session_timeout=15 -c search_path=public",
29- application_name='DBMind-openGauss-exporter',29+ application_name='DBMind-openGauss-exporter'
30- sslmode='disable',
31)30)
32 31 
33 32 
@@ -28,6 +28,7 @@ METRIC_VALUE_RANGE_CONFIG = "metric_value_range.conf"
28MUST_FILTER_LABEL_CONFIG = 'filter_label.conf'28MUST_FILTER_LABEL_CONFIG = 'filter_label.conf'
29DYNAMIC_CONFIG = 'dynamic_config.db'29DYNAMIC_CONFIG = 'dynamic_config.db'
30DATE_FORMAT = '%Y-%m-%d %H:%M:%S'30DATE_FORMAT = '%Y-%m-%d %H:%M:%S'
31+CIPHER_S1 = 'encryption_part_a.bin'
31 32 
32with open(os.path.join(MISC_PATH, VERFILE_NAME)) as fp:33with open(os.path.join(MISC_PATH, VERFILE_NAME)) as fp:
33 __version__ = fp.readline().strip()34 __version__ = fp.readline().strip()
@@ -13,6 +13,9 @@
13from dbmind.metadatabase import DynamicConfigDbBase13from dbmind.metadatabase import DynamicConfigDbBase
14 14 
15 15 
16+# IV table name
17+IV_TABLE = 'iv_table'
18+ 
16class DynamicParams(DynamicConfigDbBase):19class DynamicParams(DynamicConfigDbBase):
17 __tablename__ = "dynamic_params"20 __tablename__ = "dynamic_params"
18 21 
@@ -16,6 +16,7 @@ port = # Port to connect to meta-data database.
16username = # User name to connect to meta-data database.16username = # User name to connect to meta-data database.
17password = (null) # Password to connect to meta-data database.17password = (null) # Password to connect to meta-data database.
18database = # Database name to connect to meta-data database.18database = # Database name to connect to meta-data database.
19+ssl_mode = prefer # The ssl mode for ssl connections. Options: disable, prefer, verify-ca.
19 20 
20[WORKER]21[WORKER]
21process_num = 0 # Number of worker processes on a local node. Less than or equal to zero means adaptive.22process_num = 0 # Number of worker processes on a local node. Less than or equal to zero means adaptive.