Skip to content

Commit

Permalink
redfish/rest: implement .netrc support
Browse files Browse the repository at this point in the history
this adds a use_netrc flag to the client, permitting it to consult ~/.netrc in the same way as the "-n" flag of "curl" if set to True
  • Loading branch information
dev-zero committed Aug 30, 2023
1 parent 3aad340 commit 3437b3c
Showing 1 changed file with 55 additions and 0 deletions.
55 changes: 55 additions & 0 deletions src/redfish/rest/v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import base64
import hashlib
import logging
import netrc
import os
import sys
from urllib.parse import urlparse

Expand Down Expand Up @@ -256,6 +258,7 @@ def __init__(
base_url=None,
auth=None,
ca_cert_data=None,
use_netrc=False,
**client_kwargs
):
"""Create a Rest Client object"""
Expand All @@ -266,6 +269,15 @@ def __init__(
auth, ca_cert_data=ca_cert_data, **client_kwargs
)
self._auth_key = None

# If .netrc should be considered, use it to preload username and/or password
if use_netrc and not (username and password):
netrc_user, netrc_pass = self._get_netrc_auth(base_url)
if username is None and netrc_user:
username = netrc_user
if password is None and netrc_pass:
password = netrc_pass

self._user_pass = (username, password)
self._session_location = None
self._cert_data = ca_cert_data
Expand All @@ -286,6 +298,49 @@ def __exit__(self, exc_type, exc_val, exc_tb):
"""Close the connection"""
self.logout()

def _get_netrc_auth(self, url):
"""Get username and password from a .netrc if available"""

# inspired by request's get_netrc_auth

hostname = urlparse(url).netloc.split(":")[0] # ignore port if present

path = None

try:
path = os.environ["NETRC"]
except KeyError:
for name in (".netrc", "_netrc"):
try:
path = os.path.expanduser(f"~/{name}")
except KeyError:
break

if os.path.exists(path):
break

if not path:
LOGGER.error("Requested use of .netrc, but no .netrc found")

try:
login, account, pwd = netrc.netrc(path).authenticators(hostname)
except FileNotFoundError as exc:
LOGGER.error(
f"Requested use of .netrc, but file inaccessible at '{path}'", exc)
return (None, None)
except netrc.NetrcParseError as exc:
LOGGER.error(
f"Requested use of .netrc, but parsing failed for '{path}'", exc)
return (None, None)
except ValueError:
LOGGER.info(f"No matching entry found in '{path}' for: {hostname}")
return (None, None)

if login:
return (login, pwd)

return (account, pwd)

def _get_auth_type(self, auth_param, ca_cert_data=None, **client_kwargs):
"""Get the auth type based on key args or positional argument.
Defaults to session auth."""
Expand Down

0 comments on commit 3437b3c

Please sign in to comment.