Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions src/ops/ansible/filter_plugins/commonfilters.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,20 @@ def flatten_tree(d, parent_key='', sep='/'):
items.append((new_key, v))
return dict(items)

def check_vault(
secret_path, key='value', vault_user=None, vault_url=None,
token=None, namespace=None, mount_point=None, auto_prompt=True):

from ops.simplevault import SimpleVault
sv = SimpleVault(
vault_user=vault_user, vault_addr=vault_url, vault_token=token,
namespace=namespace, mount_point=mount_point, auto_prompt=auto_prompt)
check_status = sv.check(secret_path, key)
# we want to return these string values because this is what Jinja2 understands
if check_status:
return "true"
return "false"

def read_vault(
secret_path, key='value', fetch_all=False, vault_user=None, vault_url=None,
token=None, namespace=None, mount_point=None, auto_prompt=True):
Expand Down Expand Up @@ -136,9 +150,9 @@ def filters(self):
'read_file': read_file,
'read_vault': read_vault,
'read_yaml': read_yaml,
'read_vault': read_vault,
'write_vault': write_vault,
'managed_vault_secret': managed_vault_secret,
'read_ssm': read_ssm,
'escape_json': escape_json
'escape_json': escape_json,
'check_vault': check_vault
}
14 changes: 14 additions & 0 deletions src/ops/cli/terraform.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
from ops.cli.parser import SubParserConfig
from ops.terraform.terraform_cmd_generator import TerraformCommandGenerator
from ops.hierarchical.composition_config_generator import TerraformConfigGenerator
from distutils.version import StrictVersion
import pkg_resources

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -136,7 +138,19 @@ def __init__(self, root_dir, cluster_config_path, cluster_config, inventory_gene
self.template = template
self.execute = execute

def check_ops_version(self):
# Check if the cluster_config has a strict requirement of OPS version
# But only if 'ops_min_version' is specified. Not all clusters configs enforce this
if "terraform" in self.cluster_config.conf:
if "ops_min_version" in self.cluster_config.conf["terraform"]:
ops_min_version = str(self.cluster_config.conf["terraform"]["ops_min_version"])
current_ops_version = [x.version for x in pkg_resources.working_set if x.project_name == "ops"][0]
if StrictVersion(current_ops_version) < StrictVersion(ops_min_version):
raise Exception("The current ops version {0} is lower than the minimum required version {1} for cluster {2}".format(
current_ops_version, ops_min_version, self.cluster_config_path))

def run(self, args):
self.check_ops_version()
if os.path.isdir(self.cluster_config_path):
return self.run_v2_integration(args)
else:
Expand Down
44 changes: 26 additions & 18 deletions src/ops/simplevault.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,31 +79,39 @@ def write_token(token=None):
raise e
else:
pass
def get(self, path, key='value', wrap_ttl=None, default=None, fetch_all=False, raise_exceptions=False, raw=False):
def get(self, path, key='value', wrap_ttl=None, default=None, fetch_all=False, raw=False):
if raw:
fetch_all = True
if fetch_all:
key=None
raw_data = self.vault_conn.secrets.kv.v2.read_secret_version(
path=path, mount_point=self.mount_point)
# move this check earlier, and, if true, return immediately
if raw:
return raw_data
data = raw_data.get('data')
if isinstance(data, dict):
if not fetch_all:
if key:
# the actual secret k v pairs are nested under another dictionary key "data"
return data.get("data").get(key, default)
else:
raise('VAULT-LIB: either key or fetch_all should be set!')

def check(self, path, key):
# somewhat boilerplate method that returns a boolean whether the provided secret exists
# and if it has the desired key, with a non-empty value
try:
raw_data = self.vault_conn.secrets.kv.v2.read_secret_version(
path=path, mount_point=self.mount_point)
# move this check earlier, and, if true, return immediately
if raw:
return raw_data
data = raw_data.get('data')
if isinstance(data, dict):
if not fetch_all:
if key:
# the actual secret k v pairs are nested under another dictionary key "data"
return data.get("data").get(key, default)
else:
raise('VAULT-LIB: either key or fetch_all should be set!')
if key not in raw_data["data"]["data"]:
return False
if raw_data["data"]["data"][key] is None:
return False
except Exception as e:
if raise_exceptions:
raise e
else:
data = default
return data
# if the provided secret path doesn't exist, return false
return False
Copy link
Contributor

@costimuraru costimuraru Aug 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we return the default value if the secret does not exist?

Never mind, I see this is in the check method.

return True

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