Adds a secrets generator and loader
secrets-tool now has a feature to both generate secrets as well as load the generated secrets in to KeyVault.
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
import logging
|
||||
import yaml
|
||||
import secrets
|
||||
import string
|
||||
from pathlib import Path
|
||||
from .auth import Auth
|
||||
from azure.keyvault.secrets import SecretClient
|
||||
|
||||
@@ -23,4 +27,83 @@ class SecretsClient(Auth):
|
||||
secret_properties = self.secret_client.list_properties_of_secrets()
|
||||
for secret in secret_properties:
|
||||
secrets.append(secret.name)
|
||||
return secrets
|
||||
return secrets
|
||||
|
||||
class SecretsLoader():
|
||||
"""
|
||||
Helper class to load secrets definition, generate
|
||||
the secrets a defined by the defintion, and then
|
||||
load the secrets in to keyvault
|
||||
"""
|
||||
def __init__(self, yaml_file: str, keyvault: object):
|
||||
assert Path(yaml_file).exists()
|
||||
self.yaml_file = yaml_file
|
||||
self.keyvault = keyvault
|
||||
self.config = dict()
|
||||
|
||||
self._load_yaml()
|
||||
self._generate_secrets()
|
||||
|
||||
def _load_yaml(self):
|
||||
with open(self.yaml_file) as handle:
|
||||
self.config = yaml.load(handle, Loader=yaml.FullLoader)
|
||||
|
||||
def _generate_secrets(self):
|
||||
secrets = GenerateSecrets(self.config).process_definition()
|
||||
self.secrets = secrets
|
||||
|
||||
def load_secrets(self):
|
||||
for key, val in self.secrets.items():
|
||||
print('{} {}'.format(key,val))
|
||||
self.keyvault.set_secret(key=key, value=val)
|
||||
|
||||
|
||||
class GenerateSecrets():
|
||||
"""
|
||||
Read the secrets definition and generate requiesite
|
||||
secrets based on the type of secret and arguments
|
||||
provided
|
||||
"""
|
||||
def __init__(self, definitions: dict):
|
||||
self.definitions = definitions
|
||||
|
||||
def process_definition(self):
|
||||
"""
|
||||
Processes a simple definiton such as the following
|
||||
```
|
||||
- postgres_root_user:
|
||||
type: 'username'
|
||||
length: 30
|
||||
- postgres_root_password:
|
||||
type: 'password'
|
||||
length: 30
|
||||
```
|
||||
This should be broken out to a function per definition type
|
||||
if the scope extends in to tokens, salts, or other specialized
|
||||
definitions.
|
||||
"""
|
||||
try:
|
||||
secrets = dict()
|
||||
for definition in self.definitions:
|
||||
key = list(definition)
|
||||
def_name = key[0]
|
||||
secret = definition[key[0]]
|
||||
assert len(str(secret['length'])) > 0
|
||||
method = getattr(self, '_generate_'+secret['type'])
|
||||
value = method(secret['length'])
|
||||
#print('{}: {}'.format(key[0], value))
|
||||
secrets.update({def_name: value})
|
||||
logger.debug('Setting secrets to: {}'.format(secrets))
|
||||
return secrets
|
||||
except KeyError as e:
|
||||
logger.error('Missing the {} key in the definition'.format(e))
|
||||
|
||||
# Types. Can be usernames, passwords, or in the future things like salted
|
||||
# tokens, uuid, or other specialized types
|
||||
def _generate_password(self, length: int):
|
||||
self.password_characters = string.ascii_letters + string.digits + string.punctuation
|
||||
return ''.join(secrets.choice(self.password_characters) for i in range(length))
|
||||
|
||||
def _generate_username(self, length: int):
|
||||
self.username_characters = string.ascii_letters
|
||||
return ''.join(secrets.choice(self.username_characters) for i in range(length))
|
||||
|
Reference in New Issue
Block a user