Skip to content

Commit e2cfe99

Browse files
authored
Enchance Vault utils (#54)
1 parent 3b6624e commit e2cfe99

File tree

3 files changed

+56
-20
lines changed

3 files changed

+56
-20
lines changed

src/ops/ansible/filter_plugins/commonfilters.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,20 @@ def flatten_tree(d, parent_key='', sep='/'):
6464
items.append((new_key, v))
6565
return dict(items)
6666

67+
def check_vault(
68+
secret_path, key='value', vault_user=None, vault_url=None,
69+
token=None, namespace=None, mount_point=None, auto_prompt=True):
70+
71+
from ops.simplevault import SimpleVault
72+
sv = SimpleVault(
73+
vault_user=vault_user, vault_addr=vault_url, vault_token=token,
74+
namespace=namespace, mount_point=mount_point, auto_prompt=auto_prompt)
75+
check_status = sv.check(secret_path, key)
76+
# we want to return these string values because this is what Jinja2 understands
77+
if check_status:
78+
return "true"
79+
return "false"
80+
6781
def read_vault(
6882
secret_path, key='value', fetch_all=False, vault_user=None, vault_url=None,
6983
token=None, namespace=None, mount_point=None, auto_prompt=True):
@@ -136,9 +150,9 @@ def filters(self):
136150
'read_file': read_file,
137151
'read_vault': read_vault,
138152
'read_yaml': read_yaml,
139-
'read_vault': read_vault,
140153
'write_vault': write_vault,
141154
'managed_vault_secret': managed_vault_secret,
142155
'read_ssm': read_ssm,
143-
'escape_json': escape_json
156+
'escape_json': escape_json,
157+
'check_vault': check_vault
144158
}

src/ops/cli/terraform.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
from ops.cli.parser import SubParserConfig
1515
from ops.terraform.terraform_cmd_generator import TerraformCommandGenerator
1616
from ops.hierarchical.composition_config_generator import TerraformConfigGenerator
17+
from distutils.version import StrictVersion
18+
import pkg_resources
1719

1820
logger = logging.getLogger(__name__)
1921

@@ -136,7 +138,19 @@ def __init__(self, root_dir, cluster_config_path, cluster_config, inventory_gene
136138
self.template = template
137139
self.execute = execute
138140

141+
def check_ops_version(self):
142+
# Check if the cluster_config has a strict requirement of OPS version
143+
# But only if 'ops_min_version' is specified. Not all clusters configs enforce this
144+
if "terraform" in self.cluster_config.conf:
145+
if "ops_min_version" in self.cluster_config.conf["terraform"]:
146+
ops_min_version = str(self.cluster_config.conf["terraform"]["ops_min_version"])
147+
current_ops_version = [x.version for x in pkg_resources.working_set if x.project_name == "ops"][0]
148+
if StrictVersion(current_ops_version) < StrictVersion(ops_min_version):
149+
raise Exception("The current ops version {0} is lower than the minimum required version {1} for cluster {2}".format(
150+
current_ops_version, ops_min_version, self.cluster_config_path))
151+
139152
def run(self, args):
153+
self.check_ops_version()
140154
if os.path.isdir(self.cluster_config_path):
141155
return self.run_v2_integration(args)
142156
else:

src/ops/simplevault.py

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -79,31 +79,39 @@ def write_token(token=None):
7979
raise e
8080
else:
8181
pass
82-
def get(self, path, key='value', wrap_ttl=None, default=None, fetch_all=False, raise_exceptions=False, raw=False):
82+
def get(self, path, key='value', wrap_ttl=None, default=None, fetch_all=False, raw=False):
8383
if raw:
8484
fetch_all = True
8585
if fetch_all:
8686
key=None
87+
raw_data = self.vault_conn.secrets.kv.v2.read_secret_version(
88+
path=path, mount_point=self.mount_point)
89+
# move this check earlier, and, if true, return immediately
90+
if raw:
91+
return raw_data
92+
data = raw_data.get('data')
93+
if isinstance(data, dict):
94+
if not fetch_all:
95+
if key:
96+
# the actual secret k v pairs are nested under another dictionary key "data"
97+
return data.get("data").get(key, default)
98+
else:
99+
raise('VAULT-LIB: either key or fetch_all should be set!')
100+
101+
def check(self, path, key):
102+
# somewhat boilerplate method that returns a boolean whether the provided secret exists
103+
# and if it has the desired key, with a non-empty value
87104
try:
88105
raw_data = self.vault_conn.secrets.kv.v2.read_secret_version(
89106
path=path, mount_point=self.mount_point)
90-
# move this check earlier, and, if true, return immediately
91-
if raw:
92-
return raw_data
93-
data = raw_data.get('data')
94-
if isinstance(data, dict):
95-
if not fetch_all:
96-
if key:
97-
# the actual secret k v pairs are nested under another dictionary key "data"
98-
return data.get("data").get(key, default)
99-
else:
100-
raise('VAULT-LIB: either key or fetch_all should be set!')
107+
if key not in raw_data["data"]["data"]:
108+
return False
109+
if raw_data["data"]["data"][key] is None:
110+
return False
101111
except Exception as e:
102-
if raise_exceptions:
103-
raise e
104-
else:
105-
data = default
106-
return data
112+
# if the provided secret path doesn't exist, return false
113+
return False
114+
return True
107115

108116
def put(self, path, value, lease=None, wrap_ttl=None):
109117
payload = {}
@@ -161,7 +169,7 @@ def __init__(
161169
display('MANAGED-SECRET: could not obtain a proper Vault connection.\n{}'.format(e.message))
162170
raise e
163171
try:
164-
self.current_data = self.sv.get(path=path, fetch_all=True, raise_exceptions=True)
172+
self.current_data = self.sv.get(path=path, fetch_all=True)
165173
except Exception as e:
166174
display('MANAGED-SECRET: could not confirm if secret at path {} does or not already exist. '
167175
'Exception was:\n{}'.format(path,e.message))

0 commit comments

Comments
 (0)