feat: Adds module attachment w/ example
This commit is contained in:
parent
2da98dac98
commit
26422700ab
|
@ -10,7 +10,8 @@
|
||||||
slash_login: "{{ lookup('viczem.keepass.keepass', 'slash\\/group/slash\\/title', 'username') }}"
|
slash_login: "{{ lookup('viczem.keepass.keepass', 'slash\\/group/slash\\/title', 'username') }}"
|
||||||
slash_url: "{{ lookup('viczem.keepass.keepass', 'slash\\/group/slash\\/title', 'url') }}"
|
slash_url: "{{ lookup('viczem.keepass.keepass', 'slash\\/group/slash\\/title', 'url') }}"
|
||||||
pork_custom_property: "{{ lookup('viczem.keepass.keepass', 'example/pork', 'custom_properties', 'pork_custom_property')}}"
|
pork_custom_property: "{{ lookup('viczem.keepass.keepass', 'example/pork', 'custom_properties', 'pork_custom_property')}}"
|
||||||
|
keepass_attachment_1_name: "attachment_1.txt"
|
||||||
|
keepass_attachment_2_name: "attachment_2.zip"
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
- debug:
|
- debug:
|
||||||
|
@ -30,3 +31,20 @@
|
||||||
msg: "fetch entry: '/slash\\/group/slash\\/title'; username: '{{ slash_login }}'; url: '{{ slash_url }}'"
|
msg: "fetch entry: '/slash\\/group/slash\\/title'; username: '{{ slash_login }}'; url: '{{ slash_url }}'"
|
||||||
|
|
||||||
- debug: "{{ lookup('viczem.keepass.keepass', 'close') }}"
|
- debug: "{{ lookup('viczem.keepass.keepass', 'close') }}"
|
||||||
|
|
||||||
|
- name: "Export file: {{ keepass_attachment_1_name }}"
|
||||||
|
viczem.keepass.attachment:
|
||||||
|
database: "{{ keepass_dbx }}"
|
||||||
|
password: "{{ keepass_psw }}"
|
||||||
|
entrypath: example/attachments
|
||||||
|
attachment: "{{ keepass_attachment_1_name }}"
|
||||||
|
dest: "{{ keepass_attachment_1_name }}"
|
||||||
|
|
||||||
|
- name: "Export file: {{ keepass_attachment_2_name }}"
|
||||||
|
viczem.keepass.attachment:
|
||||||
|
database: "{{ keepass_dbx }}"
|
||||||
|
password: "{{ keepass_psw }}"
|
||||||
|
entrypath: example/attachments
|
||||||
|
attachment: "{{ keepass_attachment_2_name }}"
|
||||||
|
dest: "{{ keepass_attachment_2_name }}"
|
||||||
|
mode: 0600
|
Binary file not shown.
|
@ -0,0 +1,188 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright: (c) 2022, Jimisola Laursen <jimisola@jimisola.com>
|
||||||
|
# Copyright: (c) 2022, LFV <www.lfv.se>
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
DOCUMENTATION = r'''
|
||||||
|
---
|
||||||
|
module: attachment
|
||||||
|
author:
|
||||||
|
- Jimisola Laursen (@lfvjimisola)
|
||||||
|
- Jimisola Laursen (@jimisola)
|
||||||
|
|
||||||
|
short_description: Exports KeePass attachments
|
||||||
|
description:
|
||||||
|
- This module will export an attachment in a KeePass entry to a file.
|
||||||
|
|
||||||
|
version_added: "0.1.0"
|
||||||
|
|
||||||
|
extends_documentation_fragment:
|
||||||
|
- files
|
||||||
|
- action_common_attributes
|
||||||
|
|
||||||
|
requirements:
|
||||||
|
- pykeepass
|
||||||
|
|
||||||
|
options:
|
||||||
|
database:
|
||||||
|
description: Path to KeePass database file.
|
||||||
|
required: true
|
||||||
|
type: str
|
||||||
|
password:
|
||||||
|
description: Password for KeePass database file.
|
||||||
|
required: true
|
||||||
|
type: str
|
||||||
|
entrypath:
|
||||||
|
description: Path to KeePass entry containing the attachment that should be exported.
|
||||||
|
required: true
|
||||||
|
type: str
|
||||||
|
attachment:
|
||||||
|
description: Name of attachment that should be exported.
|
||||||
|
required: true
|
||||||
|
type: str
|
||||||
|
dest:
|
||||||
|
description: Absolute path where the file should be exported to.
|
||||||
|
required: true
|
||||||
|
type: str
|
||||||
|
|
||||||
|
attributes:
|
||||||
|
check_mode:
|
||||||
|
support: none
|
||||||
|
diff_mode:
|
||||||
|
support: none
|
||||||
|
platform:
|
||||||
|
platforms: posix
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXAMPLES = r'''
|
||||||
|
# Export a file
|
||||||
|
- name: Export a file from KeePass
|
||||||
|
keepass:
|
||||||
|
database: database.kdbx
|
||||||
|
password: somepassword
|
||||||
|
path: "group/subgroup/entry"
|
||||||
|
attachment: somefile.txt
|
||||||
|
dest: somefile_exported.txt
|
||||||
|
'''
|
||||||
|
|
||||||
|
RETURN = r''' # '''
|
||||||
|
|
||||||
|
from importlib.metadata import EntryPoint
|
||||||
|
import traceback
|
||||||
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
from ansible.module_utils.basic import missing_required_lib
|
||||||
|
from ansible.module_utils._text import to_bytes, to_native
|
||||||
|
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
LIB_IMP_ERR = None
|
||||||
|
try:
|
||||||
|
from pykeepass import PyKeePass
|
||||||
|
HAS_LIB = True
|
||||||
|
except Exception as e:
|
||||||
|
HAS_LIB = False
|
||||||
|
LIB_IMP_ERR = traceback.format_exc()
|
||||||
|
|
||||||
|
|
||||||
|
def check_file_attrs(module, result, diff):
|
||||||
|
|
||||||
|
changed, msg = result['changed'], result['msg']
|
||||||
|
|
||||||
|
file_args = module.load_file_common_arguments(module.params)
|
||||||
|
if module.set_fs_attributes_if_different(file_args, False, diff=diff):
|
||||||
|
|
||||||
|
if changed:
|
||||||
|
msg += " and "
|
||||||
|
changed = True
|
||||||
|
msg += "ownership, perms or SE linux context changed"
|
||||||
|
|
||||||
|
result['changed'] = changed
|
||||||
|
result['msg'] = msg
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def export_attachment(module, result):
|
||||||
|
try:
|
||||||
|
# load database
|
||||||
|
kp = PyKeePass(module.params['database'], password=module.params['password'])
|
||||||
|
|
||||||
|
entrypath = module.params['entrypath']
|
||||||
|
dest = module.params['dest']
|
||||||
|
attachment = module.params['attachment']
|
||||||
|
|
||||||
|
# find entry
|
||||||
|
kp_entry = kp.find_entries(path=entrypath.split('/'), first=True)
|
||||||
|
|
||||||
|
if (kp_entry is None):
|
||||||
|
module.fail_json(msg="Entry '{0}' not found".format(entrypath))
|
||||||
|
|
||||||
|
kp_attachment = None
|
||||||
|
for item in kp_entry.attachments:
|
||||||
|
if item.filename == attachment:
|
||||||
|
kp_attachment = item
|
||||||
|
|
||||||
|
if (kp_attachment is None):
|
||||||
|
module.fail_json(msg="Entry '{0}' does not contain attachment '{1}'".format(entrypath, attachment))
|
||||||
|
|
||||||
|
b_data = kp_attachment.binary
|
||||||
|
|
||||||
|
tmpfd, tmpfile = tempfile.mkstemp()
|
||||||
|
f = os.fdopen(tmpfd, 'wb')
|
||||||
|
f.write(b_data)
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
module.atomic_move(tmpfile,
|
||||||
|
to_native(os.path.realpath(to_bytes(dest, errors='surrogate_or_strict')), errors='surrogate_or_strict'),
|
||||||
|
unsafe_writes=module.params['unsafe_writes'])
|
||||||
|
|
||||||
|
result['changed'] = True
|
||||||
|
result['msg'] = "attachment '{0}' exported to file '{1}'".format(module.params['attachment'], dest)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
result['msg'] = "Module viczem.keepass.attachment failed: {0}".format(e)
|
||||||
|
module.fail_json(**result)
|
||||||
|
|
||||||
|
attr_diff = None
|
||||||
|
|
||||||
|
result = check_file_attrs(module, result, attr_diff)
|
||||||
|
|
||||||
|
module.exit_json(**result, diff=attr_diff)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
module_args = dict(
|
||||||
|
database=dict(type='str', required=True),
|
||||||
|
password=dict(type='str', no_log=True, required=True),
|
||||||
|
entrypath=dict(type='str', required=True),
|
||||||
|
attachment=dict(type='str', required=True),
|
||||||
|
dest=dict(type='path', required=True),
|
||||||
|
)
|
||||||
|
|
||||||
|
module = AnsibleModule(
|
||||||
|
argument_spec=module_args,
|
||||||
|
add_file_common_args=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not HAS_LIB:
|
||||||
|
module.fail_json(msg=missing_required_lib("pykeepass"), exception=LIB_IMP_ERR)
|
||||||
|
|
||||||
|
result = dict(
|
||||||
|
changed=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
dest = module.params['dest']
|
||||||
|
b_dest = to_bytes(dest, errors='surrogate_or_strict')
|
||||||
|
|
||||||
|
if os.path.isdir(b_dest):
|
||||||
|
module.fail_json(rc=256, msg='Destination {0} is a directory!'.format(dest))
|
||||||
|
|
||||||
|
export_attachment(module, result)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
Loading…
Reference in New Issue