Skip to content

Commit

Permalink
add backup,update,remove of custom compliance and linux
Browse files Browse the repository at this point in the history
  • Loading branch information
almenscorner committed Mar 3, 2024
1 parent 8e88459 commit 7862ae6
Show file tree
Hide file tree
Showing 19 changed files with 2,729 additions and 6 deletions.
161 changes: 161 additions & 0 deletions src/IntuneCD/backup/Intune/backup_compliancePolicies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
This module backs up all Compliance Polices in Intune.
"""

from ...intunecdlib.check_prefix import check_prefix_match
from ...intunecdlib.clean_filename import clean_filename
from ...intunecdlib.graph_batch import batch_assignment, get_object_assignment
from ...intunecdlib.graph_request import makeapirequest, makeAuditRequest
from ...intunecdlib.process_audit_data import process_audit_data
from ...intunecdlib.process_scope_tags import get_scope_tags_name
from ...intunecdlib.remove_keys import remove_keys
from ...intunecdlib.save_output import save_output

# Set MS Graph endpoint
ENDPOINT = "https://graph.microsoft.com/beta/deviceManagement/compliancePolicies"


def _check_linux_discovery_script(data):
if isinstance(data, dict):
if "linux_customcompliance_discoveryscript" in data.values():
return True
return any(_check_linux_discovery_script(v) for v in data.values())
if isinstance(data, list):
return any(_check_linux_discovery_script(v) for v in data)
return False


def _get_detection_script_id(data, path=None):
if path is None:
path = []
if isinstance(data, dict):
for k, v in data.items():
if isinstance(v, dict):
new_path = _get_detection_script_id(v, path + [k])
if new_path is not None:
return new_path
elif isinstance(v, list):
for i, item in enumerate(v):
new_path = _get_detection_script_id(item, path + [k, i])
if new_path is not None:
return new_path
elif v == "linux_customcompliance_discoveryscript":
return path
return None


def _get_value_from_path(data, path):
for key in path:
if isinstance(data, list):
data = data[int(key)]
else:
data = data[key]
return data["simpleSettingValue"]["value"]


# Get all Compliance policies and save them in specified path
def savebackup(path, output, exclude, token, prefix, append_id, audit, scope_tags):
"""
Saves all Compliance policies in Intune to a JSON or YAML file.
:param path: Path to save the backup to
:param output: Format the backup will be saved as
:param exclude: If "assignments" is in the list, it will not back up the assignments
:param token: Token to use for authenticating the request
"""

results = {"config_count": 0, "outputs": []}
audit_data = None
configpath = path + "/" + "Compliance Policies/Policies/"
q_param = {
"$expand": "settings",
}
data = makeapirequest(ENDPOINT, token, q_param)

assignment_responses = batch_assignment(
data, "deviceManagement/compliancePolicies/", "/assignments", token
)
if audit:
graph_filter = "componentName eq 'DeviceCompliancePolicy'"
audit_data = makeAuditRequest(graph_filter, token)

for policy in data["value"]:
if prefix and not check_prefix_match(policy["name"], prefix):
continue

# Is the policy a Linux discovery script?
if _check_linux_discovery_script(policy):
# Get the detection script ID
detection_script_id_path = _get_detection_script_id(policy)
if detection_script_id_path is not None:
detection_script_id = _get_value_from_path(
policy, detection_script_id_path
)
# get the script name
detection_script = makeapirequest(
"https://graph.microsoft.com/beta/deviceManagement/reusablePolicySettings/",
token,
{"$filter": f"id eq '{detection_script_id}'"},
)
if detection_script["value"]:
policy["detectionScriptName"] = detection_script["value"][0][
"displayName"
]

# get scheduledActionsForRule
scheduledActionsForRule = makeapirequest(
f"{ENDPOINT}/{policy['id']}/scheduledActionsForRule",
token,
{"$expand": "scheduledActionConfigurations"},
)

policy["scheduledActionsForRule"] = scheduledActionsForRule["value"]

results["config_count"] += 1
print("Backing up compliance policy: " + policy["name"])

if scope_tags:
policy = get_scope_tags_name(policy, scope_tags)

if "assignments" not in exclude:
assignments = get_object_assignment(policy["id"], assignment_responses)
if assignments:
policy["assignments"] = assignments

graph_id = policy["id"]
policy = remove_keys(policy)
for rule in policy["scheduledActionsForRule"]:
remove_keys(rule)
if policy["scheduledActionsForRule"]:
for scheduled_config in policy["scheduledActionsForRule"][0][
"scheduledActionConfigurations"
]:
remove_keys(scheduled_config)

# Get filename without illegal characters
fname = clean_filename(policy["name"])
if append_id:
fname = f"{fname}_{policy['technologies']}__{graph_id}"
else:
fname = f"{fname}_{policy['technologies']}"
# Save Compliance policy as JSON or YAML depending on configured value
# in "-o"
save_output(
output,
configpath,
fname,
policy,
)

results["outputs"].append(fname)

if audit_data:
compare_data = {"type": "resourceId", "value": graph_id}
process_audit_data(
audit_data, compare_data, path, f"{configpath}{fname}.{output}"
)

return results
99 changes: 99 additions & 0 deletions src/IntuneCD/backup/Intune/backup_complianceScripts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
This module backs up all Compliance scripts in Intune.
"""

import base64
import os

from ...intunecdlib.check_prefix import check_prefix_match
from ...intunecdlib.clean_filename import clean_filename
from ...intunecdlib.graph_batch import batch_request
from ...intunecdlib.graph_request import makeapirequest, makeAuditRequest
from ...intunecdlib.process_audit_data import process_audit_data
from ...intunecdlib.process_scope_tags import get_scope_tags_name
from ...intunecdlib.remove_keys import remove_keys
from ...intunecdlib.save_output import save_output

# Set MS Graph endpoint
ENDPOINT = "https://graph.microsoft.com/beta/deviceManagement/deviceComplianceScripts/"


# Get all Compliance scripts and save them in specified path
def savebackup(path, output, token, prefix, append_id, audit, scope_tags):
"""
Saves all Compliance scripts in Intune to a JSON or YAML file and script files.
:param path: Path to save the backup to
:param output: Format the backup will be saved as
:param exclude: If "assignments" is in the list, it will not back up the assignments
:param token: Token to use for authenticating the request
"""

results = {"config_count": 0, "outputs": []}
audit_data = None
configpath = path + "/" + "Compliance Policies/Scripts/"
data = makeapirequest(ENDPOINT, token)
if data["value"]:
script_ids = []
for script in data["value"]:
script_ids.append(script["id"])

script_data_responses = batch_request(
script_ids, "deviceManagement/deviceComplianceScripts/", "", token
)
if audit:
graph_filter = "componentName eq 'DeviceConfiguration'"
audit_data = makeAuditRequest(graph_filter, token)

for script_data in script_data_responses:
if prefix and not check_prefix_match(script_data["displayName"], prefix):
continue

results["config_count"] += 1

if scope_tags:
script_data = get_scope_tags_name(script_data, scope_tags)

graph_id = script_data["id"]
script_data = remove_keys(script_data)

print("Backing up Compliance script: " + script_data["displayName"])

# Get filename without illegal characters
fname = clean_filename(script_data["displayName"])

script_file_name = script_data["displayName"]
if append_id:
fname = f"{fname}__{graph_id}"
script_name = script_data["displayName"].replace(".ps1", "")
script_file_name = f"{script_name}__{graph_id}.ps1"
# Save Compliance script as JSON or YAML depending on configured value
# in "-o"
save_output(output, configpath, fname, script_data)

results["outputs"].append(fname)

if audit_data:
compare_data = {"type": "resourceId", "value": graph_id}
process_audit_data(
audit_data, compare_data, path, f"{configpath}{fname}.{output}"
)

# Save Compliance script data to the script data folder
if script_data.get("detectionScriptContent"):
if not os.path.exists(configpath + "Script Data/"):
os.makedirs(configpath + "Script Data/")
decoded = base64.b64decode(
script_data["detectionScriptContent"]
).decode("utf-8")
f = open(
configpath + "Script Data/" + script_file_name,
"w",
encoding="utf-8",
)
f.write(decoded)

return results
101 changes: 101 additions & 0 deletions src/IntuneCD/backup/Intune/backup_reusablePolicySettings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
This module backs up all Compliance scripts in Intune.
"""

import base64
import os

from ...intunecdlib.check_prefix import check_prefix_match
from ...intunecdlib.clean_filename import clean_filename
from ...intunecdlib.graph_request import makeapirequest, makeAuditRequest
from ...intunecdlib.process_audit_data import process_audit_data
from ...intunecdlib.process_scope_tags import get_scope_tags_name
from ...intunecdlib.remove_keys import remove_keys
from ...intunecdlib.save_output import save_output

# Set MS Graph endpoint
ENDPOINT = "https://graph.microsoft.com/beta/deviceManagement/reusablePolicySettings/"


# Get all Compliance scripts and save them in specified path
def savebackup(path, output, token, prefix, append_id, audit, scope_tags):
"""
Saves all Compliance scripts in Intune to a JSON or YAML file and script files.
:param path: Path to save the backup to
:param output: Format the backup will be saved as
:param exclude: If "assignments" is in the list, it will not back up the assignments
:param token: Token to use for authenticating the request
"""

results = {"config_count": 0, "outputs": []}
audit_data = None
configpath = path + "/" + "Compliance Policies/Scripts/"
data = makeapirequest(ENDPOINT, token)
if data["value"]:
if audit:
graph_filter = "componentName eq 'DeviceConfiguration'"
audit_data = makeAuditRequest(graph_filter, token)
for policy in data["value"]:
q_param = {
"$select": "id,settinginstance,displayname,description,settingDefinitionId,version"
}
policy = makeapirequest(f"{ENDPOINT}/{policy['id']}", token, q_param)

if (
policy.get("settingDefinitionId")
!= "linux_customcompliance_discoveryscript_reusablesetting"
):
continue

if prefix and not check_prefix_match(policy["displayName"], prefix):
continue

results["config_count"] += 1

if scope_tags:
script_data = get_scope_tags_name(policy, scope_tags)

graph_id = policy["id"]
script_data = remove_keys(policy)

print("Backing up Reusable policy setting: " + policy["displayName"])

# Get filename without illegal characters
fname = clean_filename(policy["displayName"])

script_file_name = script_data["displayName"]
if append_id:
fname = f"{fname}__{graph_id}"
script_name = policy["displayName"].replace(".sh", "")
script_file_name = f"{script_name}__{graph_id}.sh"
# Save Compliance script as JSON or YAML depending on configured value
# in "-o"
save_output(output, configpath, fname, script_data)

results["outputs"].append(fname)

if audit_data:
compare_data = {"type": "resourceId", "value": graph_id}
process_audit_data(
audit_data, compare_data, path, f"{configpath}{fname}.{output}"
)

# Save Compliance script data to the script data folder
if script_data.get("settingInstance").get("simpleSettingValue"):
if not os.path.exists(configpath + "Script Data/"):
os.makedirs(configpath + "Script Data/")
decoded = base64.b64decode(
script_data["settingInstance"]["simpleSettingValue"]["value"]
).decode("utf-8")
f = open(
configpath + "Script Data/" + script_file_name,
"w",
encoding="utf-8",
)
f.write(decoded)

return results
23 changes: 23 additions & 0 deletions src/IntuneCD/backup_intune.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,29 @@ def backup_intune(results, path, output, exclude, token, prefix, append_id, args
savebackup(path, output, exclude, token, append_id, args.audit, scope_tags)
)

if "DeviceCompliancePolicies" not in exclude:
from .backup.Intune.backup_compliancePolicies import savebackup

results.append(
savebackup(
path, output, exclude, token, prefix, append_id, args.audit, scope_tags
)
)

if "ReusablePolicySettings" not in exclude:
from .backup.Intune.backup_reusablePolicySettings import savebackup

results.append(
savebackup(path, output, token, prefix, append_id, args.audit, scope_tags)
)

if "ComplianceScripts" not in exclude:
from .backup.Intune.backup_complianceScripts import savebackup

results.append(
savebackup(path, output, token, prefix, append_id, args.audit, scope_tags)
)

if "Compliance" not in exclude:
from .backup.Intune.backup_compliance import savebackup

Expand Down
Loading

0 comments on commit 7862ae6

Please sign in to comment.