Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 36 additions & 38 deletions src/artifacts_keyring/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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.")
Loading