From 5049f6fbd1d58d92b0a0360763ff3f3cc173af89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20R=C3=BCthlein?= Date: Sun, 7 Jan 2024 15:23:11 +0100 Subject: [PATCH] add storage of additional variables in keystore --- README.md | 32 +++++++++++++++- documentation/additional_storage.yaml | 53 +++++++++++++++++++++++++++ documentation/docs/features/index.md | 30 +++++++++++++++ documentation/docs/installation.md | 2 +- documentation/mkdocs.yml | 1 + encryptcontent/plugin.py | 29 +++++++++++++++ setup.py | 2 +- 7 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 documentation/additional_storage.yaml diff --git a/README.md b/README.md index 732de88..9eb3a9f 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ In order to use environment variables in user names or passwords, use the * [Tag encrypted page](#Tag-encrypted-page) * [Remember password](#Remember-password) * [Share link generation](#Share-link-generation) + * [Storage of additional variables in keystore](#Storage-of-additional-variables-in-keystore) * [Modify generated pages](#Modify-generated-pages) * [Encrypt something](#Encrypt-something) * [Inject decrypt-form.tpl to theme](#Inject-decrypt-form.tpl-to-theme) @@ -94,7 +95,7 @@ Install the package from source with pip: ```bash cd mkdocs-encryptcontent-plugin/ python setup.py sdist bdist_wheel -pip install --force-reinstall --no-deps dist/mkdocs_encryptcontent_plugin-3.0.2-py3-none-any.whl +pip install --force-reinstall --no-deps dist/mkdocs_encryptcontent_plugin-3.0.3-py3-none-any.whl ``` Enable the plugin in your `mkdocs.yml`: @@ -486,6 +487,35 @@ However if `sharelinks: True` is enabled in the plugin configuration you can gen > Then another condition applies: If non-aphanumeric characters are used in user/password, > they need to be URLencoded (f.ex. %20 = space character). Some browsers may do that automatically (Do a copy/paste from the browsers address bar then). +### Storage of additional variables in keystore + +Since version 3.0.3 it is possible to set arbitrary session store variables after decryption. +These can be used by javascript functions f. ex. to read API tokens or show the user name or set visibility of menu entries. +The variables are encrypted together with the content keys in the keystore. + +```yaml +plugins: + - encryptcontent: + additional_storage_file: 'additional_storage.yaml' +``` + +The file may contain a `userpass:` dictionary, wich refers to user names +and/or a `password:` dictionary, that refers to password-only credentials. +It may contain a arbitrary number of key/value pairs, +but keep in mind to check if the key name is reasonable and not already used by other parts of the page +(as it will be overwritten after decryption). + +```yaml +userpass: + alice: + username: Alice McAliceface + userid: 1 + token: uCZDqa2vzuSPFX-o9TebinUAnD9sePJqpPYhavMkCH7gGo7lhjWRS17-HgBys9UKnFR37zXO4Q_f1_ywZJqBlA== + +password: + Head32_Sculpture_bovine_: + username: Head McPassword +``` ## Modify generated pages ### Encrypt something diff --git a/documentation/additional_storage.yaml b/documentation/additional_storage.yaml new file mode 100644 index 0000000..ef6c4e3 --- /dev/null +++ b/documentation/additional_storage.yaml @@ -0,0 +1,53 @@ +userpass: + alice: + username: Alice McAliceface + userid: 1 + token: uCZDqa2vzuSPFX-o9TebinUAnD9sePJqpPYhavMkCH7gGo7lhjWRS17-HgBys9UKnFR37zXO4Q_f1_ywZJqBlA== + bob: + username: Bob McBobface + userid: 2 + token: uCZDqa2vzuSPFX-o9TebinUAnD9sePJqpPYhavMkCH7gGo7lhjWRS17-HgBys9UKnFR37zXO4Q_f1_ywZJqBlA== + carlos: + username: Carlos McCarlosface + userid: 3 + token: uCZDqa2vzuSPFX-o9TebinUAnD9sePJqpPYhavMkCH7gGo7lhjWRS17-HgBys9UKnFR37zXO4Q_f1_ywZJqBlA== + carol: + username: Carol McCarolface + charlie: + username: Charlie McCharlieface + dan: + username: Dan McDanface + token: uCZDqa2vzuSPFX-o9TebinUAnD9sePJqpPYhavMkCH7gGo7lhjWRS17-HgBys9UKnFR37zXO4Q_f1_ywZJqBlA== + dave: + username: Dave McDaveface + token: uCZDqa2vzuSPFX-o9TebinUAnD9sePJqpPYhavMkCH7gGo7lhjWRS17-HgBys9UKnFR37zXO4Q_f1_ywZJqBlA== + david: + username: David McDavidface + token: uCZDqa2vzuSPFX-o9TebinUAnD9sePJqpPYhavMkCH7gGo7lhjWRS17-HgBys9UKnFR37zXO4Q_f1_ywZJqBlA== + +password: + C4bbage Profile blinking: + username: Cabbage McPassword + userid: 90 + token: NM-pdQyiJnLXSzY1e3d13GuekqLkClfWDLHtWQIu0l-geAkrygFvjJa3eux6ZJVAiSMtM8jphQCSSl9ru7TvRA== + Clique.Shampoo.Ve55el: + username: Clique McPassword + userid: 91 + token: NM-pdQyiJnLXSzY1e3d13GuekqLkClfWDLHtWQIu0l-geAkrygFvjJa3eux6ZJVAiSMtM8jphQCSSl9ru7TvRA== + Hatless,hertz,C4lzone: + username: Hatless McPassword + userid: 92 + Head32_Sculpture_bovine_: + username: Head McPassword + Negotiator-leftover-567: + username: Negotiator McPassword + token: NM-pdQyiJnLXSzY1e3d13GuekqLkClfWDLHtWQIu0l-geAkrygFvjJa3eux6ZJVAiSMtM8jphQCSSl9ru7TvRA== + SpotChestOilCycle22: + username: Spot McPassword + token: NM-pdQyiJnLXSzY1e3d13GuekqLkClfWDLHtWQIu0l-geAkrygFvjJa3eux6ZJVAiSMtM8jphQCSSl9ru7TvRA== + m00dy#augmented#Arsonist: + username: Moody McPassword + token: NM-pdQyiJnLXSzY1e3d13GuekqLkClfWDLHtWQIu0l-geAkrygFvjJa3eux6ZJVAiSMtM8jphQCSSl9ru7TvRA== + moist:W00l:kept:royal: + username: Moist McPassword + token: NM-pdQyiJnLXSzY1e3d13GuekqLkClfWDLHtWQIu0l-geAkrygFvjJa3eux6ZJVAiSMtM8jphQCSSl9ru7TvRA== diff --git a/documentation/docs/features/index.md b/documentation/docs/features/index.md index 8300f64..4879cdb 100644 --- a/documentation/docs/features/index.md +++ b/documentation/docs/features/index.md @@ -143,3 +143,33 @@ However if `sharelinks: True` is enabled in the plugin configuration you can gen > Then another condition applies: If non-aphanumeric characters are used in user/password, > they need to be URLencoded (f.ex. %20 = space character). Some browsers may do that automatically (Do a copy/paste from the browsers address bar then). + +### Storage of additional variables in keystore + +Since version 3.0.3 it is possible to set arbitrary session store variables after decryption. +These can be used by javascript functions f. ex. to read API tokens or show the user name or set visibility of menu entries. +The variables are encrypted together with the content keys in the keystore. + +```yaml +plugins: + - encryptcontent: + additional_storage_file: 'additional_storage.yaml' +``` + +The file may contain a `userpass:` dictionary, wich refers to user names +and/or a `password:` dictionary, that refers to password-only credentials. +It may contain a arbitrary number of key/value pairs, +but keep in mind to check if the key name is reasonable and not already used by other parts of the page +(as it will be overwritten after decryption). + +```yaml +userpass: + alice: + username: Alice McAliceface + userid: 1 + token: uCZDqa2vzuSPFX-o9TebinUAnD9sePJqpPYhavMkCH7gGo7lhjWRS17-HgBys9UKnFR37zXO4Q_f1_ywZJqBlA== + +password: + Head32_Sculpture_bovine_: + username: Head McPassword +``` \ No newline at end of file diff --git a/documentation/docs/installation.md b/documentation/docs/installation.md index d2d8170..dd2f9e0 100644 --- a/documentation/docs/installation.md +++ b/documentation/docs/installation.md @@ -13,7 +13,7 @@ Install the package from source with pip: ```bash cd mkdocs-encryptcontent-plugin/ python setup.py sdist bdist_wheel -pip install --force-reinstall --no-deps dist/mkdocs_encryptcontent_plugin-3.0.2-py3-none-any.whl +pip install --force-reinstall --no-deps dist/mkdocs_encryptcontent_plugin-3.0.3-py3-none-any.whl ``` Enable the plugin in your `mkdocs.yml`: diff --git a/documentation/mkdocs.yml b/documentation/mkdocs.yml index 6e78203..b0cf3d3 100644 --- a/documentation/mkdocs.yml +++ b/documentation/mkdocs.yml @@ -134,6 +134,7 @@ plugins: reload_scripts: - '#autostart' password_file: 'passwords.yml' + additional_storage_file: 'additional_storage.yaml' sharelinks: true #kdf_pow: 4 webcrypto: true diff --git a/encryptcontent/plugin.py b/encryptcontent/plugin.py index 2c40a4e..d01201b 100644 --- a/encryptcontent/plugin.py +++ b/encryptcontent/plugin.py @@ -80,6 +80,7 @@ class encryptContentPlugin(BasePlugin): ('session_storage', config_options.Type(bool, default=True)), ('password_inventory', config_options.Type(dict, default={})), ('password_file', config_options.Type(string_types, default=None)), + ('additional_storage_file', config_options.Type(string_types, default=None)), ('cache_file', config_options.Type(string_types, default='encryptcontent.cache')), ('sharelinks', config_options.Type(bool, default=False)), ('sharelinks_output', config_options.Type(string_types, default='sharelinks.txt')), @@ -159,6 +160,10 @@ def __add_to_keystore__(self, index, key, id): else: keystore[index][store_id] = key.hex() + def __vars_to_keystore__(self, index, var, value): + keystore = self.setup['keystore'] + keystore[index][var] = value + def __encrypt_keys_from_keystore__(self, index, plaintext_length=-1): keystore = self.setup['keystore'] password = index[1] @@ -612,6 +617,30 @@ def on_config(self, config, **kwargs): os._exit(1) self.setup['level_keys'][level] = new_entry + if 'additional_storage' not in self.setup: + if self.config['additional_storage_file']: + storage_file = self.setup['config_path'].joinpath(self.config['additional_storage_file']) + with open(storage_file, 'r') as stream: + self.setup['additional_storage'] = yaml_load(stream) + + #init empty if missing + if 'userpass' not in self.setup['additional_storage']: + self.setup['additional_storage']['userpass'] = {} + if 'password' not in self.setup['additional_storage']: + self.setup['additional_storage']['password'] = {} + + for entry in self.setup['keystore'].copy(): + if entry[0] == KS_PASSWORD: + if entry[1] in self.setup['additional_storage']['password']: + for var in self.setup['additional_storage']['password'][entry[1]]: + value = self.setup['additional_storage']['password'][entry[1]][var] + self.__vars_to_keystore__(entry, var, value) + else: + if entry[0] in self.setup['additional_storage']['userpass']: + for var in self.setup['additional_storage']['userpass'][entry[0]]: + value = self.setup['additional_storage']['userpass'][entry[0]][var] + self.__vars_to_keystore__(entry, var, value) + if self.config['sign_files'] and 'sign_key' not in self.setup: sign_key_path = self.setup['config_path'].joinpath(self.config['sign_key']) sign_key_path.parents[0].mkdir(parents=True, exist_ok=True) diff --git a/setup.py b/setup.py index 78e8889..f462845 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ def read(fname): setup( name='mkdocs-encryptcontent-plugin', - version='3.0.2', + version='3.0.3', author='unverbuggt', author_email='unverbuggt@xn--rthlein-n2a.de', description='A MkDocs plugin that encrypt/decrypt markdown content with AES',