diff --git a/src/artifacts_keyring/plugin.py b/src/artifacts_keyring/plugin.py index 1f091ba..f841b58 100644 --- a/src/artifacts_keyring/plugin.py +++ b/src/artifacts_keyring/plugin.py @@ -106,10 +106,9 @@ def _get_credentials_from_credential_provider(self, url, is_retry): non_interactive = self._NON_INTERACTIVE_VAR_NAME in os.environ and \ os.environ[self._NON_INTERACTIVE_VAR_NAME] and \ str(os.environ[self._NON_INTERACTIVE_VAR_NAME]).lower() == "true" - verbosity = os.environ.get(self._VERBOSITY_VAR_NAME, "Information") - proc = Popen( + with Popen( self.exe + [ "-Uri", url, "-IsRetry", str(is_retry), @@ -118,41 +117,40 @@ def _get_credentials_from_credential_provider(self, url, is_retry): "-OutputFormat", "Json", "-Verbosity", verbosity ], - stdin=subprocess.PIPE, + stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE - ) - - # Read all standard error first, which may either display - # errors from the credential provider or instructions - # from it for Device Flow authentication. - for stderr_line in iter(proc.stderr.readline, b''): - line = stderr_line.decode("utf-8", "ignore") - sys.stderr.write(line) - sys.stderr.flush() - - proc.wait() - - if proc.returncode != 0: - stderr = proc.stderr.read().decode("utf-8", "ignore") - - error_msg = "Failed to get credentials: process with PID {pid} exited with code {code}".format( - pid=proc.pid, code=proc.returncode - ) - if stderr.strip(): - error_msg += "; additional error message: {error}".format(error=stderr) - else: - error_msg += "; no additional error message available, see Credential Provider logs above for details." - raise RuntimeError(error_msg) - - try: - # stdout is expected to be UTF-8 encoded JSON, so decoding errors are not ignored here. - payload = proc.stdout.read().decode("utf-8") - except ValueError: - raise RuntimeError("Failed to get credentials: the Credential Provider's output could not be decoded using UTF-8.") - - try: - parsed = json.loads(payload) - return parsed["Username"], parsed["Password"] - except ValueError: - raise RuntimeError("Failed to get credentials: the Credential Provider's output could not be parsed as JSON.") + ) as proc: + # Read all standard error first, which may either display + # errors from the credential provider or instructions + # from it for Device Flow authentication. + for stderr_line in iter(proc.stderr.readline, b''): + line = stderr_line.decode("utf-8", "ignore") + sys.stderr.write(line) + sys.stderr.flush() + + proc.wait() + + if proc.returncode != 0: + stderr = proc.stderr.read().decode("utf-8", "ignore") + + error_msg = "Failed to get credentials: process with PID {pid} exited with code {code}".format( + pid=proc.pid, code=proc.returncode + ) + if stderr.strip(): + error_msg += "; additional error message: {error}".format(error=stderr) + else: + error_msg += "; no additional error message available, see Credential Provider logs above for details." + raise RuntimeError(error_msg) + + try: + # stdout is expected to be UTF-8 encoded JSON, so decoding errors are not ignored here. + payload = proc.stdout.read().decode("utf-8") + except ValueError: + raise RuntimeError("Failed to get credentials: the Credential Provider's output could not be decoded using UTF-8.") + + try: + parsed = json.loads(payload) + return parsed["Username"], parsed["Password"] + except ValueError: + raise RuntimeError("Failed to get credentials: the Credential Provider's output could not be parsed as JSON.")