besapi 4.0.1__tar.gz → 4.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {besapi-4.0.1/src/besapi.egg-info → besapi-4.1.2}/PKG-INFO +1 -1
- {besapi-4.0.1 → besapi-4.1.2}/src/besapi/besapi.py +74 -2
- {besapi-4.0.1 → besapi-4.1.2/src/besapi.egg-info}/PKG-INFO +1 -1
- {besapi-4.0.1 → besapi-4.1.2}/src/bescli/bescli.py +17 -3
- {besapi-4.0.1 → besapi-4.1.2}/tests/test_besapi.py +76 -0
- {besapi-4.0.1 → besapi-4.1.2}/LICENSE.txt +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/MANIFEST.in +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/README.md +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/pyproject.toml +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/setup.cfg +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/setup.py +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/src/besapi/__init__.py +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/src/besapi/__main__.py +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/src/besapi/plugin_utilities.py +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/src/besapi/plugin_utilities_win.py +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/src/besapi/schemas/BES.xsd +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/src/besapi/schemas/BESAPI.xsd +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/src/besapi/schemas/BESActionSettings.xsd +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/src/besapi.egg-info/SOURCES.txt +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/src/besapi.egg-info/dependency_links.txt +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/src/besapi.egg-info/requires.txt +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/src/besapi.egg-info/top_level.txt +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/src/bescli/__init__.py +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/src/bescli/__main__.py +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/tests/test_plugin_utilities.py +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/tests/test_plugin_utilities_logging.py +0 -0
- {besapi-4.0.1 → besapi-4.1.2}/tests/tests.py +0 -0
|
@@ -12,6 +12,7 @@ Library for communicating with the BES (BigFix) REST API.
|
|
|
12
12
|
|
|
13
13
|
import configparser
|
|
14
14
|
import datetime
|
|
15
|
+
import getpass
|
|
15
16
|
import hashlib
|
|
16
17
|
import importlib.resources
|
|
17
18
|
import json
|
|
@@ -20,6 +21,7 @@ import os
|
|
|
20
21
|
import random
|
|
21
22
|
import site
|
|
22
23
|
import string
|
|
24
|
+
import sys
|
|
23
25
|
import urllib.parse
|
|
24
26
|
|
|
25
27
|
import lxml.etree
|
|
@@ -27,7 +29,7 @@ import lxml.objectify
|
|
|
27
29
|
import requests
|
|
28
30
|
import urllib3.poolmanager
|
|
29
31
|
|
|
30
|
-
__version__ = "4.
|
|
32
|
+
__version__ = "4.1.2"
|
|
31
33
|
|
|
32
34
|
besapi_logger = logging.getLogger("besapi")
|
|
33
35
|
|
|
@@ -304,6 +306,76 @@ def get_bes_conn_using_config_file(conf_file=None):
|
|
|
304
306
|
return None
|
|
305
307
|
|
|
306
308
|
|
|
309
|
+
def get_bes_conn_interactive(
|
|
310
|
+
user=None, password=None, root_server=None, force_prompt=False
|
|
311
|
+
):
|
|
312
|
+
"""Get BESConnection using interactive prompts."""
|
|
313
|
+
|
|
314
|
+
if not (force_prompt or sys.__stdin__.isatty()):
|
|
315
|
+
logging.error("No TTY available for interactive login!")
|
|
316
|
+
return None
|
|
317
|
+
|
|
318
|
+
print(
|
|
319
|
+
"Attempting BESAPI Connection using interactive prompts. Use Ctrl-C to cancel."
|
|
320
|
+
)
|
|
321
|
+
try:
|
|
322
|
+
if not user:
|
|
323
|
+
user = str(input("User [%s]: " % getpass.getuser())).strip()
|
|
324
|
+
if not user:
|
|
325
|
+
user = getpass.getuser()
|
|
326
|
+
|
|
327
|
+
if not root_server:
|
|
328
|
+
root_server = str(
|
|
329
|
+
input("Root Server (ex. %s): " % "https://localhost:52311")
|
|
330
|
+
).strip()
|
|
331
|
+
if not root_server or root_server == "":
|
|
332
|
+
print("Root Server is required, try again!")
|
|
333
|
+
return get_bes_conn_interactive(
|
|
334
|
+
user=user,
|
|
335
|
+
password=password,
|
|
336
|
+
root_server=None,
|
|
337
|
+
force_prompt=force_prompt,
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
if not password:
|
|
341
|
+
password = str(
|
|
342
|
+
getpass.getpass(f"Password for {user}@{root_server}: ")
|
|
343
|
+
).strip()
|
|
344
|
+
|
|
345
|
+
if not password or password == "":
|
|
346
|
+
print("Password is required, try again!")
|
|
347
|
+
return get_bes_conn_interactive(
|
|
348
|
+
user=user,
|
|
349
|
+
password=None,
|
|
350
|
+
root_server=root_server,
|
|
351
|
+
force_prompt=force_prompt,
|
|
352
|
+
)
|
|
353
|
+
except (KeyboardInterrupt, EOFError):
|
|
354
|
+
print("\nLogin cancelled.")
|
|
355
|
+
return None
|
|
356
|
+
|
|
357
|
+
try:
|
|
358
|
+
return BESConnection(user, password, root_server)
|
|
359
|
+
except requests.exceptions.HTTPError as err:
|
|
360
|
+
print("Bad Username or Bad Password, Try again!")
|
|
361
|
+
logging.debug(err)
|
|
362
|
+
print(" BES_ROOT_SERVER: ", root_server)
|
|
363
|
+
return get_bes_conn_interactive(
|
|
364
|
+
user=None, password=None, root_server=root_server, force_prompt=force_prompt
|
|
365
|
+
)
|
|
366
|
+
except requests.exceptions.ConnectionError as err:
|
|
367
|
+
print("Bad Root Server Specified, Try again!")
|
|
368
|
+
logging.debug("Connection Error: %s", err)
|
|
369
|
+
print(" BES_USER_NAME: ", user)
|
|
370
|
+
print("BES_PASSWORD length: ", len(password))
|
|
371
|
+
return get_bes_conn_interactive(
|
|
372
|
+
user=user, password=password, root_server=None, force_prompt=force_prompt
|
|
373
|
+
)
|
|
374
|
+
except Exception as e: # pylint: disable=broad-except
|
|
375
|
+
logging.error("Error occurred while establishing BESConnection: %s", e)
|
|
376
|
+
return None
|
|
377
|
+
|
|
378
|
+
|
|
307
379
|
# https://docs.python-requests.org/en/latest/user/advanced/#transport-adapters
|
|
308
380
|
class HTTPAdapterBlocksize(requests.adapters.HTTPAdapter):
|
|
309
381
|
"""Custom HTTPAdapter for requests to override blocksize
|
|
@@ -543,7 +615,7 @@ class BESConnection:
|
|
|
543
615
|
return RESTResult(
|
|
544
616
|
self.session.post(
|
|
545
617
|
self.url("query"),
|
|
546
|
-
data=f"relevance={urllib.parse.quote(relevance, safe='
|
|
618
|
+
data=f"relevance={urllib.parse.quote(relevance, safe=':')}",
|
|
547
619
|
verify=self.verify,
|
|
548
620
|
**kwargs,
|
|
549
621
|
)
|
|
@@ -216,6 +216,20 @@ class BESCLInterface(Cmd):
|
|
|
216
216
|
self.pfeedback(" - attempt login using config parameters - ")
|
|
217
217
|
self.do_login()
|
|
218
218
|
|
|
219
|
+
def do_login_new(self, user=None):
|
|
220
|
+
"""Login to BigFix Server."""
|
|
221
|
+
if not user or str(user).strip() == "":
|
|
222
|
+
user = self.BES_USER_NAME
|
|
223
|
+
self.bes_conn = besapi.get_bes_conn_interactive(
|
|
224
|
+
user=user,
|
|
225
|
+
password=self.BES_PASSWORD,
|
|
226
|
+
root_server=self.BES_ROOT_SERVER,
|
|
227
|
+
)
|
|
228
|
+
if self.bes_conn:
|
|
229
|
+
self.pfeedback("Login Successful!")
|
|
230
|
+
(self.BES_USER_NAME, self.BES_PASSWORD) = self.bes_conn.session.auth
|
|
231
|
+
self.BES_ROOT_SERVER = self.bes_conn.rootserver
|
|
232
|
+
|
|
219
233
|
def do_login(self, user=None):
|
|
220
234
|
"""Login to BigFix Server."""
|
|
221
235
|
|
|
@@ -227,7 +241,7 @@ class BESCLInterface(Cmd):
|
|
|
227
241
|
if not user:
|
|
228
242
|
user = getpass.getuser()
|
|
229
243
|
|
|
230
|
-
self.BES_USER_NAME = user
|
|
244
|
+
self.BES_USER_NAME = user.strip()
|
|
231
245
|
if not self.CONFPARSER.has_section("besapi"):
|
|
232
246
|
self.CONFPARSER.add_section("besapi")
|
|
233
247
|
self.CONFPARSER.set("besapi", "BES_USER_NAME", user)
|
|
@@ -237,14 +251,14 @@ class BESCLInterface(Cmd):
|
|
|
237
251
|
if not root_server:
|
|
238
252
|
root_server = str(input("Root Server [%s]: " % self.BES_ROOT_SERVER))
|
|
239
253
|
|
|
240
|
-
self.BES_ROOT_SERVER = root_server
|
|
254
|
+
self.BES_ROOT_SERVER = root_server.strip()
|
|
241
255
|
|
|
242
256
|
else:
|
|
243
257
|
root_server = str(
|
|
244
258
|
input("Root Server (ex. %s): " % "https://server.institution.edu:52311")
|
|
245
259
|
)
|
|
246
260
|
if root_server:
|
|
247
|
-
self.BES_ROOT_SERVER = root_server
|
|
261
|
+
self.BES_ROOT_SERVER = root_server.strip()
|
|
248
262
|
if not self.CONFPARSER.has_section("besapi"):
|
|
249
263
|
self.CONFPARSER.add_section("besapi")
|
|
250
264
|
self.CONFPARSER.set("besapi", "BES_ROOT_SERVER", root_server)
|
|
@@ -312,10 +312,86 @@ def test_bes_conn_json():
|
|
|
312
312
|
assert result is not None
|
|
313
313
|
assert "TestString" in result
|
|
314
314
|
assert "BES Support" in result
|
|
315
|
+
print("testing session relevance with + in relevance")
|
|
316
|
+
str_relevance_plus = 'lengths of first matches (regex " +") of " "'
|
|
317
|
+
result = bes_conn.session_relevance_xml(str_relevance_plus)
|
|
318
|
+
print(result)
|
|
319
|
+
assert result is not None
|
|
315
320
|
else:
|
|
316
321
|
pytest.skip("Skipping BESConnection test, no config file or login failed.")
|
|
317
322
|
|
|
318
323
|
|
|
324
|
+
def test_bes_conn_session_relevance_with_plus():
|
|
325
|
+
"""Test the BESConnection class with JSON output."""
|
|
326
|
+
|
|
327
|
+
bes_conn = besapi.plugin_utilities.get_besapi_connection(None)
|
|
328
|
+
|
|
329
|
+
if bes_conn and bes_conn.login():
|
|
330
|
+
print("testing session relevance with + in relevance")
|
|
331
|
+
str_relevance_plus = 'lengths of first matches (regex " +") of " "'
|
|
332
|
+
str_relevance_answer = "8"
|
|
333
|
+
result = bes_conn.session_relevance_xml(str_relevance_plus)
|
|
334
|
+
print(result)
|
|
335
|
+
assert result is not None
|
|
336
|
+
print(result.request.request.body)
|
|
337
|
+
assert f'<Answer type="integer">{str_relevance_answer}</Answer>' in str(result)
|
|
338
|
+
result = bes_conn.session_relevance_json_string(str_relevance_plus)
|
|
339
|
+
print(result)
|
|
340
|
+
assert result is not None
|
|
341
|
+
assert str_relevance_answer in str(result)
|
|
342
|
+
result = bes_conn.session_relevance_json(str_relevance_plus)
|
|
343
|
+
print(result)
|
|
344
|
+
assert result is not None
|
|
345
|
+
assert f"[{str_relevance_answer}]" in str(result["result"])
|
|
346
|
+
result = bes_conn.session_relevance_string(str_relevance_plus)
|
|
347
|
+
print(result)
|
|
348
|
+
assert result is not None
|
|
349
|
+
assert str_relevance_answer in str(result)
|
|
350
|
+
result = bes_conn.session_relevance_array(str_relevance_plus)
|
|
351
|
+
print(result)
|
|
352
|
+
assert result is not None
|
|
353
|
+
assert f"['{str_relevance_answer}']" in str(result)
|
|
354
|
+
result = bes_conn.session_relevance_json_array(str_relevance_plus)
|
|
355
|
+
print(result)
|
|
356
|
+
assert result is not None
|
|
357
|
+
assert f"[{str_relevance_answer}]" in str(result)
|
|
358
|
+
|
|
359
|
+
# test already escaped +
|
|
360
|
+
str_relevance_plus = r'lengths of first matches (regex " %2b") of " "'
|
|
361
|
+
print(str_relevance_plus)
|
|
362
|
+
result = bes_conn.session_relevance_xml(str_relevance_plus)
|
|
363
|
+
print(result)
|
|
364
|
+
assert result is not None
|
|
365
|
+
print(result.request.request.body)
|
|
366
|
+
assert f'<Answer type="integer">{str_relevance_answer}</Answer>' in str(result)
|
|
367
|
+
else:
|
|
368
|
+
pytest.skip("Skipping BESConnection test, no config file or login failed.")
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
def test_bes_conn_upload_always():
|
|
372
|
+
"""Test the BESConnection class with JSON output."""
|
|
373
|
+
file_name = "LICENSE.txt"
|
|
374
|
+
file_path = "../" + file_name
|
|
375
|
+
if not os.path.isfile(os.path.abspath(file_path)):
|
|
376
|
+
# handle case where not running from src or tests folder.
|
|
377
|
+
file_path = "./" + file_name
|
|
378
|
+
assert os.path.isfile(os.path.abspath(file_path))
|
|
379
|
+
|
|
380
|
+
bes_conn = besapi.plugin_utilities.get_besapi_connection(None)
|
|
381
|
+
if bes_conn and bes_conn.login():
|
|
382
|
+
# test upload
|
|
383
|
+
# Example Header:: Content-Disposition: attachment; filename="file.xml"
|
|
384
|
+
headers = {"Content-Disposition": f'attachment; filename="{file_name}"'}
|
|
385
|
+
with open(file_path, "rb") as f:
|
|
386
|
+
result = bes_conn.post(bes_conn.url("upload"), data=f, headers=headers)
|
|
387
|
+
print(result)
|
|
388
|
+
assert result is not None
|
|
389
|
+
assert result.besobj.FileUpload.Available == 1
|
|
390
|
+
assert result.besdict["FileUpload"]["Available"] == "1"
|
|
391
|
+
else:
|
|
392
|
+
pytest.skip("Skipping BESConnection upload test, login failed.")
|
|
393
|
+
|
|
394
|
+
|
|
319
395
|
def test_plugin_utilities_logging():
|
|
320
396
|
"""Test the plugin_utilities module."""
|
|
321
397
|
print(besapi.plugin_utilities.get_invoke_folder())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|