blob: 309a00122a8e12f8524fff7bea67331fb317c7d8 [file] [log] [blame]
Andrew Geisslereff27472021-10-29 15:35:00 -05001From 3540ddcc7448dc784b65c74424c8a25132cb8534 Mon Sep 17 00:00:00 2001
Brad Bishopd7bf8c12018-02-25 22:55:05 -05002From: Hongxu Jia <hongxu.jia@windriver.com>
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08003Date: Tue, 31 Jul 2018 17:24:47 +0800
Andrew Geisslereff27472021-10-29 15:35:00 -05004Subject: [PATCH] support authentication for kickstart
Brad Bishopd7bf8c12018-02-25 22:55:05 -05005
6While download kickstart file from web server,
7we support basic/digest authentication.
8
9Add KickstartAuthError to report authentication failure,
10which the invoker could parse this specific error.
11
Andrew Geissler6aa7eec2023-03-03 12:41:14 -060012Upstream-Status: Inappropriate [oe specific]
Brad Bishopd7bf8c12018-02-25 22:55:05 -050013
14Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com>
15---
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080016 pykickstart/errors.py | 17 +++++++++++++++++
Andrew Geissler6aa7eec2023-03-03 12:41:14 -060017 pykickstart/load.py | 32 +++++++++++++++++++++++++++-----
Brad Bishopd7bf8c12018-02-25 22:55:05 -050018 pykickstart/parser.py | 4 ++--
Andrew Geissler6aa7eec2023-03-03 12:41:14 -060019 3 files changed, 46 insertions(+), 7 deletions(-)
Brad Bishopd7bf8c12018-02-25 22:55:05 -050020
21diff --git a/pykickstart/errors.py b/pykickstart/errors.py
Andrew Geissler6aa7eec2023-03-03 12:41:14 -060022index 8294f59..3d20bf8 100644
Brad Bishopd7bf8c12018-02-25 22:55:05 -050023--- a/pykickstart/errors.py
24+++ b/pykickstart/errors.py
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080025@@ -32,6 +32,9 @@ This module exports several exception classes:
Brad Bishopd7bf8c12018-02-25 22:55:05 -050026 KickstartVersionError - An exception for errors relating to unsupported
27 syntax versions.
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080028
Brad Bishopd7bf8c12018-02-25 22:55:05 -050029+ KickstartAuthError - An exception for errors relating to authentication
30+ failed while downloading kickstart from web server
31+
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080032 And some warning classes:
Brad Bishopd7bf8c12018-02-25 22:55:05 -050033
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080034 KickstartWarning - A generic warning class.
Andrew Geissler748a4832020-07-24 16:24:21 -050035@@ -125,3 +128,17 @@ class KickstartDeprecationWarning(KickstartParseWarning, DeprecationWarning):
36 """A class for warnings occurring during parsing related to using deprecated
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080037 commands and options.
38 """
Brad Bishopd7bf8c12018-02-25 22:55:05 -050039+
40+class KickstartAuthError(KickstartError):
41+ """An exception for errors relating to authentication failed while
42+ downloading kickstart from web server
43+ """
44+ def __init__(self, msg):
45+ """Create a new KickstartAuthError exception instance with the
Andrew Geissler748a4832020-07-24 16:24:21 -050046+ descriptive message val. val should be the return value of
Brad Bishopd7bf8c12018-02-25 22:55:05 -050047+ formatErrorMsg.
48+ """
49+ KickstartError.__init__(self, msg)
50+
51+ def __str__(self):
52+ return self.value
Brad Bishopd7bf8c12018-02-25 22:55:05 -050053diff --git a/pykickstart/load.py b/pykickstart/load.py
Andrew Geissler6aa7eec2023-03-03 12:41:14 -060054index eb76b65..f51cf08 100644
Brad Bishopd7bf8c12018-02-25 22:55:05 -050055--- a/pykickstart/load.py
56+++ b/pykickstart/load.py
Andrew Geissler6aa7eec2023-03-03 12:41:14 -060057@@ -18,9 +18,11 @@
Brad Bishopd7bf8c12018-02-25 22:55:05 -050058 # with the express permission of Red Hat, Inc.
59 #
60 import requests
61+from requests.auth import HTTPDigestAuth
62+from requests.auth import HTTPBasicAuth
Brad Bishopd7bf8c12018-02-25 22:55:05 -050063 import shutil
Brad Bishopd7bf8c12018-02-25 22:55:05 -050064
65-from pykickstart.errors import KickstartError
66+from pykickstart.errors import KickstartError, KickstartAuthError
67 from pykickstart.i18n import _
68 from requests.exceptions import SSLError, RequestException
69
Andrew Geissler6aa7eec2023-03-03 12:41:14 -060070@@ -28,7 +30,7 @@ is_url = lambda location: '://' in location # RFC 3986
Brad Bishopd7bf8c12018-02-25 22:55:05 -050071
72 SSL_VERIFY = True
73
74-def load_to_str(location):
75+def load_to_str(location, user=None, passwd=None):
76 '''Load a destination URL or file into a string.
77 Type of input is inferred automatically.
78
Andrew Geissler6aa7eec2023-03-03 12:41:14 -060079@@ -39,7 +41,7 @@ def load_to_str(location):
Brad Bishopd7bf8c12018-02-25 22:55:05 -050080 Raises: KickstartError on error reading'''
81
Andrew Geissler6aa7eec2023-03-03 12:41:14 -060082 if is_url(location):
Brad Bishopd7bf8c12018-02-25 22:55:05 -050083- return _load_url(location)
84+ return _load_url(location, user=user, passwd=passwd)
85 else:
86 return _load_file(location)
87
Andrew Geissler6aa7eec2023-03-03 12:41:14 -060088@@ -69,11 +71,31 @@ def load_to_file(location, destination):
Brad Bishopd7bf8c12018-02-25 22:55:05 -050089 _copy_file(location, destination)
90 return destination
91
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080092-def _load_url(location):
Brad Bishopd7bf8c12018-02-25 22:55:05 -050093+def _get_auth(location, user=None, passwd=None):
94+
95+ auth = None
96+ request = requests.get(location, verify=SSL_VERIFY)
97+ if request.status_code == requests.codes.unauthorized:
98+ if user is None or passwd is None:
99+ log.info("Require Authentication")
100+ raise KickstartAuthError("Require Authentication.\nAppend 'ksuser=<username> kspasswd=<password>' to boot command")
Andrew Geissler6aa7eec2023-03-03 12:41:14 -0600101+
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500102+ reasons = request.headers.get("WWW-Authenticate", "").split()
103+ if reasons:
104+ auth_type = reasons[0]
105+ if auth_type == "Basic":
106+ auth = HTTPBasicAuth(user, passwd)
107+ elif auth_type == "Digest":
108+ auth=HTTPDigestAuth(user, passwd)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800109+
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500110+ return auth
111+
112+def _load_url(location, user=None, passwd=None):
Andrew Geissler6aa7eec2023-03-03 12:41:14 -0600113 '''Load a location (URL or filename) and return contents as string'''
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500114+ auth = _get_auth(location, user=user, passwd=passwd)
Andrew Geissler6aa7eec2023-03-03 12:41:14 -0600115
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500116 try:
117- request = requests.get(location, verify=SSL_VERIFY)
118+ request = requests.get(location, verify=SSL_VERIFY, auth=auth)
119 except SSLError as e:
120 raise KickstartError(_('Error securely accessing URL "%s"') % location + ': {e}'.format(e=str(e)))
121 except RequestException as e:
122diff --git a/pykickstart/parser.py b/pykickstart/parser.py
Andrew Geissler6aa7eec2023-03-03 12:41:14 -0600123index 7edf8aa..46c5299 100644
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500124--- a/pykickstart/parser.py
125+++ b/pykickstart/parser.py
Andrew Geissler6aa7eec2023-03-03 12:41:14 -0600126@@ -790,7 +790,7 @@ class KickstartParser(object):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500127 i = PutBackIterator(s.splitlines(True) + [""])
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800128 self._stateMachine(i)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500129
130- def readKickstart(self, f, reset=True):
131+ def readKickstart(self, f, reset=True, username=None, password=None):
132 """Process a kickstart file, given by the filename f."""
133 if reset:
134 self._reset()
Andrew Geissler6aa7eec2023-03-03 12:41:14 -0600135@@ -811,7 +811,7 @@ class KickstartParser(object):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500136 self.currentdir[self._includeDepth] = cd
137
138 try:
139- s = load_to_str(f)
140+ s = load_to_str(f, user=username, passwd=password)
141 except KickstartError as e:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800142 raise KickstartError(_("Unable to open input kickstart file: %s") % str(e), lineno=0)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500143
Andrew Geissler6aa7eec2023-03-03 12:41:14 -0600144--
1452.34.1
146