def take_action(self, parsed_args): secrets_basedir = self.app.secrets_basedir if parsed_args.alias is not None: if len(parsed_args.env) != 1: raise RuntimeError( '[-] --alias requires one source environment') se = SecretsEnvironment( environment=parsed_args.alias, secrets_basedir=secrets_basedir, create_root=parsed_args.force, ) se.environment_create( source=parsed_args.env[0], alias=True ) if se.environment_exists(): self.logger.info( "[+] environment '%s' aliased to '%s'", parsed_args.alias, parsed_args.env[0] ) else: raise RuntimeError('[-] creating environment failed') else: # Default to app environment identifier if len(parsed_args.env) == 0: parsed_args.env = list(self.app.environment) for environment in parsed_args.env: se = SecretsEnvironment( environment=environment, secrets_basedir=secrets_basedir, create_root=True, ) se.environment_create(source=parsed_args.clone_from) self.logger.info( "[+] environment '%s' (%s) created", environment, se.get_environment_path() ) if parsed_args.clone_from: se.read_secrets(from_descriptions=True) se.write_secrets()
def take_action(self, parsed_args): if (len(parsed_args.arg) == 0 and not parsed_args.undefined and not parsed_args.from_options): raise RuntimeError('[-] no secrets specified to be set') se = self.app.secrets se.requires_environment() se.read_secrets_and_descriptions() # TODO(dittrich): Use Variable map like this elsewhere variables = dict(se.Variable) types = dict(se.Type) from_env = None if parsed_args.from_environment is not None: from_env = SecretsEnvironment( environment=parsed_args.from_environment) from_env.read_secrets() variables = dict(from_env._secrets.Variable) types = dict(from_env._secrets.Type) args = (list(variables.keys()) if len(parsed_args.arg) == 0 else parsed_args.arg) if parsed_args.undefined and len(variables) > 0: # Downselect to just those currently undefined args = [k for k, v in variables.items() if v in [None, '']] if len(args) == 0: raise RuntimeError('[-] no secrets identified to be set') for arg in args: k, v, k_type = None, None, None if parsed_args.from_options: k, v, k_type = (arg, se.get_default_value(arg), types.get(arg)) # Don't set from options if the type is generable if is_generable(k_type): continue elif '=' not in arg: # No value was specified with the argument k = arg k_type = se.secrets.get_type(k) if k_type is None: self.logger.info("[-] no description for '%s'", k) raise RuntimeError( f"[-] variable '{k}' has no description") if from_env is not None: # Getting value from same var, different environment v = from_env.get_secret(k, allow_none=True) else: # Try to prompt user for value if (k_type == 'boolean' and k not in se.Options): # Default options for boolean type se.Options[k] = BOOLEAN_OPTIONS k_options = se.get_options(k) if (k_options != '*' and k in se.Options): # Attempt to select from list. Options will look like # 'a,b' or 'a,b,*', or 'a,*'. old_v = se.get_secret(k, allow_none=True) v = prompt_options_list( options=k_options.split(','), default=(None if old_v in ['', None] else old_v), prompt=se.get_prompt(k)) if v is None: # User cancelled selection. break v = v if v not in ['', '*'] else None # Ask user for value if v is None: v = prompt_string(prompt=se.get_prompt(k), default="") v = v if v != '' else None else: # ('=' in arg) # Assignment syntax found (a=b) lhs, rhs = arg.split('=') k_type = se.get_type(lhs) if k_type is None: self.logger.info("[-] no description for '%s'", lhs) raise RuntimeError( f"[-] variable '{lhs}' has no description") k = lhs if from_env is not None: # Get value from different var in different environment v = from_env.get_secret(rhs, allow_none=True) self.logger.info( "[+] getting value from '%s' in environment '%s'", rhs, str(from_env)) else: # Value was specified in arg v = rhs if v is not None: # Is the value indirectly referenced? if v.startswith('@'): if v[1] == '~': _path = os.path.expanduser(v[1:]) else: _path = v[1:] with open(_path, 'r') as f: v = f.read().strip() elif v.startswith('!'): # >> Issue: [B603:subprocess_without_shell_equals_true] subprocess call - check for execution of untrusted input. # noqa # Severity: Low Confidence: High # Location: psec/secrets.py:641 p = run(v[1:].split(), stdout=PIPE, stderr=PIPE, shell=False) v = p.stdout.decode('UTF-8').strip() # After all that, did we get a value? if v is None: self.logger.info("[-] could not obtain value for '%s'", k) else: self.logger.debug("[+] setting variable '%s'", k) se.set_secret(k, v)