Skip to content

Commit

Permalink
easy support for all-secret file
Browse files Browse the repository at this point in the history
  • Loading branch information
dactylroot committed Jun 9, 2022
1 parent e006ade commit 7ca4253
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 8 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,15 @@ To keep secret encrypted "at rest", set a secret key environment variable *FIGKE
This will print the value of `'password'`, which is stored in `./creds.yml` and not `./conf.yml`. If the value of `'password'` is changed in either YAML file, the password will be updated in `./creds.yml` and masked from `./conf.yml` the next time the class is loaded in Python. If a secret key is present via environment variable *FIGKEY*, the values in `./creds.yml` will be encrypted using that key.
The dictionary object returned for `cfg` contains the true value.

If you want everything treated as secret, only provide a `secretpath`:

cfg = figtion.Config(defaults=defaults,secretpath='./creds.yml')

In this case no call to `mask` is needed, everything is encrypted at rest.

## Roadmap

* 0.9 - secrets store in separate location
* 1.0 - secrets store in encrypted location
* 1.0.1 - easy support for all-secret config
* 1.1 - automatic/dynamic reloading of YAML files
17 changes: 11 additions & 6 deletions figtion/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,14 @@ def __init__(self,description = None, filepath = None, defaults = None, secretpa
self._intered = None
self._masks = {}
self._verbose=verbose
self._allsecret = description == _MASK_FLAG

if secretpath:
self._intered = Config(filepath=secretpath,description=_MASK_FLAG)
if not _filepath:
self._filepath = secretpath
self._allsecret = True
else:
self._intered = Config(filepath=secretpath,description=_MASK_FLAG)

### Precedence of YAML over defaults
if defaults:
Expand Down Expand Up @@ -83,14 +88,14 @@ def _getcipherkey(self):
""" return cipherkey environment variable forced to 32-bit bytestring
return None to indicate no encryption """
key = _os.getenv("FIGKEY",default="")
if not key or self.description != _MASK_FLAG:
if not key or not self._allsecret:
return None
if len(key) > 32:
return key[:32].encode()
else:
return key.ljust(32).encode()

def load(self,verbose=True):
def load(self):
""" Load from filepath and overwrite local items. """
try:
key = self._getcipherkey()
Expand All @@ -112,9 +117,9 @@ def load(self,verbose=True):
self._recursive_strict_update(self,newstuff)
self._unmask()
except Exception as e:
if verbose and hasattr(e,'strerror') and 'No such file' in e.strerror:
if self._verbose and hasattr(e,'strerror') and 'No such file' in e.strerror:
self.dump()
print("Initialized config file {}".format(self.filepath))
print(f"Initialized config file '{self.filepath}'")
elif type(e) is UnicodeDecodeError:
raise OSError(f"Missing the encryption key for file '{self.filepath}'")
else:
Expand Down Expand Up @@ -159,7 +164,7 @@ def _unmask(self):
""" resolve hierarchy: {new_val > interred > mask} """
if not self._intered:
return
self._intered.load(verbose=False)
self._intered.load()

try:
self._masks.update(self._intered.pop('_masks'))
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
long_description = f.read()

name = 'figtion'
version = '1.0.0'
version = '1.0.1'

### include README as main package docfile
from shutil import copyfile
Expand Down
16 changes: 15 additions & 1 deletion tests/test.py → tests/test_figtion.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def test_missing_encryption_key(self):
fig = figtion.Config(defaults=self.defaults,filepath=self.confpath,secretpath=self.secretpath)
except Exception as e:
assert( type(e) == OSError )
assert( str(e).startswith("Missing an encryption key for file"))
assert( str(e).startswith("Missing the encryption key for file"))

def test_unencrypted_serialization(self):
os.environ["FIGKEY"] = ""
Expand All @@ -96,3 +96,17 @@ def test_unencrypted_serialization(self):

newfig = figtion.Config(filepath=self.openpath)
assert( newfig['password'] == self.defaults['password'] )

def test_only_secret(self):
fig = figtion.Config(defaults=self.defaults,secretpath=self.secretpath)

assert( len(fig._masks) == 0 )
assert( fig['password'] == self.defaults['password'] )

os.environ["FIGKEY"] = ""

try:
fig = figtion.Config(defaults=self.defaults,secretpath=self.secretpath)
except Exception as e:
assert( type(e) == OSError )
assert( str(e).startswith("Missing the encryption key for file"))

0 comments on commit 7ca4253

Please sign in to comment.