Skip to content

Commit ffdc9af

Browse files
committed
redfish/rest: implement .netrc support
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
1 parent 3aad340 commit ffdc9af

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed

src/redfish/rest/v1.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import base64
2424
import hashlib
2525
import logging
26+
import netrc
27+
import os
2628
import sys
2729
from urllib.parse import urlparse
2830

@@ -256,6 +258,7 @@ def __init__(
256258
base_url=None,
257259
auth=None,
258260
ca_cert_data=None,
261+
use_netrc=False,
259262
**client_kwargs
260263
):
261264
"""Create a Rest Client object"""
@@ -266,6 +269,15 @@ def __init__(
266269
auth, ca_cert_data=ca_cert_data, **client_kwargs
267270
)
268271
self._auth_key = None
272+
273+
# If .netrc should be considered, use it to preload username and/or password
274+
if use_netrc and not (username and password):
275+
netrc_user, netrc_pass = self._get_netrc_auth(base_url)
276+
if username is None and netrc_user:
277+
username = netrc_user
278+
if password is None and netrc_pass:
279+
password = netrc_pass
280+
269281
self._user_pass = (username, password)
270282
self._session_location = None
271283
self._cert_data = ca_cert_data
@@ -286,6 +298,49 @@ def __exit__(self, exc_type, exc_val, exc_tb):
286298
"""Close the connection"""
287299
self.logout()
288300

301+
def _get_netrc_auth(self, url):
302+
"""Get username and password from a .netrc if available"""
303+
304+
# inspired by request's get_netrc_auth
305+
306+
hostname = urlparse(url).netloc.split(":")[0] # ignore port if present
307+
308+
path = None
309+
310+
try:
311+
path = os.environ["NETRC"]
312+
except KeyError:
313+
for name in (".netrc", "_netrc"):
314+
try:
315+
path = os.path.expanduser(f"~/{name}")
316+
except KeyError:
317+
break
318+
319+
if os.path.exists(path):
320+
break
321+
322+
if not path:
323+
LOGGER.error("Requested use of .netrc, but no .netrc found")
324+
325+
try:
326+
login, account, pwd = netrc.netrc(path).authenticators(hostname)
327+
except FileNotFoundError as exc:
328+
LOGGER.error(
329+
f"Requested use of .netrc, but file inaccessible at '{path}'", exc)
330+
return (None, None)
331+
except netrc.NetrcParseError as exc:
332+
LOGGER.error(
333+
f"Requested use of .netrc, but parsing failed for '{path}'", exc)
334+
return (None, None)
335+
except TypeError:
336+
LOGGER.info(f"No matching entry found in '{path}' for: {hostname}")
337+
return (None, None)
338+
339+
if login:
340+
return (login, pwd)
341+
342+
return (account, pwd)
343+
289344
def _get_auth_type(self, auth_param, ca_cert_data=None, **client_kwargs):
290345
"""Get the auth type based on key args or positional argument.
291346
Defaults to session auth."""

0 commit comments

Comments
 (0)