commit 7e13499798ac9d044dcf32347b6e9721600b1de9
parent 0441a4d0fbb989de97c1527afdaddcd16e43f4ec
Author: nolash <dev@holbrook.no>
Date: Sat, 17 Oct 2020 16:18:46 +0200
Add readme, test for gpg
Diffstat:
13 files changed, 281 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
@@ -0,0 +1,102 @@
+# CONFINI
+
+Configuration parser that process all sections and values in all `ini` files in a directory.
+
+## Usage
+
+```
+import confini
+
+c = confini.Config('/path/to/config/dir')
+c.process()
+
+print(c.get('FOO_BAR_BAZ'))
+
+```
+
+### Value storage
+
+The values are stored in a single key/value dictionary, with section and name separated by _underscore_ and all letters transformed to uppercase.
+
+Consider this value in an ini section:
+
+```
+[foO]
+bar_baz = 42
+```
+
+This will be stored in the `confini` store with `FOO_BAR_BAZ` as the key.
+
+### Environment overrides
+
+By default, the value of any environment variable matching a store key will overwrite the corresponding value in the store.
+
+A prefix can be provided on instantiation to define a separate namespace for environment variable overrides:
+
+```
+>>> os.environ.set('FOO_BAZ_BAZ', 666)
+>>> c = config.Config('/path/to/config/dir')
+>>> c.process()
+>>> print(c.get('FOO_BAR_BAZ'))
+666
+>>> c = config.Config('/path/to/config/dir', 'XXX')
+>>> c.process()
+>>> print(c.get('FOO_BAR_BAZ'))
+42
+>>> os.environ.set('XXX_FOO_BAZ_BAZ', 13)
+>>> c = config.Config('/path/to/config/dir', 'XXX')
+>>> c.process()
+>>> print(c.get('FOO_BAR_BAZ'))
+13
+```
+
+### Required values
+
+Keys can be set as required, and after processing independently validated:
+
+```
+>>> c = config.Config('/path/to/config/dir')
+>>> c.require('BAR_BAZ', 'FOO')
+>>> c.process()
+>>> c.validate()
+True
+>>> c = config.Config('/path/to/config/dir')
+>>> c.require('BAR_BAZ_BAZ', 'FOO')
+>>> c.process()
+>>> c.validate()
+False
+```
+
+### Censoring logs
+
+The string representation of the confini object is a list of all stored values, one on each line.
+
+Display of individual values can be suppressed:
+
+```
+>>> c = config.Config('/path/to/config/dir')
+>>> c.process()
+>>> print(c)
+FOO_BAR_BAZ = 666
+>>> c.censor('BAR_BAZ', 'FOO')
+>>> print(c)
+***
+```
+
+### Encryption
+
+Values can be **GNUPG** encrypted by saving them in individual encrypted files providing the filename as value argument wrapped in a gpg directve:
+
+```
+[foo]
+BAR_BAZ = !gpg(foo_bar_baz.asc)
+```
+
+Decryption mode must be explicitly activated:
+
+```
+>>> c = config.Config('/path/to/config/dir', decrypt=True)
+```
+The user keyring in the default location is used for decryption.
+
+
diff --git a/confini/config.py b/confini/config.py
@@ -8,6 +8,8 @@ import configparser
import re
import gnupg
+from .error import DecryptError
+
logg = logging.getLogger('confini')
current_config = None
@@ -128,7 +130,9 @@ class Config:
f = open(filename, 'rb')
logg.debug('decrypting entry {} in file {}'.format(k, f))
d = gpg.decrypt_file(f)
- v =str(d)
+ if not d.ok:
+ raise DecryptError()
+ v = str(d)
f.close()
return v
diff --git a/confini/error.py b/confini/error.py
@@ -0,0 +1,2 @@
+class DecryptError(Exception):
+ pass
diff --git a/test/files/crypt/baz.asc b/test/files/crypt/baz.asc
@@ -0,0 +1,14 @@
+-----BEGIN PGP MESSAGE-----
+
+hQGMA8Ll7MXhlLGLAQv/Skj9eYN9MuR2JLIFJ7V2BYgpdakukamW6dCEwr1dyWbq
+Uj0UurqSCJBg3qvDQvK2K/UU1ez2+Sot8i/rQY5Q7t9Daxlzp4PombtYw0R3dxLE
+bcNCEv7tIr1VjW8cRvkgKc9CamcI2zcUDt2DGq+c9w8Hxn+N7KRF1ZZLGvb7nnTU
+ugMyrQb8ILJDyw7ifjgjQFSeh5Kfg+tQAKaPTk7ydCqCXaODd1dCNE1IK/ebl8kT
+gGm0db20lcNG9MOmmumD22hTovlouv1WcybpQGzNsogkiJxMRgCQ2DRRAxWOLyam
+71iEcCb3w/xf+YISUSWkD+H1W0+2i0X6RTIVNYs/tEnI9/DypKV4wPWcsWbLsVqO
+u8wodH5Kk3f/gwVd90wjmpYMrRCIL0/GOfMn8IglN58lOMEtopRtll/CbM8XcRUc
+5vsCIcrBiZiwq6bfQxyPSVmpOsxz24BMvU537bVf5qI7KpFn5L5Gjo/Sy1Xq4rpT
+avEBM1lXrRbEqXz/fd2J0j4BInKLK3yaAkBq0pFYvCFsHOB/7n0SUkOZcFBXxGGb
+sDj+VuQr5hdhJbgyl0ZhsUvHaJQzKFn2N4cW8RQwmw==
+=qkyQ
+-----END PGP MESSAGE-----
diff --git a/test/files/crypt/foo.ini b/test/files/crypt/foo.ini
@@ -0,0 +1,3 @@
+[FOO]
+bar = 42
+baz = !gpg(baz.asc)
diff --git a/test/gnupg/openpgp-revocs.d/E3C39E57B5478DF8C9341B1FAC061DE3A30B512E.rev b/test/gnupg/openpgp-revocs.d/E3C39E57B5478DF8C9341B1FAC061DE3A30B512E.rev
@@ -0,0 +1,35 @@
+This is a revocation certificate for the OpenPGP key:
+
+pub rsa3072 2020-10-17 [SC] [expires: 2022-10-17]
+ E3C39E57B5478DF8C9341B1FAC061DE3A30B512E
+uid Confini Encrypter <dev@holbrook.no>
+
+A revocation certificate is a kind of "kill switch" to publicly
+declare that a key shall not anymore be used. It is not possible
+to retract such a revocation certificate once it has been published.
+
+Use it to revoke this key in case of a compromise or loss of
+the secret key. However, if the secret key is still accessible,
+it is better to generate a new revocation certificate and give
+a reason for the revocation. For details see the description of
+of the gpg command "--generate-revocation" in the GnuPG manual.
+
+To avoid an accidental use of this file, a colon has been inserted
+before the 5 dashes below. Remove this colon with a text editor
+before importing and publishing this revocation certificate.
+
+:-----BEGIN PGP PUBLIC KEY BLOCK-----
+Comment: This is a revocation certificate
+
+iQG2BCABCAAgFiEE48OeV7VHjfjJNBsfrAYd46MLUS4FAl+K+LACHQAACgkQrAYd
+46MLUS7HMQv8DTs3zp74XIDL4coYc4j75MkZOqTdzQea6hlz4cWuzWAkLJi2m19p
+qC4vfhT7hvhwr/3/jc1Wd1wd8JkZWRdONU9aBx6NodvjOaCXzacfIBKO7BSIuhoM
+aEsLU8tUdigUoO84tpKojIareHxhJcgRIecStPAXru0NtyS0j+z9OznIaqvHW3o9
+yGeTJoHio17nXMH4jkBXNu1PszzPrBE1ttX43sfdwP9goxY5i7oBb+nWG+yFBsBE
+168k/dQ2ZWOaInnchqA6gNBWn5R2rK1sVS0v7BDvqXwBeNEohvW4HWarVY3nekv2
+wX3UcrXlg3n8anw2awtBinmh/iZAm11k4KX5r1mAd4Hj4Dwak4DzE9ZmqZeywsMq
+ARlkJdh7aG5OWEN9eUKEjj4GVIpr4GhsZvQFTspz4g0uIGfWhTzXyq9EasSUAgLj
+De0+dVaC8UDqH5qq1K8e6fweQDodn8ZA80U08BFqeHjkziFUY7JHE+cH3c+1/x1O
+6zJxHLAjzCvE
+=m9JT
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/test/gnupg/private-keys-v1.d/31CD2D9AD1C478010F1851D4BA8A4E62473E3206.key b/test/gnupg/private-keys-v1.d/31CD2D9AD1C478010F1851D4BA8A4E62473E3206.key
@@ -0,0 +1,42 @@
+Key: (private-key (rsa (n #00C23A8EE0588FD7889AF41A196C5B20EBEBFECFE495
+ 307D818E1942121D6A15DD055150A9F98DD2D03C1C1F4E0419F5A9E781762FA5D465C9
+ 593977D90E948ACA553EF8A9C4795FE775C2CCE8E536440192BCCC46DEFE56C9D8FD42
+ E9C8681CAAEBC8EF743C8FDB391893B20EB9824ADDF249F3B298238DF1720D9F1AB787
+ 6C29FE4CDFEA27747C0C69C518857D56233793F4557C2B9B8C3F9F03B1C8BD77CD2760
+ 21BB19E8D1B7B3A02EF1DF6D2E306EB4359B4EC480D1DDB6D62DFA9B25F130C3035D48
+ 6BB0470A4DEB109B64A0461A72F93E16C7EA66AF509AF3DAA50B783FE88907956C72AB
+ 9B24471ED55793D1BFD537C11F05E6323A6E2196D52C6B23F7FCC82566294B7C08374B
+ 107A2ACB46E2518D62CC822775E3DE8273FE78DF51C7F5E18E24737ACB04F40572CD6B
+ 9BF80070D58062F6D0B4020F9D93CB015665BCDBECF9696A4A6CDF9F6CED802F63F203
+ 54B701E952CFF7F4ED3709638EF1800B482FDB9A59898E016899F3D00D78BADCF88DA9
+ 2FFDF62C7280E0544F321AB391#)(e #010001#)(d
+ #0B238D971B2D20A8C26E3662F7DE600C77ABD4E36094F7D5AABF131573DF6622974F
+ FB06CC7B903806027CDF1E08191925E03C556E36B8A1ABFECA3B460549D261C22B439D
+ 3372C714EF578E11BB237A4D9E8B3E934255DADC9965B17F9F4CE9967D1F1274F8B113
+ 5CAFF7B9B574DDF34D966525FC68A996CBBA3142387D493C3D4BCE59A0EAA2C4997A46
+ B63D226801A3781340FC453EED5522C29AE716CC4AB24E2CEB46F9640626AD1A8CFC37
+ 766A9AE62A2281CD7B7BB225255CE671EE1B8AB6C6AA577131852540A002466077AFC1
+ 99E30B51CFA573812542C03E1E685A2F0EFF233A0340C4142901C28DC69792EFB0B683
+ 7FF7D1F55FFD4D336F791C4B55495BE2BC1F86EF91A42790EFBFA59B65226BFA19F6D1
+ 74F28FE9854BB03DC9845E2FD2EBF90D9A465FA463C737CEA33A3DC1A119DC78944456
+ CC79C683DF5C8D9E35616465A2F89D1CDDCE33678A46AB74F9800424B4AC714DD4F0B9
+ 4BDDA3630E0825DCBAB059B79B43138D43AFD5758815B148D64CAC492858EE1E0E9DEB
+ #)(p #00DABE83B906C4FF9E184D46DA7B4B081D7E80DC00F731DF14E6CD0D6D673613
+ 41CA1CFC0F86E40F9BA45AA0BEAA49191B44400872C08A7786C0522822B122B6584E66
+ 418CFDD46F9899E1A46DCC0C0EF98D7C298ED9C88679675973818F301A1F221C0B8C3C
+ 19B26F791BF57942C64CD801A3A7ED8481C4FC413A4FE9D5F417F36F0EB6F8ABBEE236
+ 69EE3C61019180CC1B03364176AF9A67CC6E9036572661D63B30CD679CD55004A85DFC
+ EF31EABD95AB73F5744DF262F8AFB945385DA5BC07#)(q
+ #00E34F249CA27D7C0CE6DC31F8DF9C47680ABBB3C596C274CB3E43324DB6E495E41B
+ 23EF4F313B2FD8E2941F4E63ECCDFE7D945DA05A3F3AB4A2D509E8AFE582CF7D911D39
+ FDA44567C6D7C8ACC0C9F4B6AFD9B45A2AACD3B5CBDE09E8471058E173B825A5E2FD68
+ 97EF0C9560B808EED33BF0FA37D6F0774C94970B08E9E24B9406D1745C1F179F9F5C6C
+ 2308F5C88505A868B4655F5D199963C971BFA4AA30AEB85F51801644AB3634E0BFE3EE
+ FC049FECA6824AE4404DD8A40D9CEF763DDDA7#)(u
+ #6147AE9A6FDDE93A57916A1711925AE6DBD37E6385F9AAC4B7F0EBA7FD75B48CB3B7
+ FFAF030420D634CCC6C91AE3EEBAD0C905D3FF657C56FFA178F81EF39EC410C63AF08E
+ 6A8292AB8E1700BF3D3E6573D4292359F4C5C43766491AFFDB801AE18C91039CEDA6FF
+ 7CC019B1F120A4AB0FB51528AD18ED3B2F87CEB6F1A6359385914430CE8A476E20AD09
+ E0C7FDDFB553F1C4B51932BF7B5051BD378B294F4B89739627270A39520717BEE45548
+ E079FAC33566A27A271745C18E081C1F1455#)))
+Created: 20201017T135858
diff --git a/test/gnupg/private-keys-v1.d/3331F234B98A55205A42C7C50FE24A5046F57913.key b/test/gnupg/private-keys-v1.d/3331F234B98A55205A42C7C50FE24A5046F57913.key
@@ -0,0 +1,42 @@
+Key: (private-key (rsa (n #00BF82D4D819E69CADF1000B78A38E848A871F610188
+ 219B41F66BB4061E5A9A9A2A389D714D3A5D737EAEB28E85B025327810D20CB914C3F9
+ 453DF7C29220B5D083D2527798226DB0640A24110F14885B65191BC833B9478D2828A2
+ 94339A183ADB8DE672B0E643D05A4E09665C682DC5F00E608306B822907BC9558BF7FA
+ FE70D71EBA0628C698515B3F0C0B9A71782262677520D3842E501477B93356BAAC017D
+ B43DF7A7F1BBD1349BB96552EDF8F763DC6FA682FE11962201682730A9BDF683F7FD1A
+ 4EC5301305418E9713238B86EF1EE31BE60629B3CF92D968942FD66F99DE5CFE1CC859
+ 69D267E62CC38A9CEBF49978B521EAF2D5E539E6E8649F66870126DAE0FE121946114B
+ 9409BCB11FE5249D90FFB2E5247ECAADAC93970D8E2E4C3DD46BCDA07A71B844A7CC7B
+ 72F96B47571AB2585C63E25BB709C7B986D7516927468896E856A7B4DA06D19BA5DFC1
+ 0C6D2F319DF7F1F97B5F03EFFE8D5E9D4F1F0FFE86A7553EA278EA29BDC86C61E08DB3
+ 1E0E3D4C430DD04D06CBF2731F#)(e #010001#)(d
+ #2C1A00D1D3051C47A21C14882F81FE5BB84A2D98A0B4BC803033153DE37791EAB696
+ 5B0B6071745BC86C8A89EF9764B97E94C10A5504C72C7C198D18AD7602E885B2C572ED
+ 01E0A8A22103B539F7CC7EDF852CB4A9D49CF990A9EAE69E0B7A50F38675EF2B759B60
+ 3BAB84D6A1A90C016D0AA28709E11574984D00FA3E9CFA431A06E567CDB40E178E1FB2
+ B2695A8003CB0D7017A31DE95C5F9A4277E41D10C7371F6EB5BD6319914FC01CAD8CAF
+ 6889EFE12F84F4DD75475185696ABCF619DC684E947837043E46CF7C3D129C6E542BDA
+ DA24672EDE88615071F0711EAFE8832D60EF8FEA4A66D20F17E19D7CBC241392BF3E28
+ 26D6CAFE8520BBAAD67452187BD01627B52D15558A76F103696102F33C76A49FFF6212
+ 169CFAFDB1E8A49676443CC1D73D03E49F5A0F03E3246C4AE4110DC57948669A34D90A
+ FE3D331F9BBBBCB22681A1C969E30F72F5F01E288248D6A6F044883A87192E633E9B13
+ 29A18EB3EF598D5C60A8365638D8F2399016A353B76B9DCFBCE075C09EC3F795D3AA01
+ #)(p #00C4C30A3ED4E3D17F8B82CA9D80CCF863308E3F0875BA6E8A20E6E4E1CA3E97
+ 5B4C3AACD677F3C8C6FBC22ED4C16116A79479F140A33176BE53B1510BD8C2E136A39C
+ 1E9360AEB1C81F2CF605D70ADCDAE4E8720FEE00627077E7875F12A5F3A5073813DDBA
+ 32D66FDF970E5EB509B39E662EA040189D39C706BCFEFC94EF1B8AC6119FE9C2621C2A
+ 8B932A0AB9A3530267D3DE843FBEBFEF130671ED9D1FFA3DEA6FC5E74BA798C6F187A2
+ 6681FED8D6B4A41271EBDC3BE4FE0AAB38BC7AA5C1#)(q
+ #00F92B18DFC2679FA9286895FDE378B17FE6E6F59C1A18B862301346C6FD7DC74553
+ BE791D1879E5D938DCA9C01E7F009B3E7D4880034127988CDD51343DB63E65809C6941
+ F4B2D08C4401CA255FE8AE9432EB735D9E74822110DD2B4BE2CF6E1D11F2954434C1F3
+ 79150661F555C9F8A5EF2C0810FCC7BCBDB601733652DA61D136E619E6F346DC9364BF
+ 5765FD9D4F2E71D9B93E6C8E4A9B83C017E82908143C4A0D70D242F89A159B1BC4D3AD
+ BCAE6C1FB883E204C02FDF91E6879322C010DF#)(u
+ #009D9B78B4BD7C932FF9639BE75FBB7095B19BE3897D3266F51B964F68193BDF313A
+ C9CA0B702BE99F66EA1F6EF6397FF2B9D66FAAFE9BD89935DA3940049FB1BA3A3142E4
+ C1B5822E8BF4EC739051536C758578B42B0ACC03D95440C5CFA2E378640AE40999EE62
+ 70725105A78718B2A69A67E13840576ACB3B8261AEAF9F9EC48B5A25EEC0A9FC2893D7
+ A749C2F506DC3F50515B2E6A643E9ABFEC762DEC49CD8D909CD696018DDBCDC9487078
+ 0C5299FA0E61E9717733C07C260FE74F4CD3#)))
+Created: 20201017T135858
diff --git a/test/gnupg/pubring.kbx b/test/gnupg/pubring.kbx
Binary files differ.
diff --git a/test/gnupg/pubring.kbx~ b/test/gnupg/pubring.kbx~
Binary files differ.
diff --git a/test/gnupg/random_seed b/test/gnupg/random_seed
Binary files differ.
diff --git a/test/gnupg/trustdb.gpg b/test/gnupg/trustdb.gpg
Binary files differ.
diff --git a/test/test_enc.py b/test/test_enc.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python
+
+import os
+import unittest
+import logging
+
+from confini import Config
+from confini.error import DecryptError
+
+logging.basicConfig(level=logging.DEBUG)
+logg = logging.getLogger()
+
+script_dir = os.path.dirname(os.path.realpath(__file__))
+gnupg_dir = os.path.join(script_dir, 'gnupg')
+
+class TestBasic(unittest.TestCase):
+
+ wd = os.path.dirname(__file__)
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_enc(self):
+ inidir = os.path.join(self.wd, 'files/crypt')
+ c = Config(inidir, decrypt=True)
+ c.process()
+ with self.assertRaises(DecryptError):
+ c.get('FOO_BAZ')
+ os.environ['GNUPGHOME'] = gnupg_dir
+ c.get('FOO_BAZ')
+
+if __name__ == '__main__':
+ unittest.main()