diff --git a/changelogs/fragments/lookup-passwordstore-umask.yml b/changelogs/fragments/lookup-passwordstore-umask.yml new file mode 100644 index 0000000000..1d9f3b711a --- /dev/null +++ b/changelogs/fragments/lookup-passwordstore-umask.yml @@ -0,0 +1,5 @@ +--- +minor_changes: + - passwordstore lookup plugin - added ``umask`` option to set the desired file permisions on creation. This is + done via the ``PASSWORD_STORE_UMASK`` environment variable + (https://github.com/ansible-collections/community.general/pull/1156). diff --git a/plugins/lookup/passwordstore.py b/plugins/lookup/passwordstore.py index 4c9bbb8980..ffec2ab6c4 100644 --- a/plugins/lookup/passwordstore.py +++ b/plugins/lookup/passwordstore.py @@ -32,6 +32,13 @@ DOCUMENTATION = ''' description: Overwrite the password if it does already exist. type: bool default: 'no' + umask: + description: + - Sets the umask for the created .gpg files. The first octed must be greater than 3 (user readable). + - Note pass' default value is C('077'). + env: + - name: PASSWORD_STORE_UMASK + version_added: 1.3.0 returnall: description: Return all the content of the password, not only the first line. type: bool @@ -175,17 +182,29 @@ class LookupModule(LookupBase): else: raise AnsibleError("{0} is not a correct value for length".format(self.paramvals['length'])) + # Collect pass environment variables from the plugin's parameters. + self.env = os.environ.copy() + # Set PASSWORD_STORE_DIR if directory is set if self.paramvals['directory']: if os.path.isdir(self.paramvals['directory']): - os.environ['PASSWORD_STORE_DIR'] = self.paramvals['directory'] + self.env['PASSWORD_STORE_DIR'] = self.paramvals['directory'] else: raise AnsibleError('Passwordstore directory \'{0}\' does not exist'.format(self.paramvals['directory'])) + # Set PASSWORD_STORE_UMASK if umask is set + if 'umask' in self.paramvals: + if len(self.paramvals['umask']) != 3: + raise AnsibleError('Passwordstore umask must have a length of 3.') + elif int(self.paramvals['umask'][0]) > 3: + raise AnsibleError('Passwordstore umask not allowed (password not user readable).') + else: + self.env['PASSWORD_STORE_UMASK'] = self.paramvals['umask'] + def check_pass(self): try: self.passoutput = to_text( - check_output2(["pass", self.passname]), + check_output2(["pass", self.passname], env=self.env), errors='surrogate_or_strict' ).splitlines() self.password = self.passoutput[0] @@ -228,7 +247,7 @@ class LookupModule(LookupBase): if self.paramvals['backup']: msg += "lookup_pass: old password was {0} (Updated on {1})\n".format(self.password, datetime) try: - check_output2(['pass', 'insert', '-f', '-m', self.passname], input=msg) + check_output2(['pass', 'insert', '-f', '-m', self.passname], input=msg, env=self.env) except (subprocess.CalledProcessError) as e: raise AnsibleError(e) return newpass @@ -240,7 +259,7 @@ class LookupModule(LookupBase): datetime = time.strftime("%d/%m/%Y %H:%M:%S") msg = newpass + '\n' + "lookup_pass: First generated by ansible on {0}\n".format(datetime) try: - check_output2(['pass', 'insert', '-f', '-m', self.passname], input=msg) + check_output2(['pass', 'insert', '-f', '-m', self.passname], input=msg, env=self.env) except (subprocess.CalledProcessError) as e: raise AnsibleError(e) return newpass