def _play_prereqs(): options = context.CLIARGS # all needs loader loader = DataLoader() basedir = options.get('basedir', False) if basedir: loader.set_basedir(basedir) add_all_plugin_dirs(basedir) AssibleCollectionConfig.playbook_paths = basedir default_collection = _get_collection_name_from_path(basedir) if default_collection: display.warning(u'running with default collection {0}'.format( default_collection)) AssibleCollectionConfig.default_collection = default_collection vault_ids = list(options['vault_ids']) default_vault_ids = C.DEFAULT_VAULT_IDENTITY_LIST vault_ids = default_vault_ids + vault_ids vault_secrets = CLI.setup_vault_secrets( loader, vault_ids=vault_ids, vault_password_files=list(options['vault_password_files']), ask_vault_pass=options['ask_vault_pass'], auto_prompt=False) loader.set_vault_secrets(vault_secrets) # create the inventory, and filter it based on the subset specified (if any) inventory = InventoryManager(loader=loader, sources=options['inventory']) # create the variable manager, which will be shared throughout # the code, ensuring a consistent view of global variables variable_manager = VariableManager( loader=loader, inventory=inventory, version_info=CLI.version_info(gitinfo=False)) return loader, inventory, variable_manager
class TestDataLoaderWithVault(unittest.TestCase): def setUp(self): self._loader = DataLoader() vault_secrets = [('default', TextVaultSecret('assible'))] self._loader.set_vault_secrets(vault_secrets) self.test_vault_data_path = os.path.join(os.path.dirname(__file__), 'fixtures', 'vault.yml') def tearDown(self): pass def test_get_real_file_vault(self): real_file_path = self._loader.get_real_file(self.test_vault_data_path) self.assertTrue(os.path.exists(real_file_path)) def test_get_real_file_vault_no_vault(self): self._loader.set_vault_secrets(None) self.assertRaises(AssibleParserError, self._loader.get_real_file, self.test_vault_data_path) def test_get_real_file_vault_wrong_password(self): wrong_vault = [('default', TextVaultSecret('wrong_password'))] self._loader.set_vault_secrets(wrong_vault) self.assertRaises(AssibleVaultError, self._loader.get_real_file, self.test_vault_data_path) def test_get_real_file_not_a_path(self): self.assertRaisesRegexp(AssibleParserError, 'Invalid filename', self._loader.get_real_file, None) @patch.multiple(DataLoader, path_exists=lambda s, x: True, is_file=lambda s, x: True) def test_parse_from_vault_1_1_file(self): vaulted_data = """$ASSIBLE_VAULT;1.1;AES256 33343734386261666161626433386662623039356366656637303939306563376130623138626165 6436333766346533353463636566313332623130383662340a393835656134633665333861393331 37666233346464636263636530626332623035633135363732623332313534306438393366323966 3135306561356164310a343937653834643433343734653137383339323330626437313562306630 3035 """ if PY3: builtins_name = 'builtins' else: builtins_name = '__builtin__' with patch(builtins_name + '.open', mock_open(read_data=vaulted_data.encode('utf-8'))): output = self._loader.load_from_file('dummy_vault.txt') self.assertEqual(output, dict(foo='bar'))
def run(self): super(VaultCLI, self).run() loader = DataLoader() # set default restrictive umask old_umask = os.umask(0o077) vault_ids = list(context.CLIARGS['vault_ids']) # there are 3 types of actions, those that just 'read' (decrypt, view) and only # need to ask for a password once, and those that 'write' (create, encrypt) that # ask for a new password and confirm it, and 'read/write (rekey) that asks for the # old password, then asks for a new one and confirms it. default_vault_ids = C.DEFAULT_VAULT_IDENTITY_LIST vault_ids = default_vault_ids + vault_ids action = context.CLIARGS['action'] # TODO: instead of prompting for these before, we could let VaultEditor # call a callback when it needs it. if action in ['decrypt', 'view', 'rekey', 'edit']: vault_secrets = self.setup_vault_secrets( loader, vault_ids=vault_ids, vault_password_files=list( context.CLIARGS['vault_password_files']), ask_vault_pass=context.CLIARGS['ask_vault_pass']) if not vault_secrets: raise AssibleOptionsError( "A vault password is required to use Assible's Vault") if action in ['encrypt', 'encrypt_string', 'create']: encrypt_vault_id = None # no --encrypt-vault-id context.CLIARGS['encrypt_vault_id'] for 'edit' if action not in ['edit']: encrypt_vault_id = context.CLIARGS[ 'encrypt_vault_id'] or C.DEFAULT_VAULT_ENCRYPT_IDENTITY vault_secrets = None vault_secrets = \ self.setup_vault_secrets(loader, vault_ids=vault_ids, vault_password_files=list(context.CLIARGS['vault_password_files']), ask_vault_pass=context.CLIARGS['ask_vault_pass'], create_new_password=True) if len(vault_secrets) > 1 and not encrypt_vault_id: raise AssibleOptionsError( "The vault-ids %s are available to encrypt. Specify the vault-id to encrypt with --encrypt-vault-id" % ','.join([x[0] for x in vault_secrets])) if not vault_secrets: raise AssibleOptionsError( "A vault password is required to use Assible's Vault") encrypt_secret = match_encrypt_secret( vault_secrets, encrypt_vault_id=encrypt_vault_id) # only one secret for encrypt for now, use the first vault_id and use its first secret # TODO: exception if more than one? self.encrypt_vault_id = encrypt_secret[0] self.encrypt_secret = encrypt_secret[1] if action in ['rekey']: encrypt_vault_id = context.CLIARGS[ 'encrypt_vault_id'] or C.DEFAULT_VAULT_ENCRYPT_IDENTITY # print('encrypt_vault_id: %s' % encrypt_vault_id) # print('default_encrypt_vault_id: %s' % default_encrypt_vault_id) # new_vault_ids should only ever be one item, from # load the default vault ids if we are using encrypt-vault-id new_vault_ids = [] if encrypt_vault_id: new_vault_ids = default_vault_ids if context.CLIARGS['new_vault_id']: new_vault_ids.append(context.CLIARGS['new_vault_id']) new_vault_password_files = [] if context.CLIARGS['new_vault_password_file']: new_vault_password_files.append( context.CLIARGS['new_vault_password_file']) new_vault_secrets = \ self.setup_vault_secrets(loader, vault_ids=new_vault_ids, vault_password_files=new_vault_password_files, ask_vault_pass=context.CLIARGS['ask_vault_pass'], create_new_password=True) if not new_vault_secrets: raise AssibleOptionsError( "A new vault password is required to use Assible's Vault rekey" ) # There is only one new_vault_id currently and one new_vault_secret, or we # use the id specified in --encrypt-vault-id new_encrypt_secret = match_encrypt_secret( new_vault_secrets, encrypt_vault_id=encrypt_vault_id) self.new_encrypt_vault_id = new_encrypt_secret[0] self.new_encrypt_secret = new_encrypt_secret[1] loader.set_vault_secrets(vault_secrets) # FIXME: do we need to create VaultEditor here? its not reused vault = VaultLib(vault_secrets) self.editor = VaultEditor(vault) context.CLIARGS['func']() # and restore umask os.umask(old_umask)