Compare commits
57 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 61fd155025 | |||
| 89112ba2e1 | |||
| a86a8bdc28 | |||
| 88e7548fa4 | |||
| 08e50e8aea | |||
| 6f358f88f2 | |||
| 2f50351b9d | |||
| 495b54dd0f | |||
| ec3b740aea | |||
| 1088164eed | |||
| c83675ae7d | |||
| 6e3b48de07 | |||
| 669c6cce98 | |||
| 0cff9b8691 | |||
| 13abd6ac4d | |||
| 24fcf6f814 | |||
| 72980ca358 | |||
| d30680cbed | |||
| a2fb9e8509 | |||
| 16119b432e | |||
| d4e3d06cc2 | |||
| a17ae75c59 | |||
| 54bdf4861c | |||
| 71a05d631c | |||
| 1d401f7e35 | |||
| 2bb0b0db3a | |||
| c4c7e0da4a | |||
| 34963ddca2 | |||
| a273820c84 | |||
| c3a0ecd557 | |||
| 3b72988cb5 | |||
| d3c0f94f86 | |||
| 80b1155d2a | |||
| 65e318e883 | |||
| e9ef79e80b | |||
| a12cf396fd | |||
| 4c72346aa6 | |||
| 80ddd65206 | |||
| d96f888e48 | |||
| 82e0c371a0 | |||
| 5d8dd6881f | |||
| 4fd27de57e | |||
| 76b43846ed | |||
| 510b97d7cf | |||
| b332195ef3 | |||
| 8b180e131e | |||
| 52a56476d3 | |||
| 7925cdcc6a | |||
| 01feb985fb | |||
| c16fcdb7fe | |||
| b16e71846b | |||
| eea2badb64 | |||
| b6e4744085 | |||
| 653790b9af | |||
| 971311e0f5 | |||
| abb4b87924 | |||
| 5682ac96b6 |
80 changed files with 1929 additions and 1 deletions
163
CHANGELOG.md
Normal file
163
CHANGELOG.md
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
## 0.1.0a27 (2025-12-22)
|
||||||
|
|
||||||
|
### Feat
|
||||||
|
|
||||||
|
- use Calculation
|
||||||
|
- doc
|
||||||
|
|
||||||
|
## 0.1.0a26 (2025-11-21)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- ExtentionError => ExtensionError
|
||||||
|
|
||||||
|
## 0.1.0a25 (2025-11-06)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- disable config if bitwarden is not selected
|
||||||
|
|
||||||
|
## 0.1.0a24 (2025-10-16)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- path is uncalculated
|
||||||
|
|
||||||
|
## 0.1.0a23 (2025-10-16)
|
||||||
|
|
||||||
|
### Feat
|
||||||
|
|
||||||
|
- update rougail-structural-bitwarden
|
||||||
|
|
||||||
|
## 0.1.0a22 (2025-10-10)
|
||||||
|
|
||||||
|
### Feat
|
||||||
|
|
||||||
|
- use user_datas to load datas
|
||||||
|
|
||||||
|
## 0.1.0a21 (2025-06-20)
|
||||||
|
|
||||||
|
### Feat
|
||||||
|
|
||||||
|
- update rougail-structural-bitwarden package version
|
||||||
|
|
||||||
|
## 0.1.0a20 (2025-05-12)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- black
|
||||||
|
|
||||||
|
## 0.1.0a19 (2025-05-02)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- do not force use_data usage
|
||||||
|
|
||||||
|
## 0.1.0a18 (2025-04-09)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- version
|
||||||
|
|
||||||
|
## 0.1.0a17 (2025-04-09)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- better error message
|
||||||
|
|
||||||
|
## 0.1.0a16 (2025-04-04)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- with ROUGAIL_BITWARDEN_MOCK_ENABLE variable, unix_user and password are different
|
||||||
|
|
||||||
|
## 0.1.0a15 (2025-03-19)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- support item without username
|
||||||
|
|
||||||
|
## 0.1.0a14 (2025-03-19)
|
||||||
|
|
||||||
|
### Feat
|
||||||
|
|
||||||
|
- port to rougail secret_manager
|
||||||
|
- same behavour between bw et rbw
|
||||||
|
|
||||||
|
## 0.1.0a13 (2025-02-19)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- MOCK
|
||||||
|
|
||||||
|
## 0.1.0a12 (2025-02-19)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- MOCK
|
||||||
|
|
||||||
|
## 0.1.0a11 (2025-02-19)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- if mock is active, do not search rbw or bw
|
||||||
|
|
||||||
|
## 0.1.0a10 (2025-02-17)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- support hidden attribut
|
||||||
|
|
||||||
|
## 0.1.0a9 (2025-02-17)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- support hidden attribut
|
||||||
|
|
||||||
|
## 0.1.0a8 (2025-02-17)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- update structural plugin version
|
||||||
|
|
||||||
|
## 0.1.0a7 (2025-02-17)
|
||||||
|
|
||||||
|
### Feat
|
||||||
|
|
||||||
|
- support rbw and bw command line
|
||||||
|
|
||||||
|
## 0.1.0a6 (2025-02-13)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- bitwarden key could be an invalid username/secret
|
||||||
|
|
||||||
|
## 0.1.0a5 (2025-02-13)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- structural load
|
||||||
|
|
||||||
|
## 0.1.0a4 (2025-02-13)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- structural version
|
||||||
|
|
||||||
|
## 0.1.0a2 (2025-02-13)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- separate user-data and structural
|
||||||
|
|
||||||
|
## 0.1.0a1 (2025-02-12)
|
||||||
|
|
||||||
|
### Fix
|
||||||
|
|
||||||
|
- many improvment
|
||||||
|
|
||||||
|
## 0.1.0a0 (2025-02-05)
|
||||||
|
|
||||||
|
### Feat
|
||||||
|
|
||||||
|
- first version
|
||||||
21
README.fr.md
Normal file
21
README.fr.md
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
gitea: none
|
||||||
|
include_toc: true
|
||||||
|
---
|
||||||
|
[🇬🇧 (EN)](README.md) - [🇫🇷 (FR)](README.fr.md)
|
||||||
|
|
||||||
|
## Les secrets sont dans Bitwarden
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
>
|
||||||
|
> Charge les secrets depuis Bitwarden. Les données sont récupérées à l'aide de la commande officielle « bw » ou de la commande alternative « rbw » (plus rapide). Avant d'utiliser Rougail, la commande doit être connectée et déverrouillée.\
|
||||||
|
> **Chemin** : bitwarden\
|
||||||
|
> *`désactivé`*\
|
||||||
|
> **Désactivé** : si bitwarden n'est pas dans "[Sélection pour données utilisateur](#step.user_data)"
|
||||||
|
|
||||||
|
| Variable | Description | Valeur par défaut | Type | Validateur |
|
||||||
|
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|--------------------------|-------------------------------------------------------------------------------------------------------------|--------------------------------------------------------|
|
||||||
|
| **<a id="bitwarden.command" name="bitwarden.command">bitwarden.command</a>**<br/>**Ligne de commande** : --bitwarden.command<br/>**Variable d'environnement** : BITWARDEN.COMMAND | Ligne de commande utilisée pour récupérer les secrets.<br/>Ligne de commande doit être dans le PATH. | • rbw<br/>• bw | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` `obligatoire` | `unique`<br/>**Choix** : <br/>• rbw<br/>• bw |
|
||||||
|
| **<a id="bitwarden.mock_enable" name="bitwarden.mock_enable">bitwarden.mock_enable</a>**<br/>**Ligne de commande** : <br/>• --bitwarden.mock_enable<br/>• --bitwarden.no-mock_enable<br/>**Variable d'environnement** : BITWARDEN.MOCK_ENABLE | Simuler la génération de mots de passe au lieu de les récupérer. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `obligatoire` | |
|
||||||
|
|
||||||
|
|
||||||
21
README.md
21
README.md
|
|
@ -1,2 +1,21 @@
|
||||||
# rougail-user-data-bitwarden
|
---
|
||||||
|
gitea: none
|
||||||
|
include_toc: true
|
||||||
|
---
|
||||||
|
[🇬🇧 (EN)](README.md) - [🇫🇷 (FR)](README.fr.md)
|
||||||
|
|
||||||
|
## Secrets are in Bitwarden
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
>
|
||||||
|
> Load the secrets from Bitwarden. The data is retrieved using the official command line "bw" or the alternative command "rbw" (faster). Before using Rougail, the command must be logged and unlocked.\
|
||||||
|
> **Path**: bitwarden\
|
||||||
|
> *`disabled`*\
|
||||||
|
> **Disabled**: if bitwarden is not set in "[Select for user datas](#step.user_data)"
|
||||||
|
|
||||||
|
| Variable | Description | Default value | Type | Validator |
|
||||||
|
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|--------------------------|-----------------------------------------------------------------------------------------------------------|---------------------------------------------------------|
|
||||||
|
| **<a id="bitwarden.command" name="bitwarden.command">bitwarden.command</a>**<br/>**Command line**: --bitwarden.command<br/>**Environment variable**: BITWARDEN.COMMAND | Command line used to retrieve secrets.<br/>Command line must be in PATH. | • rbw<br/>• bw | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` `mandatory` | `unique`<br/>**Choices**: <br/>• rbw<br/>• bw |
|
||||||
|
| **<a id="bitwarden.mock_enable" name="bitwarden.mock_enable">bitwarden.mock_enable</a>**<br/>**Command line**: <br/>• --bitwarden.mock_enable<br/>• --bitwarden.no-mock_enable<br/>**Environment variable**: BITWARDEN.MOCK_ENABLE | Simulate password generation instead of retrieve them. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | |
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
44
doc.py
Executable file
44
doc.py
Executable file
|
|
@ -0,0 +1,44 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
from rougail import Rougail
|
||||||
|
from rougail.config import get_common_rougail_config, get_rougail_config
|
||||||
|
from rougail.output_doc import RougailOutputDoc
|
||||||
|
from rougail.user_data_bitwarden.config import get_rougail_config as local_get_rougail_config
|
||||||
|
|
||||||
|
|
||||||
|
def to_yaml(options):
|
||||||
|
return """%YAML 1.2
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
""" + options + "..."
|
||||||
|
|
||||||
|
backward_compatibility = False
|
||||||
|
rougailconfig = get_rougail_config(backward_compatibility=backward_compatibility)
|
||||||
|
rougailconfig['force_optional'] = True
|
||||||
|
rougailconfig['step.output'] = "doc"
|
||||||
|
# rougailconfig['tiramisu_cache'] = "a.py"
|
||||||
|
rougailconfig['step.structural'] = ["commandline", "string"]
|
||||||
|
rougailconfig['main_namespace'] = None
|
||||||
|
rougailconfig["doc.root"] = "bitwarden"
|
||||||
|
rougailconfig["doc.title_level"] = 2
|
||||||
|
rougailconfig["doc.tabulars.with_commandline"] = True
|
||||||
|
rougailconfig["doc.tabulars.with_environment"] = True
|
||||||
|
rougailconfig["doc.tabulars.environment_prefix"] = "ROUGAILCLI"
|
||||||
|
rougailconfig["doc.output_format"] = "github"
|
||||||
|
rougailconfig['doc.tabular_template'] = 'six_columns'
|
||||||
|
rougail_config = to_yaml(get_common_rougail_config(backward_compatibility=backward_compatibility)[2])
|
||||||
|
module_config = to_yaml(local_get_rougail_config(backward_compatibility=False)['options'])
|
||||||
|
rougailconfig['main_structural_strings'] = [rougail_config, module_config]
|
||||||
|
rougail = Rougail(rougailconfig)
|
||||||
|
config = rougail.run()
|
||||||
|
config.property.read_write()
|
||||||
|
output = RougailOutputDoc(
|
||||||
|
config=config,
|
||||||
|
rougailconfig=rougailconfig,
|
||||||
|
)
|
||||||
|
print("""---
|
||||||
|
gitea: none
|
||||||
|
include_toc: true
|
||||||
|
---
|
||||||
|
[🇬🇧 (EN)](README.md) - [🇫🇷 (FR)](README.fr.md)
|
||||||
|
""")
|
||||||
|
output.print()
|
||||||
159
locale/fr/LC_MESSAGES/rougail_user_data_bitwarden.po
Normal file
159
locale/fr/LC_MESSAGES/rougail_user_data_bitwarden.po
Normal file
|
|
@ -0,0 +1,159 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR ORGANIZATION
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: \n"
|
||||||
|
"POT-Creation-Date: 2025-12-20 20:33+0100\n"
|
||||||
|
"PO-Revision-Date: 2025-12-20 20:33+0100\n"
|
||||||
|
"Last-Translator: \n"
|
||||||
|
"Language-Team: \n"
|
||||||
|
"Language: fr\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Generated-By: pygettext.py 1.5\n"
|
||||||
|
"X-Generator: Poedit 3.8\n"
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/config.py:30
|
||||||
|
msgid "Secrets are in Bitwarden"
|
||||||
|
msgstr "Les secrets sont dans Bitwarden"
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/config.py:32
|
||||||
|
msgid ""
|
||||||
|
"Load the secrets from Bitwarden. The data is retrieved using the official "
|
||||||
|
"command line \"bw\" or the alternative command \"rbw\" (faster). Before "
|
||||||
|
"using Rougail, the command must be logged and unlocked."
|
||||||
|
msgstr ""
|
||||||
|
"Charge les secrets depuis Bitwarden. Les données sont récupérées à l'aide de "
|
||||||
|
"la commande officielle « bw » ou de la commande alternative « rbw » (plus "
|
||||||
|
"rapide). Avant d'utiliser Rougail, la commande doit être connectée et "
|
||||||
|
"déverrouillée."
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/config.py:37
|
||||||
|
msgid "if bitwarden is not set in \"_.step.user_data\""
|
||||||
|
msgstr "si bitwarden n'est pas dans \"_.step.user_data\""
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/config.py:40
|
||||||
|
msgid "Command line used to retrieve secrets"
|
||||||
|
msgstr "Ligne de commande utilisée pour récupérer les secrets"
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/config.py:41
|
||||||
|
msgid "Command line must be in PATH"
|
||||||
|
msgstr "Ligne de commande doit être dans le PATH"
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/config.py:49
|
||||||
|
msgid "Simulate password generation instead of retrieve them"
|
||||||
|
msgstr "Simuler la génération de mots de passe au lieu de les récupérer"
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:132
|
||||||
|
msgid "\"bitwarden\" is not set in step.user_data"
|
||||||
|
msgstr "\"bitwarden\" n'est pas dans step.user_data"
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:169
|
||||||
|
msgid "please unlock Bitwarden password database with {0} command line"
|
||||||
|
msgstr ""
|
||||||
|
"veuillez déverrouiller la base de mot de passe Bitwarden avec la ligne de "
|
||||||
|
"commande {0}"
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:171
|
||||||
|
msgid "cannot find Bitwarden command line {0} please install it"
|
||||||
|
msgstr ""
|
||||||
|
"ne peut trouver la ligne de commande Bitwarden {0} veuillez l'installer"
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:208
|
||||||
|
msgid "the default value for \"{0}\" must be the Bitwarden item name"
|
||||||
|
msgstr ""
|
||||||
|
"la valeur par défaut pour \"{0}\" doit être un nom d'élément de Bitwarden"
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:219
|
||||||
|
msgid "cannot execute the \"{0}\" commandline from Bitwarden for \"{1}\": {2}"
|
||||||
|
msgstr ""
|
||||||
|
"ne peut exécuter la ligne de commande \"{0}\" pour Bitwarden pour \"{1}\": "
|
||||||
|
"{2}"
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:228
|
||||||
|
msgid "item \"{0}\" in Bitwarden is not found for \"{1}\""
|
||||||
|
msgstr "l'élément \"{0}\" dans Bitwarden n'est pas trouvé pour \"{1}\""
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:243
|
||||||
|
msgid "several items found with name \"{0}\" in Bitwarden for \"{1}\": \"{2}\""
|
||||||
|
msgstr ""
|
||||||
|
"plusieurs éléments trouvés avec le nom \"{0}\" dans Bitwarden pour \"{1}\": "
|
||||||
|
"\"{2}\""
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:262
|
||||||
|
msgid "unexpected datas \"{0}\" from Bitwarden for \"{1}\": {2}"
|
||||||
|
msgstr "données inattendues \"{0}\" pour Bitwarden pour \"{1}\": {2}"
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:270
|
||||||
|
msgid "password"
|
||||||
|
msgstr "de mot de passe"
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:272
|
||||||
|
msgid "username"
|
||||||
|
msgstr "de nom d'utilisateur"
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:274
|
||||||
|
msgid "item \"{0}\" in Bitwarden has no {1} for \"{2}\""
|
||||||
|
msgstr "l'élément \"{0}\" dans Bitwarden n'a pas {1} for \"{2}\""
|
||||||
|
|
||||||
|
#~ msgid "Configuration rougail-user-data-bitwarden"
|
||||||
|
#~ msgstr "Configuration de rougail-user-data-bitwarden"
|
||||||
|
|
||||||
|
#~ msgid "\"rbw\" or \"bw\""
|
||||||
|
#~ msgstr "\"rbw\" ou \"bw\""
|
||||||
|
|
||||||
|
#~ msgid "\"{0}\""
|
||||||
|
#~ msgstr "\"{0}\""
|
||||||
|
|
||||||
|
#~ msgid ""
|
||||||
|
#~ "the value for \"{0}\" at index {1} is already set while it should be "
|
||||||
|
#~ "filled in by Bitwarden"
|
||||||
|
#~ msgstr ""
|
||||||
|
#~ "la valeur de \"{0}\" à l'index {1} est déjà renseigné alors que celle "
|
||||||
|
#~ "doit devrait être renseigné par Bitwarden"
|
||||||
|
|
||||||
|
#~ msgid ""
|
||||||
|
#~ "the value for \"{0}\" is already set while it should be filled in by "
|
||||||
|
#~ "Bitwarden"
|
||||||
|
#~ msgstr ""
|
||||||
|
#~ "la valeur de \"{0}\" est déjà renseignée alors que celle doit devrait "
|
||||||
|
#~ "être renseignée par Bitwarden"
|
||||||
|
|
||||||
|
#~ msgid "cannot find {0} \"{1}\" from Bitwarden for \"{2}\""
|
||||||
|
#~ msgstr "ne peut trouver {0} \"{1}\" pour Bitwarden pour \"{2}\""
|
||||||
|
|
||||||
|
#~ msgid ""
|
||||||
|
#~ "only \"unix_user\" or \"secret\" variable type can have \"bitwarden\" "
|
||||||
|
#~ "attribute, but \"{0}\" has type \"{1}\""
|
||||||
|
#~ msgstr ""
|
||||||
|
#~ "seule une variable de type \"unix_user\" ou \"secret\" peuvent avoir "
|
||||||
|
#~ "l'attribut \"bitwarden\", mais \"{0}\" a le type \"{1}\""
|
||||||
|
|
||||||
|
#~ msgid ""
|
||||||
|
#~ "the variable \"{0}\" has attribute \"bitwarden\" but is a multi variable"
|
||||||
|
#~ msgstr ""
|
||||||
|
#~ "la variable \"{0}\" a un attribut \"bitwarden\" mais est une variable "
|
||||||
|
#~ "multiple"
|
||||||
|
|
||||||
|
#~ msgid ""
|
||||||
|
#~ "the variable \"{0}\" is a follower and leader variable (\"{1}\") is also "
|
||||||
|
#~ "in Bitwarden so this variable could not have default value"
|
||||||
|
#~ msgstr ""
|
||||||
|
#~ "la variable \"{0}\" est une suiveuse et la variable leader (\"{1}\") est "
|
||||||
|
#~ "aussi dans Bitwarden donc cette variable ne peut avoir de valeur par "
|
||||||
|
#~ "défaut"
|
||||||
|
|
||||||
|
#~ msgid "the variable \"{0}\" is in Bitwarden so should have default value"
|
||||||
|
#~ msgstr ""
|
||||||
|
#~ "la variable \"{0}\" est dans Bitwarden donc doit avoir une valeur par "
|
||||||
|
#~ "défaut"
|
||||||
|
|
||||||
|
#~ msgid "cannot get {0} \"{1}\" from Bitwarden for \"{2}\": {3} ({4})"
|
||||||
|
#~ msgstr ""
|
||||||
|
#~ "ne peut récupérer {0} \"{1}\" pour Bitwarden pour \"{2}\": {3} ({4})"
|
||||||
|
|
||||||
|
#~ msgid "cannot load {0} \"{1}\" from Bitwarden for \"{2}\": {3}"
|
||||||
|
#~ msgstr "ne peut charger {0} \"{1}\" pour Bitwarden pour \"{2}\": {3}"
|
||||||
85
locale/rougail_user_data_bitwarden.pot
Normal file
85
locale/rougail_user_data_bitwarden.pot
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR ORGANIZATION
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"POT-Creation-Date: 2025-12-20 20:33+0100\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Generated-By: pygettext.py 1.5\n"
|
||||||
|
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/config.py:30
|
||||||
|
msgid "Secrets are in Bitwarden"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/config.py:32
|
||||||
|
msgid "Load the secrets from Bitwarden. The data is retrieved using the official command line \"bw\" or the alternative command \"rbw\" (faster). Before using Rougail, the command must be logged and unlocked."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/config.py:37
|
||||||
|
msgid "if bitwarden is not set in \"_.step.user_data\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/config.py:40
|
||||||
|
msgid "Command line used to retrieve secrets"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/config.py:41
|
||||||
|
msgid "Command line must be in PATH"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/config.py:49
|
||||||
|
msgid "Simulate password generation instead of retrieve them"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:132
|
||||||
|
msgid "\"bitwarden\" is not set in step.user_data"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:169
|
||||||
|
msgid "please unlock Bitwarden password database with {0} command line"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:171
|
||||||
|
msgid "cannot find Bitwarden command line {0} please install it"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:208
|
||||||
|
msgid "the default value for \"{0}\" must be the Bitwarden item name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:219
|
||||||
|
msgid "cannot execute the \"{0}\" commandline from Bitwarden for \"{1}\": {2}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:228
|
||||||
|
msgid "item \"{0}\" in Bitwarden is not found for \"{1}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:243
|
||||||
|
msgid "several items found with name \"{0}\" in Bitwarden for \"{1}\": \"{2}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:262
|
||||||
|
msgid "unexpected datas \"{0}\" from Bitwarden for \"{1}\": {2}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:270
|
||||||
|
msgid "password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:272
|
||||||
|
msgid "username"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/rougail/user_data_bitwarden/data.py:274
|
||||||
|
msgid "item \"{0}\" in Bitwarden has no {1} for \"{2}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
44
pyproject.toml
Normal file
44
pyproject.toml
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
[build-system]
|
||||||
|
build-backend = "flit_core.buildapi"
|
||||||
|
requires = ["flit_core >=3.8.0,<4"]
|
||||||
|
|
||||||
|
[project]
|
||||||
|
name = "rougail.user_data_bitwarden"
|
||||||
|
version = "0.1.0a27"
|
||||||
|
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
|
||||||
|
readme = "README.md"
|
||||||
|
description = "Rougail user_data Bitwarden"
|
||||||
|
requires-python = ">=3.8"
|
||||||
|
license = {file = "LICENSE"}
|
||||||
|
classifiers = [
|
||||||
|
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
|
||||||
|
"Programming Language :: Python",
|
||||||
|
"Programming Language :: Python :: 3.11",
|
||||||
|
"Programming Language :: Python :: 3.12",
|
||||||
|
"Programming Language :: Python :: 3.13",
|
||||||
|
"Programming Language :: Python :: 3.14",
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"Operating System :: OS Independent",
|
||||||
|
"Natural Language :: English",
|
||||||
|
"Natural Language :: French",
|
||||||
|
|
||||||
|
]
|
||||||
|
dependencies = [
|
||||||
|
"rougail >= 1.1,<2",
|
||||||
|
"rougail-structural-bitwarden == 0.1.0a6",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.urls]
|
||||||
|
Home = "https://forge.cloud.silique.fr/stove/rougail-user-data-bitwarden"
|
||||||
|
|
||||||
|
[tool.commitizen]
|
||||||
|
name = "cz_conventional_commits"
|
||||||
|
tag_format = "$version"
|
||||||
|
version_scheme = "pep440"
|
||||||
|
version_provider = "pep621"
|
||||||
|
version_files = [
|
||||||
|
"src/rougail/user_data_bitwarden/__version__.py",
|
||||||
|
"pyproject.toml:version"
|
||||||
|
]
|
||||||
|
update_changelog_on_bump = true
|
||||||
|
changelog_merge_prerelease = true
|
||||||
27
src/rougail/user_data_bitwarden/__init__.py
Normal file
27
src/rougail/user_data_bitwarden/__init__.py
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
"""
|
||||||
|
Silique (https://www.silique.fr)
|
||||||
|
Copyright (C) 2025
|
||||||
|
|
||||||
|
distribued with GPL-2 or later license
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .data import RougailUserDataBitwarden
|
||||||
|
from .__version__ import __version__
|
||||||
|
|
||||||
|
|
||||||
|
RougailUserData = RougailUserDataBitwarden
|
||||||
|
__all__ = ("RougailUserDataBitwarden",)
|
||||||
1
src/rougail/user_data_bitwarden/__version__.py
Normal file
1
src/rougail/user_data_bitwarden/__version__.py
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
__version__ = "0.1.0a27"
|
||||||
48
src/rougail/user_data_bitwarden/annotator.py
Normal file
48
src/rougail/user_data_bitwarden/annotator.py
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
"""
|
||||||
|
Silique (https://www.silique.fr)
|
||||||
|
Copyright (C) 2025
|
||||||
|
|
||||||
|
distribued with GPL-2 or later license
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
"""
|
||||||
|
from rougail.error import DictConsistencyError
|
||||||
|
from rougail.annotator.variable import Walk
|
||||||
|
|
||||||
|
|
||||||
|
class Annotator(Walk):
|
||||||
|
"""Annotate for bitwarden"""
|
||||||
|
|
||||||
|
level = 90
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
objectspace,
|
||||||
|
*args, # pylint: disable=unused-argument
|
||||||
|
) -> None:
|
||||||
|
if not objectspace.paths:
|
||||||
|
return
|
||||||
|
self.objectspace = objectspace
|
||||||
|
self.check_variable()
|
||||||
|
|
||||||
|
def check_variable(self):
|
||||||
|
for variable in self.get_variables():
|
||||||
|
if not variable.secret_manager:
|
||||||
|
continue
|
||||||
|
path = variable.path
|
||||||
|
self.objectspace.informations.add(path, "bitwarden", True)
|
||||||
|
self.objectspace.informations.add(path, "default_value_makes_sense", False)
|
||||||
|
self.objectspace.properties.add(path, "novalidator", True)
|
||||||
|
variable.default = variable.secret_manager
|
||||||
59
src/rougail/user_data_bitwarden/config.py
Normal file
59
src/rougail/user_data_bitwarden/config.py
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
"""
|
||||||
|
Silique (https://www.silique.fr)
|
||||||
|
Copyright (C) 2025
|
||||||
|
|
||||||
|
distribued with GPL-2 or later license
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .i18n import _
|
||||||
|
|
||||||
|
|
||||||
|
def get_rougail_config(
|
||||||
|
*,
|
||||||
|
backward_compatibility=True,
|
||||||
|
) -> dict:
|
||||||
|
options = f"""bitwarden:
|
||||||
|
description: {_("Secrets are in Bitwarden")}
|
||||||
|
help: |-
|
||||||
|
{_("Load the secrets from Bitwarden. The data is retrieved using the official command line \"bw\" or the alternative command \"rbw\" (faster). Before using Rougail, the command must be logged and unlocked.")}
|
||||||
|
disabled:
|
||||||
|
jinja: |-
|
||||||
|
{{{{ _.step.user_data is propertyerror or 'bitwarden' not in _.step.user_data }}}}
|
||||||
|
return_type: boolean
|
||||||
|
description: {_('if bitwarden is not set in "_.step.user_data"')}
|
||||||
|
|
||||||
|
command:
|
||||||
|
description: {_("Command line used to retrieve secrets")}
|
||||||
|
help: {_("Command line must be in PATH")}
|
||||||
|
choices:
|
||||||
|
- rbw
|
||||||
|
- bw
|
||||||
|
default:
|
||||||
|
- rbw
|
||||||
|
- bw
|
||||||
|
|
||||||
|
mock_enable: false # {_("Simulate password generation instead of retrieve them")}
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
"name": "bitwarden",
|
||||||
|
"process": "user data",
|
||||||
|
"options": options,
|
||||||
|
"level": 90,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ("get_rougail_config",)
|
||||||
273
src/rougail/user_data_bitwarden/data.py
Normal file
273
src/rougail/user_data_bitwarden/data.py
Normal file
|
|
@ -0,0 +1,273 @@
|
||||||
|
"""
|
||||||
|
Silique (https://www.silique.fr)
|
||||||
|
Copyright (C) 2025
|
||||||
|
|
||||||
|
distribued with GPL-2 or later license
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
"""
|
||||||
|
|
||||||
|
from subprocess import run
|
||||||
|
from json import loads
|
||||||
|
from os import environ
|
||||||
|
from shutil import which
|
||||||
|
|
||||||
|
|
||||||
|
from tiramisu.error import ConfigError, display_list
|
||||||
|
from rougail.error import ExtensionError
|
||||||
|
from .i18n import _
|
||||||
|
|
||||||
|
|
||||||
|
class FakeBW:
|
||||||
|
def get_key(
|
||||||
|
self,
|
||||||
|
key_bitwarden: str,
|
||||||
|
multiple: bool,
|
||||||
|
):
|
||||||
|
return [{'name': key_bitwarden, 'login': {'username': "example_login", 'password': "Ex4mpL3_P4ssw0rD"}}]
|
||||||
|
|
||||||
|
|
||||||
|
class RBW:
|
||||||
|
def unlocked(self):
|
||||||
|
try:
|
||||||
|
cpe = run(["rbw", "unlocked"], capture_output=True)
|
||||||
|
except Exception as exc:
|
||||||
|
return False
|
||||||
|
return cpe.returncode == 0
|
||||||
|
|
||||||
|
def get_key(
|
||||||
|
self,
|
||||||
|
key_bitwarden: str,
|
||||||
|
multiple: bool,
|
||||||
|
):
|
||||||
|
keys = []
|
||||||
|
items = run_commandline(["rbw", "search", key_bitwarden]).strip()
|
||||||
|
if items:
|
||||||
|
items = items.split("\n")
|
||||||
|
else:
|
||||||
|
items = []
|
||||||
|
for item in items:
|
||||||
|
if "@" in item:
|
||||||
|
keys.append(item.split("@", 1)[-1])
|
||||||
|
else:
|
||||||
|
keys.append(item.rsplit("/", 1)[-1])
|
||||||
|
if not multiple:
|
||||||
|
if not items:
|
||||||
|
return []
|
||||||
|
if len(items) > 1:
|
||||||
|
return [{"name": key} for key in keys]
|
||||||
|
keys = [key_bitwarden]
|
||||||
|
datas = []
|
||||||
|
for key in keys:
|
||||||
|
data = loads(
|
||||||
|
run_commandline(
|
||||||
|
["rbw", "get", key, "--raw", "--ignorecase"]
|
||||||
|
).strip()
|
||||||
|
)
|
||||||
|
datas.append({"name": key, "login": data["data"]})
|
||||||
|
return datas
|
||||||
|
|
||||||
|
|
||||||
|
class BW:
|
||||||
|
def unlocked(self):
|
||||||
|
try:
|
||||||
|
cpe = run(["bw", "status"], capture_output=True)
|
||||||
|
except Exception as exc:
|
||||||
|
return False
|
||||||
|
if cpe.returncode != 0:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
data = loads(cpe.stdout.decode("utf8"))
|
||||||
|
if data["status"] == "unlocked":
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_key(
|
||||||
|
self,
|
||||||
|
key_bitwarden: str,
|
||||||
|
*args,
|
||||||
|
):
|
||||||
|
return loads(
|
||||||
|
run_commandline(
|
||||||
|
["bw", "list", "items", "--search", key_bitwarden, "--nointeraction"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class RougailUserDataBitwarden:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
config: "Config",
|
||||||
|
*,
|
||||||
|
rougailconfig: "RougailConfig" = None,
|
||||||
|
):
|
||||||
|
# this is the tiramisu config object
|
||||||
|
self.config = config
|
||||||
|
if rougailconfig is None:
|
||||||
|
from rougail.config import RougailConfig
|
||||||
|
|
||||||
|
rougailconfig = RougailConfig
|
||||||
|
user_data = rougailconfig["step.user_data"]
|
||||||
|
if "bitwarden" not in user_data:
|
||||||
|
user_data.append("bitwarden")
|
||||||
|
rougailconfig["step.user_data"] = user_data
|
||||||
|
else:
|
||||||
|
user_data = rougailconfig["step.user_data"]
|
||||||
|
self.rougailconfig = rougailconfig
|
||||||
|
if "bitwarden" not in user_data:
|
||||||
|
raise ExtensionError(_('"bitwarden" is not set in step.user_data'))
|
||||||
|
self.errors = []
|
||||||
|
self.warnings = []
|
||||||
|
self.leader_informations = {}
|
||||||
|
self.commands = {'rbw': RBW(),
|
||||||
|
'bw': BW(),
|
||||||
|
}
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
values = {}
|
||||||
|
self.command = self.get_command()
|
||||||
|
self.set_passwords(self.config.unrestraint, values)
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"source": 'Bitwarden',
|
||||||
|
"errors": self.errors,
|
||||||
|
"warnings": self.warnings,
|
||||||
|
"values": values,
|
||||||
|
"options": {
|
||||||
|
"secret_manager": True,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_command(self):
|
||||||
|
if self.rougailconfig["bitwarden.mock_enable"]:
|
||||||
|
return FakeBW()
|
||||||
|
one_is_find = False
|
||||||
|
for command_name in self.rougailconfig["bitwarden.command"]:
|
||||||
|
if not which(command_name):
|
||||||
|
continue
|
||||||
|
command = self.commands[command_name]
|
||||||
|
if not command.unlocked():
|
||||||
|
one_is_find = True
|
||||||
|
continue
|
||||||
|
return command
|
||||||
|
if one_is_find:
|
||||||
|
msg = _("please unlock Bitwarden password database with {0} command line")
|
||||||
|
else:
|
||||||
|
msg = _("cannot find Bitwarden command line {0} please install it")
|
||||||
|
raise ExtensionError(msg.format(display_list(list(self.commands))))
|
||||||
|
|
||||||
|
def set_passwords(self, optiondescription, values):
|
||||||
|
for option in optiondescription.list(uncalculated=True):
|
||||||
|
if option.isoptiondescription():
|
||||||
|
self.set_passwords(option, values)
|
||||||
|
elif option.information.get("bitwarden", False):
|
||||||
|
values[option.path(uncalculated=True)] = (set_password, self.leader_informations, self.command)
|
||||||
|
|
||||||
|
|
||||||
|
def set_password(leader_informations, command, *, option):
|
||||||
|
path = option.path()
|
||||||
|
leader_key = None
|
||||||
|
if option.isfollower():
|
||||||
|
leader_path = option.parent().leader().path()
|
||||||
|
if leader_path in leader_informations:
|
||||||
|
leader_key = leader_informations[leader_path][option.index()]
|
||||||
|
if not option.isleader():
|
||||||
|
return get_values(command, option, leader_key=leader_key)
|
||||||
|
leader_informations[path], option_values = get_values(
|
||||||
|
command, option, multiple=True, leader_key=option.value.default()[0]
|
||||||
|
)
|
||||||
|
return option_values
|
||||||
|
|
||||||
|
|
||||||
|
def get_values(command, option, *, multiple=False, leader_key=None):
|
||||||
|
if leader_key:
|
||||||
|
key = leader_key
|
||||||
|
else:
|
||||||
|
key = option.value.default()
|
||||||
|
type_ = option.information.get("type")
|
||||||
|
if "validator" not in option.property.get():
|
||||||
|
option.property.add("validator")
|
||||||
|
if not isinstance(key, str):
|
||||||
|
raise ConfigError(
|
||||||
|
_('the default value must be the Bitwarden item name')
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
data = command.get_key(key, multiple)
|
||||||
|
except Exception as exc:
|
||||||
|
raise ConfigError(
|
||||||
|
_(
|
||||||
|
'cannot execute the "{0}" commandline from Bitwarden: {1}'
|
||||||
|
).format(command, exc)
|
||||||
|
)
|
||||||
|
if not data:
|
||||||
|
raise ConfigError(
|
||||||
|
_('item "{0}" in Bitwarden is not found"').format(
|
||||||
|
key
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if len(data) != 1:
|
||||||
|
names = [d["name"] for d in data]
|
||||||
|
if multiple:
|
||||||
|
ret = []
|
||||||
|
return names, [
|
||||||
|
get_value(key, type_, d) for d in data
|
||||||
|
]
|
||||||
|
raise ConfigError(
|
||||||
|
_(
|
||||||
|
'several items found with name "{0}" in Bitwarden: "{1}"'
|
||||||
|
).format(key, '", "'.join(names))
|
||||||
|
)
|
||||||
|
value = get_value(key, type_, data[0])
|
||||||
|
if multiple:
|
||||||
|
return [data[0]["name"]], [value]
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def get_value( key_bitwarden: str, type_: str, data: dict) -> str:
|
||||||
|
try:
|
||||||
|
if type_ == "secret":
|
||||||
|
value = data["login"]["password"]
|
||||||
|
else:
|
||||||
|
value = data["login"]["username"]
|
||||||
|
except Exception as exc:
|
||||||
|
raise ConfigError(
|
||||||
|
_('unexpected datas "{0}" from Bitwarden: {2}').format(
|
||||||
|
key_bitwarden, exc
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
if value is None:
|
||||||
|
if type_ == "secret":
|
||||||
|
bw_type = _("password")
|
||||||
|
else:
|
||||||
|
bw_type = _("username")
|
||||||
|
raise ConfigError(
|
||||||
|
_('item "{0}" in Bitwarden has no {1}').format(
|
||||||
|
key_bitwarden, bw_type
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def run_commandline(cmd) -> str:
|
||||||
|
cpe = run(cmd, capture_output=True)
|
||||||
|
returncode = cpe.returncode
|
||||||
|
err = cpe.stderr.decode("utf8")
|
||||||
|
if returncode != 0 or err:
|
||||||
|
raise ExtensionError("{0} ({1})".format(err, returncode))
|
||||||
|
return cpe.stdout.decode("utf8")
|
||||||
26
src/rougail/user_data_bitwarden/i18n.py
Normal file
26
src/rougail/user_data_bitwarden/i18n.py
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
"""
|
||||||
|
Silique (https://www.silique.fr)
|
||||||
|
Copyright (C) 2025
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
|
details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from gettext import translation
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
t = translation(
|
||||||
|
"rougail_user_data_bitwarden", str(Path(__file__).parent / "locale"), fallback=True
|
||||||
|
)
|
||||||
|
|
||||||
|
_ = t.gettext
|
||||||
Binary file not shown.
4
tests/results/1_secret/errors/bitwarden.json
Normal file
4
tests/results/1_secret/errors/bitwarden.json
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
4
tests/results/1_secret/errors/bitwarden_env.json
Normal file
4
tests/results/1_secret/errors/bitwarden_env.json
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
3
tests/results/1_secret/makedict/bitwarden.json
Normal file
3
tests/results/1_secret/makedict/bitwarden.json
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"rougail.secret": "bitwarden_password"
|
||||||
|
}
|
||||||
3
tests/results/1_secret/makedict/bitwarden_env.json
Normal file
3
tests/results/1_secret/makedict/bitwarden_env.json
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"rougail.secret": "Ex4mpL3_P4ssw0rD"
|
||||||
|
}
|
||||||
6
tests/results/1_secret_unknown/errors/bitwarden.json
Normal file
6
tests/results/1_secret_unknown/errors/bitwarden.json
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"errors": [
|
||||||
|
"item \"1_secret_unknown - environment - service - user\" in Bitwarden is not found for \"rougail.secret\""
|
||||||
|
],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
4
tests/results/1_secret_unknown/errors/bitwarden_env.json
Normal file
4
tests/results/1_secret_unknown/errors/bitwarden_env.json
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
3
tests/results/1_secret_unknown/makedict/bitwarden.json
Normal file
3
tests/results/1_secret_unknown/makedict/bitwarden.json
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"rougail.secret": null
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"rougail.secret": "Ex4mpL3_P4ssw0rD"
|
||||||
|
}
|
||||||
4
tests/results/2_username_secret/errors/bitwarden.json
Normal file
4
tests/results/2_username_secret/errors/bitwarden.json
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
4
tests/results/2_username_secret/makedict/bitwarden.json
Normal file
4
tests/results/2_username_secret/makedict/bitwarden.json
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"rougail.username": "bitwarden_username",
|
||||||
|
"rougail.secret": "bitwarden_password"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"rougail.username": "example_login",
|
||||||
|
"rougail.secret": "Ex4mpL3_P4ssw0rD"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"rougail.username": "up_secret_error_1",
|
||||||
|
"rougail.secret": "up_secret_error_pass_1"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"rougail.username": "example_login",
|
||||||
|
"rougail.secret": "Ex4mpL3_P4ssw0rD"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"rougail.username": "bitwarden_username",
|
||||||
|
"rougail.secret": "bitwarden_password"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"rougail.username": "example_login",
|
||||||
|
"rougail.secret": "Ex4mpL3_P4ssw0rD"
|
||||||
|
}
|
||||||
4
tests/results/3_leadership_secret/errors/bitwarden.json
Normal file
4
tests/results/3_leadership_secret/errors/bitwarden.json
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
12
tests/results/3_leadership_secret/makedict/bitwarden.json
Normal file
12
tests/results/3_leadership_secret/makedict/bitwarden.json
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"rougail.leader.username": [
|
||||||
|
{
|
||||||
|
"rougail.leader.username": "bitwarden_username",
|
||||||
|
"rougail.leader.secret": "bitwarden_password"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rougail.leader.username": "bitwarden_username_2",
|
||||||
|
"rougail.leader.secret": "bitwarden_password_2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"rougail.leader.username": [
|
||||||
|
{
|
||||||
|
"rougail.leader.username": "example_login",
|
||||||
|
"rougail.leader.secret": "Ex4mpL3_P4ssw0rD"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"rougail.leader.username": [
|
||||||
|
{
|
||||||
|
"rougail.leader.username": "bitwarden_username",
|
||||||
|
"rougail.leader.secret": "bitwarden_password"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rougail.leader.username": "bitwarden_username_2",
|
||||||
|
"rougail.leader.secret": "bitwarden_password_2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"rougail.leader.username": [
|
||||||
|
{
|
||||||
|
"rougail.leader.username": "bitwarden_username_2",
|
||||||
|
"rougail.leader.secret": "bitwarden_password_2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"rougail.leader.username": "bitwarden_username",
|
||||||
|
"rougail.leader.secret": "bitwarden_password"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"rougail.leader.username": [
|
||||||
|
{
|
||||||
|
"rougail.leader.username": "example_login",
|
||||||
|
"rougail.leader.secret": "Ex4mpL3_P4ssw0rD"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
6
tests/results/4_several_secrets/errors/bitwarden.json
Normal file
6
tests/results/4_several_secrets/errors/bitwarden.json
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"errors": [
|
||||||
|
"several items found with name \"4_several_secrets - environment - service - user\" in Bitwarden for \"rougail.secret\": \"4_several_secrets - environment - service - user_1\", \"4_several_secrets - environment - service - user_2\""
|
||||||
|
],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
3
tests/results/4_several_secrets/makedict/bitwarden.json
Normal file
3
tests/results/4_several_secrets/makedict/bitwarden.json
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"rougail.secret": null
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"rougail.secret": "Ex4mpL3_P4ssw0rD"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"errors": [
|
||||||
|
"several items found with name \"3_leadership_secret - ENVIRONMENT - SERVICE - USER\" in Bitwarden for \"rougail.secret\": \"3_leadership_secret - environment - service - user_1\", \"3_leadership_secret - environment - service - user_2\""
|
||||||
|
],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"rougail.secret": null
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"rougail.secret": "Ex4mpL3_P4ssw0rD"
|
||||||
|
}
|
||||||
4
tests/results/5_secret_calc/errors/bitwarden.json
Normal file
4
tests/results/5_secret_calc/errors/bitwarden.json
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
4
tests/results/5_secret_calc/errors/bitwarden_env.json
Normal file
4
tests/results/5_secret_calc/errors/bitwarden_env.json
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
10
tests/results/5_secret_calc/makedict/bitwarden.json
Normal file
10
tests/results/5_secret_calc/makedict/bitwarden.json
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"rougail.host": "test",
|
||||||
|
"rougail.project": "5_secret_calc",
|
||||||
|
"rougail.environment": "environment",
|
||||||
|
"rougail.service": "service",
|
||||||
|
"rougail.user": "user_1",
|
||||||
|
"rougail.secret": "bitwarden_password",
|
||||||
|
"rougail.dyn_user_1.secret": "bitwarden_password",
|
||||||
|
"rougail.dyn_user_2.secret": "bitwarden_password_2"
|
||||||
|
}
|
||||||
10
tests/results/5_secret_calc/makedict/bitwarden_env.json
Normal file
10
tests/results/5_secret_calc/makedict/bitwarden_env.json
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"rougail.host": "test",
|
||||||
|
"rougail.project": "5_secret_calc",
|
||||||
|
"rougail.environment": "environment",
|
||||||
|
"rougail.service": "service",
|
||||||
|
"rougail.user": "user_1",
|
||||||
|
"rougail.secret": "Ex4mpL3_P4ssw0rD",
|
||||||
|
"rougail.dyn_user_1.secret": "Ex4mpL3_P4ssw0rD",
|
||||||
|
"rougail.dyn_user_2.secret": "Ex4mpL3_P4ssw0rD"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": [
|
||||||
|
"variable or family \"rougail.modified_variable_single\" does not exist, it will be ignored when loading from By Hand"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"rougail.host": "test",
|
||||||
|
"rougail.project": "5_secret_calc",
|
||||||
|
"rougail.environment": "environment",
|
||||||
|
"rougail.service": "service",
|
||||||
|
"rougail.modified_variable": [
|
||||||
|
"user_1",
|
||||||
|
"user_2"
|
||||||
|
],
|
||||||
|
"rougail.dyn_user_1.secret": "bitwarden_password",
|
||||||
|
"rougail.dyn_user_2.secret": "bitwarden_password_2"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": [
|
||||||
|
"variable or family \"rougail.modified_variable\" does not exist, it will be ignored when loading from By Hand"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"rougail.host": "test",
|
||||||
|
"rougail.project": "5_secret_calc",
|
||||||
|
"rougail.environment": "environment",
|
||||||
|
"rougail.service": "service",
|
||||||
|
"rougail.modified_variable_single": "user_2",
|
||||||
|
"rougail.secret": "bitwarden_password_2"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"errors": [],
|
||||||
|
"warnings": [
|
||||||
|
"variable or family \"rougail.modified_variable\" does not exist, it will be ignored when loading from By Hand"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"rougail.modified_variable_single": "user_2",
|
||||||
|
"rougail.secret": "bitwarden_password_2"
|
||||||
|
}
|
||||||
6
tests/results/6_no_username/errors/bitwarden.json
Normal file
6
tests/results/6_no_username/errors/bitwarden.json
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"errors": [
|
||||||
|
"item \"6_no_username - environment - service - user_1\" in Bitwarden has no username for \"rougail.username\""
|
||||||
|
],
|
||||||
|
"warnings": []
|
||||||
|
}
|
||||||
4
tests/results/6_no_username/makedict/bitwarden.json
Normal file
4
tests/results/6_no_username/makedict/bitwarden.json
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"rougail.username": null,
|
||||||
|
"rougail.secret": "ET6RrpdZv5bNZu"
|
||||||
|
}
|
||||||
12
tests/structures/1_secret/00-base.yml
Normal file
12
tests/structures/1_secret/00-base.yml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
secret:
|
||||||
|
description: the second variable
|
||||||
|
type: secret
|
||||||
|
secret_manager:
|
||||||
|
host: test
|
||||||
|
project: 1_secret
|
||||||
|
environment: environment
|
||||||
|
service: service
|
||||||
|
user: user
|
||||||
12
tests/structures/1_secret_unknown/00-base.yml
Normal file
12
tests/structures/1_secret_unknown/00-base.yml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
secret:
|
||||||
|
description: the second variable
|
||||||
|
type: secret
|
||||||
|
secret_manager:
|
||||||
|
host: test
|
||||||
|
project: 1_secret_unknown
|
||||||
|
environment: environment
|
||||||
|
service: service
|
||||||
|
user: user
|
||||||
22
tests/structures/2_username_secret/00-base.yml
Normal file
22
tests/structures/2_username_secret/00-base.yml
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
username:
|
||||||
|
description: the username
|
||||||
|
type: unix_user
|
||||||
|
secret_manager:
|
||||||
|
host: test
|
||||||
|
project: 2_username_secret
|
||||||
|
environment: environment
|
||||||
|
service: service
|
||||||
|
user: user_1
|
||||||
|
|
||||||
|
secret:
|
||||||
|
description: the secret
|
||||||
|
type: secret
|
||||||
|
secret_manager:
|
||||||
|
host: test
|
||||||
|
project: 2_username_secret
|
||||||
|
environment: environment
|
||||||
|
service: service
|
||||||
|
user: user_1
|
||||||
22
tests/structures/2_username_secret_invalid/00-base.yml
Normal file
22
tests/structures/2_username_secret_invalid/00-base.yml
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
username:
|
||||||
|
description: the username
|
||||||
|
type: unix_user
|
||||||
|
secret_manager:
|
||||||
|
host: test
|
||||||
|
project: 2_username_secret_invalid
|
||||||
|
environment: environment
|
||||||
|
service: service
|
||||||
|
user: UP SECRET 1
|
||||||
|
|
||||||
|
secret:
|
||||||
|
description: the secret
|
||||||
|
type: secret
|
||||||
|
secret_manager:
|
||||||
|
host: test
|
||||||
|
project: 2_username_secret_invalid
|
||||||
|
environment: environment
|
||||||
|
service: service
|
||||||
|
user: UP SECRET 1
|
||||||
22
tests/structures/2_username_secret_upper/00-base.yml
Normal file
22
tests/structures/2_username_secret_upper/00-base.yml
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
username:
|
||||||
|
description: the username
|
||||||
|
type: unix_user
|
||||||
|
secret_manager:
|
||||||
|
host: TEST
|
||||||
|
project: 2_USERNAME_SECRET_UPPER
|
||||||
|
environment: ENVIRONMENT
|
||||||
|
service: SERVICE
|
||||||
|
user: USER_1
|
||||||
|
|
||||||
|
secret:
|
||||||
|
description: the secret
|
||||||
|
type: secret
|
||||||
|
secret_manager:
|
||||||
|
host: TEST
|
||||||
|
project: 2_USERNAME_SECRET_UPPER
|
||||||
|
environment: ENVIRONMENT
|
||||||
|
service: SERVICE
|
||||||
|
user: USER_1
|
||||||
25
tests/structures/3_leadership_secret/00-base.yml
Normal file
25
tests/structures/3_leadership_secret/00-base.yml
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
leader:
|
||||||
|
type: leadership
|
||||||
|
|
||||||
|
username:
|
||||||
|
description: the username
|
||||||
|
type: unix_user
|
||||||
|
secret_manager:
|
||||||
|
host: test
|
||||||
|
project: 3_leadership_secret
|
||||||
|
environment: environment
|
||||||
|
service: service
|
||||||
|
user: user
|
||||||
|
|
||||||
|
secret:
|
||||||
|
description: the secret
|
||||||
|
type: secret
|
||||||
|
secret_manager:
|
||||||
|
host: test
|
||||||
|
project: 3_leadership_secret
|
||||||
|
environment: environment
|
||||||
|
service: service
|
||||||
|
user: user
|
||||||
25
tests/structures/3_leadership_secret_several/00-base.yml
Normal file
25
tests/structures/3_leadership_secret_several/00-base.yml
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
leader:
|
||||||
|
type: leadership
|
||||||
|
|
||||||
|
username:
|
||||||
|
description: the username
|
||||||
|
type: unix_user
|
||||||
|
secret_manager:
|
||||||
|
host: test
|
||||||
|
project: 3_leadership_secret_several
|
||||||
|
environment: environment
|
||||||
|
service: service
|
||||||
|
user: user
|
||||||
|
|
||||||
|
secret:
|
||||||
|
description: the secret
|
||||||
|
type: secret
|
||||||
|
secret_manager:
|
||||||
|
host: test
|
||||||
|
project: 3_leadership_secret_several
|
||||||
|
environment: environment
|
||||||
|
service: service
|
||||||
|
user: user
|
||||||
12
tests/structures/4_several_secrets/00-base.yml
Normal file
12
tests/structures/4_several_secrets/00-base.yml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
secret:
|
||||||
|
description: the second variable
|
||||||
|
type: secret
|
||||||
|
secret_manager:
|
||||||
|
host: test
|
||||||
|
project: 4_several_secrets
|
||||||
|
environment: environment
|
||||||
|
service: service
|
||||||
|
user: user
|
||||||
12
tests/structures/4_several_secrets_upper/00-base.yml
Normal file
12
tests/structures/4_several_secrets_upper/00-base.yml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
secret:
|
||||||
|
description: the second variable
|
||||||
|
type: secret
|
||||||
|
secret_manager:
|
||||||
|
host: test
|
||||||
|
project: 3_leadership_secret
|
||||||
|
environment: ENVIRONMENT
|
||||||
|
service: SERVICE
|
||||||
|
user: USER
|
||||||
57
tests/structures/5_secret_calc/00-base.yml
Normal file
57
tests/structures/5_secret_calc/00-base.yml
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
host:
|
||||||
|
description: hostname
|
||||||
|
default: test
|
||||||
|
|
||||||
|
project:
|
||||||
|
description: the project
|
||||||
|
default: 5_secret_calc
|
||||||
|
|
||||||
|
environment:
|
||||||
|
description: the environment
|
||||||
|
default: environment
|
||||||
|
|
||||||
|
service:
|
||||||
|
description: the service
|
||||||
|
default: service
|
||||||
|
|
||||||
|
user:
|
||||||
|
description: the user
|
||||||
|
default: user_1
|
||||||
|
|
||||||
|
secret:
|
||||||
|
description: the secret
|
||||||
|
type: secret
|
||||||
|
secret_manager:
|
||||||
|
host:
|
||||||
|
variable: _.host
|
||||||
|
project:
|
||||||
|
variable: _.project
|
||||||
|
environment:
|
||||||
|
variable: _.environment
|
||||||
|
service:
|
||||||
|
variable: _.service
|
||||||
|
user:
|
||||||
|
variable: _.user
|
||||||
|
|
||||||
|
dyn_{{ identifier }}:
|
||||||
|
dynamic:
|
||||||
|
- user_1
|
||||||
|
- user_2
|
||||||
|
|
||||||
|
secret:
|
||||||
|
description: the second secret
|
||||||
|
type: secret
|
||||||
|
secret_manager:
|
||||||
|
host:
|
||||||
|
variable: __.host
|
||||||
|
project:
|
||||||
|
variable: __.project
|
||||||
|
environment:
|
||||||
|
variable: __.environment
|
||||||
|
service:
|
||||||
|
variable: __.service
|
||||||
|
user:
|
||||||
|
type: identifier
|
||||||
39
tests/structures/5_secret_calc_other_user_data/00-base.yml
Normal file
39
tests/structures/5_secret_calc_other_user_data/00-base.yml
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
host:
|
||||||
|
description: hostname
|
||||||
|
default: test
|
||||||
|
|
||||||
|
project:
|
||||||
|
description: the project
|
||||||
|
default: 5_secret_calc
|
||||||
|
|
||||||
|
environment:
|
||||||
|
description: the environment
|
||||||
|
default: environment
|
||||||
|
|
||||||
|
service:
|
||||||
|
description: the service
|
||||||
|
default: service
|
||||||
|
|
||||||
|
modified_variable: [] # a variable modified
|
||||||
|
|
||||||
|
dyn_{{ identifier }}:
|
||||||
|
dynamic:
|
||||||
|
variable: _.modified_variable
|
||||||
|
|
||||||
|
secret:
|
||||||
|
description: the second secret
|
||||||
|
type: secret
|
||||||
|
secret_manager:
|
||||||
|
host:
|
||||||
|
variable: __.host
|
||||||
|
project:
|
||||||
|
variable: __.project
|
||||||
|
environment:
|
||||||
|
variable: __.environment
|
||||||
|
service:
|
||||||
|
variable: __.service
|
||||||
|
user:
|
||||||
|
type: identifier
|
||||||
35
tests/structures/5_secret_calc_other_user_data2/00-base.yml
Normal file
35
tests/structures/5_secret_calc_other_user_data2/00-base.yml
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
host:
|
||||||
|
description: hostname
|
||||||
|
default: test
|
||||||
|
|
||||||
|
project:
|
||||||
|
description: the project
|
||||||
|
default: 5_secret_calc
|
||||||
|
|
||||||
|
environment:
|
||||||
|
description: the environment
|
||||||
|
default: environment
|
||||||
|
|
||||||
|
service:
|
||||||
|
description: the service
|
||||||
|
default: service
|
||||||
|
|
||||||
|
modified_variable_single: # a variable modified
|
||||||
|
|
||||||
|
secret:
|
||||||
|
description: the second secret
|
||||||
|
type: secret
|
||||||
|
secret_manager:
|
||||||
|
host:
|
||||||
|
variable: _.host
|
||||||
|
project:
|
||||||
|
variable: _.project
|
||||||
|
environment:
|
||||||
|
variable: _.environment
|
||||||
|
service:
|
||||||
|
variable: _.service
|
||||||
|
user:
|
||||||
|
variable: _.modified_variable_single
|
||||||
41
tests/structures/5_secret_calc_other_user_data3/00-base.yml
Normal file
41
tests/structures/5_secret_calc_other_user_data3/00-base.yml
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
host:
|
||||||
|
description: hostname
|
||||||
|
default: test
|
||||||
|
hidden: true
|
||||||
|
|
||||||
|
project:
|
||||||
|
description: the project
|
||||||
|
default: 5_secret_calc
|
||||||
|
hidden: true
|
||||||
|
|
||||||
|
environment:
|
||||||
|
description: the environment
|
||||||
|
default: environment
|
||||||
|
hidden: true
|
||||||
|
|
||||||
|
service:
|
||||||
|
description: the service
|
||||||
|
default: service
|
||||||
|
hidden: true
|
||||||
|
|
||||||
|
modified_variable_single: # a variable modified
|
||||||
|
|
||||||
|
secret:
|
||||||
|
description: the second secret
|
||||||
|
type: secret
|
||||||
|
secret_manager:
|
||||||
|
host:
|
||||||
|
variable: _.host
|
||||||
|
project:
|
||||||
|
variable: _.project
|
||||||
|
environment:
|
||||||
|
variable: _.environment
|
||||||
|
service:
|
||||||
|
variable: _.service
|
||||||
|
user:
|
||||||
|
variable: _.modified_variable_single
|
||||||
|
...
|
||||||
22
tests/structures/6_no_username/00-base.yml
Normal file
22
tests/structures/6_no_username/00-base.yml
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
username:
|
||||||
|
description: the username
|
||||||
|
type: unix_user
|
||||||
|
secret_manager:
|
||||||
|
host: test
|
||||||
|
project: 6_no_username
|
||||||
|
environment: environment
|
||||||
|
service: service
|
||||||
|
user: user_1
|
||||||
|
|
||||||
|
secret:
|
||||||
|
description: the secret
|
||||||
|
type: secret
|
||||||
|
secret_manager:
|
||||||
|
host: test
|
||||||
|
project: 6_no_username
|
||||||
|
environment: environment
|
||||||
|
service: service
|
||||||
|
user: user_1
|
||||||
13
tests/structures/8_multi_variable/00-base.yml
Normal file
13
tests/structures/8_multi_variable/00-base.yml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
secret:
|
||||||
|
description: the secret variable
|
||||||
|
type: secret
|
||||||
|
multi: true
|
||||||
|
secret_manager:
|
||||||
|
host: test
|
||||||
|
project: 8_multi_variable
|
||||||
|
environment: environment
|
||||||
|
service: service
|
||||||
|
user: user
|
||||||
12
tests/structures/9_unknown_type/00-base.yml
Normal file
12
tests/structures/9_unknown_type/00-base.yml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
secret:
|
||||||
|
description: the first variable
|
||||||
|
type: string
|
||||||
|
secret_manager:
|
||||||
|
host: test
|
||||||
|
project: 9_unknown_type
|
||||||
|
environment: environment
|
||||||
|
service: service
|
||||||
|
user: user
|
||||||
318
tests/test_load.py
Normal file
318
tests/test_load.py
Normal file
|
|
@ -0,0 +1,318 @@
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
from rougail import Rougail, RougailConfig
|
||||||
|
from rougail.error import DictConsistencyError
|
||||||
|
#########################
|
||||||
|
from rougail.user_data_bitwarden import RougailUserDataBitwarden as RougailUserData
|
||||||
|
from json import load, dump
|
||||||
|
#########################
|
||||||
|
from pytest import raises
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
|
||||||
|
from rougail_tests.utils import config_to_dict
|
||||||
|
|
||||||
|
|
||||||
|
test_dir = Path(__file__).parent / 'structures'
|
||||||
|
|
||||||
|
|
||||||
|
def _test_structural_files(test_dir, command, *, env=False, modified=False, mock=False):
|
||||||
|
rougailconfig = RougailConfig.copy()
|
||||||
|
rougailconfig['main_structural_directories'] = [str(test_dir)]
|
||||||
|
# rougailconfig['tiramisu_cache'] = "cache.py"
|
||||||
|
rougailconfig['step.user_data'] = ['bitwarden']
|
||||||
|
rougailconfig['bitwarden.command'] = [command]
|
||||||
|
if mock:
|
||||||
|
rougailconfig["bitwarden.mock_enable"] = True
|
||||||
|
rougail = Rougail(rougailconfig)
|
||||||
|
config = rougail.run()
|
||||||
|
config.property.read_write()
|
||||||
|
# loads variables in the tiramisu config
|
||||||
|
generated_user_data = RougailUserData(config, rougailconfig=rougailconfig).run()
|
||||||
|
if modified:
|
||||||
|
generated_user_data.insert(0, {'source': 'By Hand', 'errors': [], 'warnings': [], 'values': {'rougail.modified_variable': ['user_1', 'user_2'], 'rougail.modified_variable_single': 'user_2'}})
|
||||||
|
errors = rougail.user_data(generated_user_data)
|
||||||
|
#expected output
|
||||||
|
config_dict = dict(config_to_dict(config.value.get()))
|
||||||
|
if not env:
|
||||||
|
base_filename = 'bitwarden.json'
|
||||||
|
else:
|
||||||
|
base_filename = 'bitwarden_env.json'
|
||||||
|
ok_file = Path('tests') / 'results' / test_dir.name / 'makedict' / (base_filename + '.' + command)
|
||||||
|
if not ok_file.is_file():
|
||||||
|
ok_file = Path('tests') / 'results' / test_dir.name / 'makedict' / base_filename
|
||||||
|
if not ok_file.is_file():
|
||||||
|
ok_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
with open(ok_file, 'a') as json_file:
|
||||||
|
dump(config_dict, json_file, indent=4)
|
||||||
|
with open(ok_file) as json_file:
|
||||||
|
expected = load(json_file)
|
||||||
|
errors_file = Path('tests') / 'results' / test_dir.name / 'errors' / (base_filename + '.' + command)
|
||||||
|
if not errors_file.is_file():
|
||||||
|
errors_file = Path('tests') / 'results' / test_dir.name / 'errors' / base_filename
|
||||||
|
if not errors_file.is_file():
|
||||||
|
errors_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
with open(errors_file, 'a') as json_file:
|
||||||
|
dump(errors, json_file, indent=4)
|
||||||
|
with open(errors_file) as json_file:
|
||||||
|
expected_errors = load(json_file)
|
||||||
|
assert expected_errors == errors, errors_file
|
||||||
|
#
|
||||||
|
assert expected == config_dict, ok_file
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_1_secret_rbw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '1_secret', 'rbw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_1_secret_bw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '1_secret', 'bw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_1_secret_unknown_rbw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '1_secret_unknown', 'rbw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_1_secret_unknown_bw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '1_secret_unknown', 'bw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_2_username_secret_rbw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '2_username_secret', 'rbw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_2_username_secret_bw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '2_username_secret', 'bw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_2_username_secret_upper_rbw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '2_username_secret_upper', 'rbw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_2_username_secret_upper_bw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '2_username_secret_upper', 'bw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_2_username_secret_invalid_rbw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '2_username_secret_invalid', 'rbw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_2_username_secret_invalid_bw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '2_username_secret_invalid', 'bw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_3_leadership_secret_rbw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '3_leadership_secret', 'rbw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_3_leadership_secret_bw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '3_leadership_secret', 'bw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_3_leadership_secret_several_rbw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '3_leadership_secret_several', 'rbw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_3_leadership_secret_several_bw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '3_leadership_secret_several', 'bw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_4_several_secrets_rbw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '4_several_secrets', 'rbw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_4_several_secrets_bw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '4_several_secrets', 'bw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_4_several_secrets_upper_rbw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '4_several_secrets_upper', 'rbw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_4_several_secrets_upper_bw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '4_several_secrets_upper', 'bw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_5_secret_calc_rbw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '5_secret_calc', 'rbw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_5_secret_calc_bw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '5_secret_calc', 'bw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_5_secret_calc_other_user_data_rbw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '5_secret_calc_other_user_data', 'rbw', modified=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_5_secret_calc_other_user_data2_rbw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '5_secret_calc_other_user_data2', 'rbw', modified=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_5_secret_calc_other_user_data3_rbw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '5_secret_calc_other_user_data3', 'rbw', modified=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_6_no_username_rbw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '6_no_username', 'rbw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_6_no_username_bw():
|
||||||
|
"tests the output"
|
||||||
|
_test_structural_files(test_dir / '6_no_username', 'bw')
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_8_multi_variable_rbw():
|
||||||
|
"tests the output"
|
||||||
|
with raises(DictConsistencyError) as err:
|
||||||
|
_test_structural_files(test_dir / '8_multi_variable', 'rbw')
|
||||||
|
assert err.value.errno == 57
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_8_multi_variable_bw():
|
||||||
|
"tests the output"
|
||||||
|
with raises(DictConsistencyError) as err:
|
||||||
|
_test_structural_files(test_dir / '8_multi_variable', 'bw')
|
||||||
|
assert err.value.errno == 57
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_9_unknown_type_rbw():
|
||||||
|
"tests the output"
|
||||||
|
with raises(DictConsistencyError) as err:
|
||||||
|
_test_structural_files(test_dir / '9_unknown_type', 'rbw')
|
||||||
|
assert err.value.errno == 56
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_9_unknown_type_bw():
|
||||||
|
"tests the output"
|
||||||
|
with raises(DictConsistencyError) as err:
|
||||||
|
_test_structural_files(test_dir / '9_unknown_type', 'bw')
|
||||||
|
assert err.value.errno == 56
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_1_secret_rbw():
|
||||||
|
_test_structural_files(test_dir / '1_secret', 'rbw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_1_secret_bw():
|
||||||
|
_test_structural_files(test_dir / '1_secret', 'bw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_1_secret_unknown_rbw():
|
||||||
|
_test_structural_files(test_dir / '1_secret_unknown', 'rbw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_1_secret_unknown_bw():
|
||||||
|
_test_structural_files(test_dir / '1_secret_unknown', 'bw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_2_username_secret_rbw():
|
||||||
|
_test_structural_files(test_dir / '2_username_secret', 'rbw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_2_username_secret_bw():
|
||||||
|
_test_structural_files(test_dir / '2_username_secret', 'bw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_2_username_secret_upper_rbw():
|
||||||
|
_test_structural_files(test_dir / '2_username_secret_upper', 'rbw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_2_username_secret_upper_bw():
|
||||||
|
_test_structural_files(test_dir / '2_username_secret_upper', 'bw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_2_username_secret_invalid_rbw():
|
||||||
|
_test_structural_files(test_dir / '2_username_secret_invalid', 'rbw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_2_username_secret_invalid_bw():
|
||||||
|
_test_structural_files(test_dir / '2_username_secret_invalid', 'bw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_3_leadership_secret_rbw():
|
||||||
|
_test_structural_files(test_dir / '3_leadership_secret', 'rbw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_3_leadership_secret_bw():
|
||||||
|
_test_structural_files(test_dir / '3_leadership_secret', 'bw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_3_leadership_secret_several_rbw():
|
||||||
|
_test_structural_files(test_dir / '3_leadership_secret_several', 'rbw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_3_leadership_secret_several_bw():
|
||||||
|
_test_structural_files(test_dir / '3_leadership_secret_several', 'bw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_4_several_secrets_rbw():
|
||||||
|
_test_structural_files(test_dir / '4_several_secrets', 'rbw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_4_several_secrets_bw():
|
||||||
|
_test_structural_files(test_dir / '4_several_secrets', 'bw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_4_several_secrets_upper_rbw():
|
||||||
|
_test_structural_files(test_dir / '4_several_secrets_upper', 'rbw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_4_several_secrets_upper_bw():
|
||||||
|
_test_structural_files(test_dir / '4_several_secrets_upper', 'bw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_5_secret_calc_rbw():
|
||||||
|
_test_structural_files(test_dir / '5_secret_calc', 'rbw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_5_secret_calc_bw():
|
||||||
|
_test_structural_files(test_dir / '5_secret_calc', 'bw', env=True, mock=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_8_multi_variable_rbw():
|
||||||
|
with raises(DictConsistencyError) as err:
|
||||||
|
_test_structural_files(test_dir / '8_multi_variable', 'rbw', env=True, mock=True)
|
||||||
|
assert err.value.errno == 57
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_8_multi_variable_bw():
|
||||||
|
with raises(DictConsistencyError) as err:
|
||||||
|
_test_structural_files(test_dir / '8_multi_variable', 'bw', env=True, mock=True)
|
||||||
|
assert err.value.errno == 57
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_9_unknown_type_rbw():
|
||||||
|
with raises(DictConsistencyError) as err:
|
||||||
|
_test_structural_files(test_dir / '9_unknown_type', 'rbw', env=True, mock=True)
|
||||||
|
assert err.value.errno == 56
|
||||||
|
|
||||||
|
|
||||||
|
def test_structural_files_env_9_unknown_type_bw():
|
||||||
|
with raises(DictConsistencyError) as err:
|
||||||
|
_test_structural_files(test_dir / '9_unknown_type', 'bw', env=True, mock=True)
|
||||||
|
assert err.value.errno == 56
|
||||||
Loading…
Reference in a new issue