<!-- MarkdownTOC -->
- [Feature: Run Enforcement against manual selection of Asset IDs](feature-run-enforcement-against-manual-selection-of-asset-ids)
- [Axonshell changes](axonshell-changes)
- [API Client library changes](api-client-library-changes)
- [Feature: support semi-colon instead of comma as CSV delimiter for env vars](feature-support-semi-colon-instead-of-comma-as-csv-delimiter-for-env-vars)
- [Bugfix: Role permissions throw KeyError for some RBAC category actions](bugfix-role-permissions-throw-keyerror-for-some-rbac-category-actions)
- [Bugfix: Reduce log output](bugfix-reduce-log-output)
<!-- /MarkdownTOC -->
Feature: Run Enforcement against manual selection of Asset IDs
Axonshell changes
New commands added to groups ``axonshell devices``, ``axonshell users``,
and ``axonshell vulnerabilities``:
- run-enforcement-from-jsonl: Grab Asset IDs from a JSONL file and run
an Enforcement Set against them.
bash
Notes:
1) --path must be a JSONL file with one dictionary per line
Example:
1) Get assets in JSONL format:
axonshell devices get --export-format json --json-flat --export-file data.jsonl --export-overwrite --wiz simple 'os.type equals windows'
2) Run an enforcement set against the asset IDs in the JSON file:
2a) prompting to verify the count:
axonshell devices run-enforcement-from-jsonl --path data.jsonl --eset test
2b) With no prompting (will error out if the count mismatches):
axonshell devices run-enforcement-from-jsonl --path data.jsonl --eset test --no-prompt
2c) With no verification because we know the asset IDs are valid for this instance:
axonshell devices run-enforcement-from-jsonl --path data.jsonl --eset test --verified
- run-enforcement-from-json: Grab Asset IDs from a JSON file and run an
Enforcement Set against them.
bash
Notes:
1) --path must be a JSON file containing a list of dictionaries
Example:
1) Get assets in JSON format:
axonshell devices get --export-format json --export-file data.json --export-overwrite --wiz simple 'os.type equals windows'
2) Run an enforcement set against the asset IDs in the JSON file:
2a) prompting to verify the count:
axonshell devices run-enforcement-from-json --path data.json --eset test
2b) With no prompting (will error out if the count mismatches):
axonshell devices run-enforcement-from-json --path data.json --eset test --no-prompt
2c) With no verification because we know the asset IDs are valid for this instance:
axonshell devices run-enforcement-from-json --path data.json --eset test --verified
- run-enforcement-from-csv: Grab Asset IDs from a CSV file and run an
Enforcement Set against them.
bash
Notes:
1) --path must be a CSV file with headers
2) --path can also be a CSV file exported from the GUI.
Example:
1) Get assets in CSV format:
axonshell devices get --export-format csv --export-file data.csv --export-overwrite --wiz simple 'os.type equals windows'
2) Run an enforcement set against the asset IDs in the CSV file:
2a) prompting to verify the count:
axonshell devices run-enforcement-from-csv --path data.csv --eset test
2b) With no prompting (will error out if the count mismatches):
axonshell devices run-enforcement-from-csv --path data.csv --eset test --no-prompt
2c) With no verification because we know the asset IDs are valid for this instance:
axonshell devices run-enforcement-from-csv --path data.csv --eset test --verified
- run-enforcement-from-text: Grab Asset IDs from any old text file and run an
Enforcement Set against them.
bash
Notes:
1) --path must be a text file with valid asset IDs
2) All lines will have any non alpha-numeric characters removed from them and
if a 32 character alpha numeric string is found it is considered an Asset ID.
Example:
1) Get assets in JSON format then use jq to extract the IDs to a text file:
axonshell devices get --export-format json --export-file data.json --export-overwrite --wiz simple 'os.type equals windows'
jq '.[].internal_axon_id' data.json > data.txt
2) Run an enforcement set against the asset IDs in the text file:
2a) prompting to verify the count:
axonshell devices run-enforcement-from-text --path data.txt --eset test
2b) With no prompting (will error out if the count mismatches):
axonshell devices run-enforcement-from-text --path data.txt --eset test --no-prompt
2c) With no verification because we know the asset IDs are valid for this instance:
axonshell devices run-enforcement-from-text --path data.txt --eset test --verified
API Client library changes
New Methods for client.devices/client.users/client.vulnerabilities:
- run_enforcement: Run an enforcement set against a manually selected list of assets.
python
'''Get a list of assets from a query and manually extract the IDs.
We know assets are valid because we just got them, so we pass verified=True.
'''
client = globals()['client'] instance of axonius_api_client.Connect
apiobj = client.devices client.devices, client.users, or client.vulnerabilities
WIZ = "simple os.type equals Windows" "query of assets to target"
ESET = "test" "name or uuid of enforcement set"
ITEMS = apiobj.get(wiz_entries=WIZ)
IDS = [x['internal_axon_id'] for x in ITEMS]
runner = apiobj.run_enforcement(eset=ESET, ids=IDS, verified=True)
print(runner)
'''
Runner(
state='Ran Enforcement Set against 31 supplied Asset IDs',
eset='test',
executed=True,
count_ids=31,
count_result=None,
verified=True,
verify_count=True,
prompt=False,
grabber=None,
)
'''
- run_enforcement_from_items: Get Asset IDs from a list of dicts or strs and run
an Enforcement Set against them.
python
'''Get a list of assets from a query and use the grabber get the IDs.
We know assets are valid because we just got them, so we pass verified=True.
'''
client = globals()['client'] instance of axonius_api_client.Connect
apiobj = client.devices client.devices, client.users, or client.vulnerabilities
WIZ = "simple os.type equals Windows" "query of assets to target"
ESET = "test" "name or uuid of enforcement set"
ITEMS = apiobj.get(wiz_entries=WIZ)
runner = apiobj.run_enforcement_from_items(eset=ESET, items=ITEMS, verified=True)
print(runner)
'''
Runner(
state='Ran Enforcement Set against 31 supplied Asset IDs',
eset='test',
executed=True,
count_ids=31,
count_result=None,
verified=True,
verify_count=True,
prompt=False,
grabber=Grabber(
count_supplied=31,
count_found=31,
do_echo=True,
do_raise=False,
source=None,
),
)
'''
- run_enforcement_from_json: Get Asset IDs from a JSON string with a list of
dicts and run an Enforcement Set against them.
python
'''Get a list of assets from a query and export the assets to a JSON str
then run an enforcement against all asset IDs from the JSON str.
We know assets are valid because we just got them, so we pass verified=True.
'''
import io
client = globals()['client'] instance of axonius_api_client.Connect
apiobj = client.devices client.devices, client.users, or client.vulnerabilities
WIZ = "simple os.type equals Windows" "query of assets to target"
ESET = "test" "name or uuid of enforcement set"
FH = io.StringIO()
z = apiobj.get(wiz_entries=WIZ, export="json", export_fd=FH, export_fd_close=False)
FH.seek(0)
ITEMS = FH.getvalue()
runner = apiobj.run_enforcement_from_json(eset=ESET, items=ITEMS, verified=True)
print(runner)
'''
Runner(
state='Ran Enforcement Set against 31 supplied Asset IDs',
eset='test',
executed=True,
count_ids=31,
count_result=None,
verified=True,
verify_count=True,
prompt=False,
grabber=Grabber(
count_supplied=31,
count_found=31,
do_echo=True,
do_raise=False,
source='from_json items type=str, length=15519 post_load type=list, length=31',
),
)
'''
python
'''Get a list of assets from a query and export the assets to a JSON file
then run an enforcement against all asset IDs from the JSON file.
We know assets are valid because we just got them, so we pass verified=True.
'''
import pathlib
client = globals()['client'] instance of axonius_api_client.Connect
apiobj = client.devices client.devices, client.users, or client.vulnerabilities
WIZ = "simple os.type equals Windows" "query of assets to target"
ESET = "test" "name or uuid of enforcement set"
PATH = pathlib.Path("data.json")
z = apiobj.get(wiz_entries=WIZ, export="json", export_file=PATH, export_overwrite=True)
runner = apiobj.run_enforcement_from_json(eset=ESET, items=PATH, verified=True)
print(runner)
'''
Runner(
state='Ran Enforcement Set against 31 supplied Asset IDs',
eset='test',
executed=True,
count_ids=31,
count_result=None,
verified=True,
verify_count=True,
prompt=False,
grabber=Grabber(
count_supplied=31,
count_found=31,
do_echo=True,
do_raise=False,
source='from_json items type=PosixPath, length=None post_load type=list, length=31',
),
)
'''
- run_enforcement_from_jsonl: Get Asset IDs from a JSONL string with one dict
per line and run an Enforcement Set against them.
python
'''Get a list of assets from a query and export the assets to a JSONL str
then run an enforcement against all asset IDs from the JSONL str.
We know assets are valid because we just got them, so we pass verified=True.
'''
import io
client = globals()['client'] instance of axonius_api_client.Connect
apiobj = client.devices client.devices, client.users, or client.vulnerabilities
WIZ = "simple os.type equals Windows" "query of assets to target"
ESET = "test" "name or uuid of enforcement set"
FH = io.StringIO()
z = apiobj.get(
wiz_entries=WIZ, export="json", json_flat=True, export_fd=FH, export_fd_close=False)
FH.seek(0)
runner = apiobj.run_enforcement_from_jsonl(eset=ESET, items=FH, verified=True)
print(runner)
'''
Runner(
state='Ran Enforcement Set against 31 supplied Asset IDs',
eset='test',
executed=True,
count_ids=31,
count_result=None,
verified=True,
verify_count=True,
prompt=False,
grabber=Grabber(
count_supplied=31,
count_found=31,
do_echo=True,
do_raise=False,
source='from_jsonl items type=StringIO, length=None post_load type=list, length=31',
),
)
'''
python
'''Get a list of assets from a query and export the assets to a JSONL file
then run an enforcement against all asset IDs from the JSONL file.
We know assets are valid because we just got them, so we pass verified=True.
'''
import pathlib
client = globals()['client'] instance of axonius_api_client.Connect
apiobj = client.devices client.devices, client.users, or client.vulnerabilities
WIZ = "simple os.type equals Windows" "query of assets to target"
ESET = "test" "name or uuid of enforcement set"
PATH = pathlib.Path("data.jsonl")
z = apiobj.get(
wiz_entries=WIZ, export="json", json_flat=True, export_file=PATH, export_overwrite=True)
runner = apiobj.run_enforcement_from_jsonl(eset=ESET, items=PATH, verified=True)
print(runner)
'''
Runner(
state='Ran Enforcement Set against 31 supplied Asset IDs',
eset='test',
executed=True,
count_ids=31,
count_result=None,
verified=True,
verify_count=True,
prompt=False,
grabber=Grabber(
count_supplied=31,
count_found=31,
do_echo=True,
do_raise=False,
source='from_jsonl items type=PosixPath, length=None post_load type=list, length=31',
),
)
'''
- run_enforcement_from_csv: Get Asset IDs from a CSV string and run
an Enforcement Set against them.
python
'''Get a list of assets from a query and export the assets to a JSONL str
then run an enforcement against all asset IDs from the JSONL str.
We can also use a CSV file exported from the GUI.
We know assets are valid because we just got them, so we pass verified=True.
'''
from axonius_api_client.tools import bom_strip
import io
client = globals()['client'] instance of axonius_api_client.Connect
apiobj = client.devices client.devices, client.users, or client.vulnerabilities
WIZ = "simple os.type equals Windows" "query of assets to target"
ESET = "test" "name or uuid of enforcement set"
FH = io.StringIO()
z = apiobj.get(wiz_entries=WIZ, export="csv", export_fd=FH, export_fd_close=False)
FH.seek(0)
ITEMS = bom_strip(FH.getvalue())
runner = apiobj.run_enforcement_from_csv(eset=ESET, items=ITEMS, verified=True)
print(runner)
'''
Runner(
state='Ran Enforcement Set against 31 supplied Asset IDs',
eset='test',
executed=True,
count_ids=31,
count_result=None,
verified=True,
verify_count=True,
prompt=False,
grabber=Grabber(
count_supplied=33,
count_found=31,
do_echo=True,
do_raise=False,
source='from_csv items type=str, length=6556 post_load type=list, length=33',
),
)
'''
python
'''Get a list of assets from a query and export the assets to a CSV file
then run an enforcement against all asset IDs from the CSV file.
We can also use a CSV file exported from the GUI.
We know assets are valid because we just got them, so we pass verified=True.
'''
import pathlib
client = globals()['client'] instance of axonius_api_client.Connect
apiobj = client.devices client.devices, client.users, or client.vulnerabilities
WIZ = "simple os.type equals Windows" "query of assets to target"
ESET = "test" "name or uuid of enforcement set"
PATH = pathlib.Path("data.csv")
z = apiobj.get(wiz_entries=WIZ, export="csv", export_file=PATH, export_overwrite=True)
runner = apiobj.run_enforcement_from_csv(eset=ESET, items=PATH, verified=True)
print(runner)
'''
Runner(
state='Ran Enforcement Set against 31 supplied Asset IDs',
eset='test',
executed=True,
count_ids=31,
count_result=None,
verified=True,
verify_count=True,
prompt=False,
grabber=Grabber(
count_supplied=33,
count_found=31,
do_echo=True,
do_raise=False,
source='from_csv items type=PosixPath, length=None post_load type=list, length=33',
),
)
'''
- run_enforcement_from_text: Get Asset IDs from a text string and run
an Enforcement Set against them.
python
'''Get a list of assets from a query and export the assets to a text file
then run an enforcement against all asset IDs from the text file.
All lines will have any non alpha-numeric characters removed from them and if a
32 character alpha numeric string is found it is considered an Asset ID.
We know assets are valid because we just got them, so we pass verified=True.
'''
import pathlib
client = globals()['client'] instance of axonius_api_client.Connect
apiobj = client.devices client.devices, client.users, or client.vulnerabilities
WIZ = "simple os.type equals Windows" "query of assets to target"
ESET = "test" "name or uuid of enforcement set"
PATH = pathlib.Path("data.txt")
ASSETS = apiobj.get(wiz_entries=WIZ)
IDS = [x['internal_axon_id'] for x in ASSETS]
PATH.write_text('\n'.join(IDS))
runner = apiobj.run_enforcement_from_text(eset=ESET, items=PATH, verified=True)
print(runner)
'''
Runner(
state='Ran Enforcement Set against 31 supplied Asset IDs',
eset='test',
executed=True,
count_ids=31,
count_result=None,
verified=True,
verify_count=True,
prompt=False,
grabber=Grabber(
count_supplied=31,
count_found=31,
do_echo=True,
do_raise=False,
source='from_text items type=PosixPath, length=None',
),
)
'''
- run_enforcement_from_json_path: Get Asset IDs from a JSON file with a list of
dicts and run an Enforcement Set against them.
python
'''Run an enforcement against all asset IDs from a JSON file.
We are unsure if Asset IDs are still valid for this instance so
we do not pass verified=True.
'''
client = globals()['client'] instance of axonius_api_client.Connect
apiobj = client.devices client.devices, client.users, or client.vulnerabilities
PATH = "data.json"
ESET = "test" "name or uuid of enforcement set"
runner = apiobj.run_enforcement_from_json_path(eset=ESET, path=PATH)
print(runner)
'''
Runner(
state='Ran Enforcement Set against 31 supplied Asset IDs',
eset='test',
executed=True,
count_ids=31,
count_result=31,
verified=True,
verify_count=True,
prompt=False,
grabber=Grabber(
count_supplied=31,
count_found=31,
do_echo=True,
do_raise=False,
source='from_json_path /Users/jimbo/gh/Axonius/axonapi/data.json /
from_json items type=PosixPath, length=None post_load
type=list, length=31',
),
)
'''
- run_enforcement_from_jsonl_path: Get Asset IDs from a JSONL file with one
dict per line and run an Enforcement Set against them.
python
'''Run an enforcement against all asset IDs from a JSONL file.
We are unsure if Asset IDs are still valid for this instance so
we do not pass verified=True.
'''
client = globals()['client'] instance of axonius_api_client.Connect
apiobj = client.devices client.devices, client.users, or client.vulnerabilities
PATH = "data.jsonl"
ESET = "test" "name or uuid of enforcement set"
runner = apiobj.run_enforcement_from_jsonl_path(eset=ESET, path=PATH)
print(runner)
'''
Runner(
state='Ran Enforcement Set against 31 supplied Asset IDs',
eset='test',
executed=True,
count_ids=31,
count_result=31,
verified=True,
verify_count=True,
prompt=False,
grabber=Grabber(
count_supplied=31,
count_found=31,
do_echo=True,
do_raise=False,
source='from_jsonl_path /Users/jimbo/gh/Axonius/axonapi/data.jsonl /
from_jsonl items type=PosixPath, length=None post_load type=list, length=31',
),
)
'''
- run_enforcement_from_csv_path: Get Asset IDs from a CSV file and run
an Enforcement Set against them.
python
'''Run an enforcement against all asset IDs from a JSONL file.
We are unsure if Asset IDs are still valid for this instance so
we do not pass verified=True.
'''
client = globals()['client'] instance of axonius_api_client.Connect
apiobj = client.devices client.devices, client.users, or client.vulnerabilities
PATH = "data.csv"
ESET = "test" "name or uuid of enforcement set"
runner = apiobj.run_enforcement_from_csv_path(eset=ESET, path=PATH)
print(runner)
'''
Runner(
state='Ran Enforcement Set against 31 supplied Asset IDs',
eset='test',
executed=True,
count_ids=31,
count_result=31,
verified=True,
verify_count=True,
prompt=False,
grabber=Grabber(
count_supplied=33,
count_found=31,
do_echo=True,
do_raise=False,
source='from_csv_path /Users/jimbo/gh/Axonius/axonapi/data.csv /
from_csv items type=PosixPath, length=None post_load type=list, length=33',
),
)
'''
- run_enforcement_from_text_path: Get Asset IDs from a text file and run
an Enforcement Set against them.
python
'''Run an enforcement against all asset IDs from a text file.
All lines will have any non alpha-numeric characters removed from them and if a
32 character alpha numeric string is found it is considered an Asset ID.
We are unsure if Asset IDs are still valid for this instance so
we do not pass verified=True.
'''
client = globals()['client'] instance of axonius_api_client.Connect
apiobj = client.devices client.devices, client.users, or client.vulnerabilities
PATH = "data.txt"
ESET = "test" "name or uuid of enforcement set"
runner = apiobj.run_enforcement_from_text_path(eset=ESET, path=PATH)
print(runner)
'''
Runner(
state='Ran Enforcement Set against 31 supplied Asset IDs',
eset='test',
executed=True,
count_ids=31,
count_result=None,
verified=True,
verify_count=True,
prompt=False,
grabber=Grabber(
count_supplied=31,
count_found=31,
do_echo=True,
do_raise=False,
source='from_text_path /Users/jimbo/gh/Axonius/axonapi/data.txt /
from_text items type=PosixPath, length=None post_load type=generator, length=None',
),
)
'''
- _run_enforcement: Direct API method to run an Enforcement Set against a
list of Asset IDs
New classes:
- axonius_api_client.api.assets.runner.Runner: verify Asset IDs and run
an enforcement set against them
- axonius_api_client.parsers.grabber.Grabber: grab asset IDs from various
export formats (csv, json, jsonl, text)
- axonius_api_client.constants.fields.AXID: global constant for working with
Asset IDs (ala internal_axon_id)
New Schemas:
- axonius_api_client.api.json_api.assets.RunEnforcementRequestSchema
- axonius_api_client.api.json_api.assets.RunEnforcementRequest
- axonius_api_client.api.json_api.selection.IdSelectionSchema
- axonius_api_client.api.json_api.selection.IdSelection
Feature: support semi-colon instead of comma as CSV delimiter for env vars
- prepending the env var value with "semi:" will now
use ; instead of , as the delimiter for CSV strings passed to AX_COOKIES
and AX_HEADERS, i.e.:
bash
export AX_HEADERS="semi:key1=value1;key2=value2"
Bugfix: Role permissions throw KeyError for some RBAC category actions
- Fallback to False if an action for an RBAC category is not defined on a roles permissions
Bugfix: Reduce log output
- Reduced log spam from Http to make logs easier to read
What's Changed
* Feature/enforcement run manual selection by lifehackjim in https://github.com/Axonius/axonius_api_client/pull/207
* Fix typos by mcsalgado in https://github.com/Axonius/axonius_api_client/pull/204
* 4.40.6 by lifehackjim in https://github.com/Axonius/axonius_api_client/pull/208
New Contributors
* mcsalgado made their first contribution in https://github.com/Axonius/axonius_api_client/pull/204
**Full Changelog**: https://github.com/Axonius/axonius_api_client/compare/4.40.5...4.40.6