Skip to content

Commit

Permalink
add storage of additional variables in keystore
Browse files Browse the repository at this point in the history
  • Loading branch information
unverbuggt committed Jan 7, 2024
1 parent 6ad9312 commit 5049f6f
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 3 deletions.
32 changes: 31 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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`:
Expand Down Expand Up @@ -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
Expand Down
53 changes: 53 additions & 0 deletions documentation/additional_storage.yaml
Original file line number Diff line number Diff line change
@@ -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==
30 changes: 30 additions & 0 deletions documentation/docs/features/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```
2 changes: 1 addition & 1 deletion documentation/docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`:
Expand Down
1 change: 1 addition & 0 deletions documentation/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
29 changes: 29 additions & 0 deletions encryptcontent/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')),
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def read(fname):

setup(
name='mkdocs-encryptcontent-plugin',
version='3.0.2',
version='3.0.3',
author='unverbuggt',
author_email='[email protected]',
description='A MkDocs plugin that encrypt/decrypt markdown content with AES',
Expand Down

0 comments on commit 5049f6f

Please sign in to comment.