From 6f5921ce8d510da9ce07fd86af86ca62b3453379 Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Wed, 30 Jul 2025 01:24:44 +1000 Subject: [PATCH 01/63] Add engine rule script and CI workflow for container image build --- .github/workflows/engine-ci.yml | 26 ++++++++++++++++++++++++++ .gitignore | 0 docker/engine.Dockerfile | 13 +++++++++++++ engine/main.py | 29 +++++++++++++++++++++++++++++ rules/CIS_1.1.2.json | 9 +++++++++ test-configs/compliant.json | 3 +++ 6 files changed, 80 insertions(+) create mode 100644 .github/workflows/engine-ci.yml create mode 100644 .gitignore create mode 100644 docker/engine.Dockerfile create mode 100644 engine/main.py create mode 100644 rules/CIS_1.1.2.json create mode 100644 test-configs/compliant.json diff --git a/.github/workflows/engine-ci.yml b/.github/workflows/engine-ci.yml new file mode 100644 index 00000000..c47ffc80 --- /dev/null +++ b/.github/workflows/engine-ci.yml @@ -0,0 +1,26 @@ +name: Engine Container Build + +on: + push: + branches: [engine] + pull_request: + branches: [engine] + +jobs: + build-engine: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Docker + run: docker --version + + - name: Build engine container + run: | + docker build -t autoaudit/engine -f docker/engine.Dockerfile . + + - name: Run engine container + run: | + docker run --rm autoaudit/engine diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/docker/engine.Dockerfile b/docker/engine.Dockerfile new file mode 100644 index 00000000..89e97865 --- /dev/null +++ b/docker/engine.Dockerfile @@ -0,0 +1,13 @@ +# Use a lightweight Python base image +FROM python:3.11-slim + +# Set the working directory inside the container +WORKDIR /app + +# Copy only necessary files +COPY engine/ ./engine/ +COPY rules/ ./rules/ +COPY test-configs/ ./test-configs/ + +# Set the default command to run the rule engine +CMD ["python", "engine/main.py", "test-configs/compliant.json", "rules/CIS_1.1.2.json"] diff --git a/engine/main.py b/engine/main.py new file mode 100644 index 00000000..0e783271 --- /dev/null +++ b/engine/main.py @@ -0,0 +1,29 @@ +import json +import sys + +def evaluate_rule(config, rule): + setting = config.get("MFA", None) + expected = rule.get("expected_setting") + if setting == expected: + return {"rule": rule["id"], "status": "pass"} + return {"rule": rule["id"], "status": "fail"} + +def main(): + if len(sys.argv) != 3: + print("Usage: python main.py ") + sys.exit(1) + + config_path = sys.argv[1] + rule_path = sys.argv[2] + + with open(config_path) as f: + config = json.load(f) + + with open(rule_path) as f: + rule = json.load(f) + + result = evaluate_rule(config, rule) + print(json.dumps(result, indent=2)) + +if __name__ == "__main__": + main() diff --git a/rules/CIS_1.1.2.json b/rules/CIS_1.1.2.json new file mode 100644 index 00000000..4e45e417 --- /dev/null +++ b/rules/CIS_1.1.2.json @@ -0,0 +1,9 @@ +{ + "id": "CIS_1.1.2", + "description": "Ensure MFA is enabled", + "expected_setting": "enabled", + "severity": "High", + "score_weight": 5, + "remediation": "Enable MFA using Conditional Access or Security Defaults.", + "tag": "MFA" +} \ No newline at end of file diff --git a/test-configs/compliant.json b/test-configs/compliant.json new file mode 100644 index 00000000..b6043643 --- /dev/null +++ b/test-configs/compliant.json @@ -0,0 +1,3 @@ +{ + "MFA": "enabled" +} From 94fef4b601512edbf0b4fc41e71b03c72cb0222e Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Wed, 30 Jul 2025 01:29:06 +1000 Subject: [PATCH 02/63] Trigger CI for engine build --- engine/.trigger | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 engine/.trigger diff --git a/engine/.trigger b/engine/.trigger new file mode 100644 index 00000000..e69de29b From 687c976953c04ed13e8b8141b10e3cde6f2c843a Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Wed, 30 Jul 2025 01:29:54 +1000 Subject: [PATCH 03/63] aja --- .github/workflows/engine-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/engine-ci.yml b/.github/workflows/engine-ci.yml index c47ffc80..16b00596 100644 --- a/.github/workflows/engine-ci.yml +++ b/.github/workflows/engine-ci.yml @@ -2,9 +2,9 @@ name: Engine Container Build on: push: - branches: [engine] + branches: [Compliance-Engine] pull_request: - branches: [engine] + branches: [Compliance-Engine] jobs: build-engine: From e694009fc95ac91a74d473c2452a37f3e5735e28 Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Wed, 30 Jul 2025 01:36:33 +1000 Subject: [PATCH 04/63] trigger test --- engine/.trigger2 | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 engine/.trigger2 diff --git a/engine/.trigger2 b/engine/.trigger2 new file mode 100644 index 00000000..e69de29b From 0eebf5d4d99f53dd0c7b13e2eec0f22597b1fda7 Mon Sep 17 00:00:00 2001 From: 223159756 <139199818+223159756@users.noreply.github.com> Date: Wed, 30 Jul 2025 01:44:46 +1000 Subject: [PATCH 05/63] Update engine.Dockerfile --- docker/engine.Dockerfile | 7 ------- 1 file changed, 7 deletions(-) diff --git a/docker/engine.Dockerfile b/docker/engine.Dockerfile index 89e97865..f930eb13 100644 --- a/docker/engine.Dockerfile +++ b/docker/engine.Dockerfile @@ -1,13 +1,6 @@ -# Use a lightweight Python base image FROM python:3.11-slim - -# Set the working directory inside the container WORKDIR /app - -# Copy only necessary files COPY engine/ ./engine/ COPY rules/ ./rules/ COPY test-configs/ ./test-configs/ - -# Set the default command to run the rule engine CMD ["python", "engine/main.py", "test-configs/compliant.json", "rules/CIS_1.1.2.json"] From 96093f2b5f9ba23a6ffa0cb96a6918a0472b7a65 Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Wed, 30 Jul 2025 14:24:26 +1000 Subject: [PATCH 06/63] imporved main.py --- docker/engine.Dockerfile | 6 +---- engine/main.py | 54 +++++++++++++++++++++++-------------- rules/CIS_2.10.json | 9 +++++++ rules/CIS_5.2.json | 9 +++++++ test-configs/compliant.json | 10 +++++-- 5 files changed, 61 insertions(+), 27 deletions(-) create mode 100644 rules/CIS_2.10.json create mode 100644 rules/CIS_5.2.json diff --git a/docker/engine.Dockerfile b/docker/engine.Dockerfile index 89e97865..56e08bda 100644 --- a/docker/engine.Dockerfile +++ b/docker/engine.Dockerfile @@ -1,13 +1,9 @@ -# Use a lightweight Python base image FROM python:3.11-slim -# Set the working directory inside the container WORKDIR /app -# Copy only necessary files COPY engine/ ./engine/ COPY rules/ ./rules/ COPY test-configs/ ./test-configs/ -# Set the default command to run the rule engine -CMD ["python", "engine/main.py", "test-configs/compliant.json", "rules/CIS_1.1.2.json"] +CMD ["python", "engine/main.py"] diff --git a/engine/main.py b/engine/main.py index 0e783271..e90aaccb 100644 --- a/engine/main.py +++ b/engine/main.py @@ -1,29 +1,43 @@ import json -import sys +import os -def evaluate_rule(config, rule): - setting = config.get("MFA", None) - expected = rule.get("expected_setting") - if setting == expected: - return {"rule": rule["id"], "status": "pass"} - return {"rule": rule["id"], "status": "fail"} +def load_config(path="test-configs/compliant.json"): + with open(path) as f: + return json.load(f) -def main(): - if len(sys.argv) != 3: - print("Usage: python main.py ") - sys.exit(1) +def load_rules(directory="rules"): + rules = [] + for file in os.listdir(directory): + with open(os.path.join(directory, file)) as f: + rules.append(json.load(f)) + return rules - config_path = sys.argv[1] - rule_path = sys.argv[2] +def evaluate_rule(rule, config): + expected = rule.get("expected_setting") + tag = rule.get("tag") - with open(config_path) as f: - config = json.load(f) + path_map = { + "MFA": config.get("azure_ad", {}).get("mfa_status"), + "LegacyAuth": config.get("azure_ad", {}).get("legacy_authentication"), + "PhishingProtection": config.get("microsoft_forms", {}).get("phishing_protection"), + } - with open(rule_path) as f: - rule = json.load(f) + compliant = path_map.get(tag) + if compliant == expected: + return True, "Pass" + else: + return False, f"{tag} = {compliant}, but expected {expected}" + +def main(): + config = load_config() + rules = load_rules() - result = evaluate_rule(config, rule) - print(json.dumps(result, indent=2)) + for rule in rules: + result, reason = evaluate_rule(rule, config) + status = "PASS" if result else "FAIL" + print(f"[{status}] {rule['id']} - {rule['description']}") + if not result: + print(f" Reason: {reason}") if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/rules/CIS_2.10.json b/rules/CIS_2.10.json new file mode 100644 index 00000000..6b3d9175 --- /dev/null +++ b/rules/CIS_2.10.json @@ -0,0 +1,9 @@ +{ + "id": "CIS_2.10", + "description": "Ensure phishing protection is enabled in Microsoft Forms", + "expected_setting": "enabled", + "severity": "High", + "score_weight": 5, + "remediation": "Enable 'Phishing protection' in Microsoft Forms settings to block suspicious forms.", + "tag": "Forms, PhishingProtection" +} diff --git a/rules/CIS_5.2.json b/rules/CIS_5.2.json new file mode 100644 index 00000000..d86cae2d --- /dev/null +++ b/rules/CIS_5.2.json @@ -0,0 +1,9 @@ +{ + "id": "CIS_5.2", + "description": "Ensure Microsoft 365 audit log search is enabled", + "expected_setting": "enabled", + "severity": "High", + "score_weight": 5, + "remediation": "Go to Microsoft Purview → Audit and enable 'Start recording user and admin activity'.", + "tag": "AuditLogging, Purview" +} diff --git a/test-configs/compliant.json b/test-configs/compliant.json index b6043643..b4d27026 100644 --- a/test-configs/compliant.json +++ b/test-configs/compliant.json @@ -1,3 +1,9 @@ { - "MFA": "enabled" -} + "azure_ad": { + "mfa_status": "enabled", + "legacy_authentication": "disabled" + }, + "microsoft_forms": { + "phishing_protection": "enabled" + } +} \ No newline at end of file From c043818d7a18cec158088b549f8a69d3d950127e Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Thu, 31 Jul 2025 10:48:28 +1000 Subject: [PATCH 07/63] trigger --- engine/.trigger | 1 + 1 file changed, 1 insertion(+) diff --git a/engine/.trigger b/engine/.trigger index e69de29b..85df5078 100644 --- a/engine/.trigger +++ b/engine/.trigger @@ -0,0 +1 @@ +abcd \ No newline at end of file From e4d480b59ca575d5a9d62674e11bc9884cf2251d Mon Sep 17 00:00:00 2001 From: 223159756 <139199818+223159756@users.noreply.github.com> Date: Thu, 31 Jul 2025 10:50:27 +1000 Subject: [PATCH 08/63] Delete .github/workflows/engine-ci.yml --- .github/workflows/engine-ci.yml | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 .github/workflows/engine-ci.yml diff --git a/.github/workflows/engine-ci.yml b/.github/workflows/engine-ci.yml deleted file mode 100644 index 16b00596..00000000 --- a/.github/workflows/engine-ci.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Engine Container Build - -on: - push: - branches: [Compliance-Engine] - pull_request: - branches: [Compliance-Engine] - -jobs: - build-engine: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Set up Docker - run: docker --version - - - name: Build engine container - run: | - docker build -t autoaudit/engine -f docker/engine.Dockerfile . - - - name: Run engine container - run: | - docker run --rm autoaudit/engine From 03980026974cacaa0f89d55b6d5a92999ed6401e Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Thu, 31 Jul 2025 10:51:24 +1000 Subject: [PATCH 09/63] trigger2 --- engine/.trigger | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/.trigger b/engine/.trigger index 85df5078..5f6c6ab5 100644 --- a/engine/.trigger +++ b/engine/.trigger @@ -1 +1 @@ -abcd \ No newline at end of file +abcda \ No newline at end of file From a8b10e30d1b0ac6bba7d13342188fcfc7e7253b4 Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Thu, 31 Jul 2025 10:57:15 +1000 Subject: [PATCH 10/63] test --- engine/.trigger2 | 1 + 1 file changed, 1 insertion(+) diff --git a/engine/.trigger2 b/engine/.trigger2 index e69de29b..7c4a013e 100644 --- a/engine/.trigger2 +++ b/engine/.trigger2 @@ -0,0 +1 @@ +aaa \ No newline at end of file From 764381adf5e2f934bfa145c7711adbd1ba34a56d Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Thu, 31 Jul 2025 11:04:41 +1000 Subject: [PATCH 11/63] readd workflow --- github/workflows/engine.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 github/workflows/engine.yml diff --git a/github/workflows/engine.yml b/github/workflows/engine.yml new file mode 100644 index 00000000..fc33c2c2 --- /dev/null +++ b/github/workflows/engine.yml @@ -0,0 +1,25 @@ +name: Engine Container Build + +on: + push: + branches: [Compliance-Engine] + pull_request: + branches: [Compliance-Engine] + +jobs: + build-engine: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Docker + run: docker --version + + - name: Build engine container + run: | + docker build -t autoaudit/engine -f docker/engine.Dockerfile . + - name: Run engine container + run: | + docker run --rm autoaudit/engine \ No newline at end of file From ea4315ee9adbe760c77b1287a2c3b1fd8bbaefa5 Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Thu, 31 Jul 2025 11:07:34 +1000 Subject: [PATCH 12/63] a --- github/workflows/engine.yml | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100644 github/workflows/engine.yml diff --git a/github/workflows/engine.yml b/github/workflows/engine.yml deleted file mode 100644 index fc33c2c2..00000000 --- a/github/workflows/engine.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Engine Container Build - -on: - push: - branches: [Compliance-Engine] - pull_request: - branches: [Compliance-Engine] - -jobs: - build-engine: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Set up Docker - run: docker --version - - - name: Build engine container - run: | - docker build -t autoaudit/engine -f docker/engine.Dockerfile . - - name: Run engine container - run: | - docker run --rm autoaudit/engine \ No newline at end of file From e3fab81404369bac4afe17927ffcf958c38be60f Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Thu, 31 Jul 2025 11:08:55 +1000 Subject: [PATCH 13/63] readding workflow --- .github/workflows/engine-ci.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/engine-ci.yml diff --git a/.github/workflows/engine-ci.yml b/.github/workflows/engine-ci.yml new file mode 100644 index 00000000..8c6cb7cd --- /dev/null +++ b/.github/workflows/engine-ci.yml @@ -0,0 +1,27 @@ +name: Build Engine Branch + +on: + push: + branches: [Compliance-Engine] + +jobs: + build-engine-from-devops: + name: Build Engine Code + runs-on: ubuntu-latest + + steps: + - name: Checkout engine branch code + uses: actions/checkout@v3 + with: + ref: engine + + - name: Confirm branch + run: git branch + + - name: Build container + run: | + docker build -t autoaudit/engine -f docker/engine.Dockerfile . + + - name: Run engine container + run: | + docker run --rm autoaudit/engine From 463c19a84cbe72991132d029c8c3abd5dfc0c021 Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Thu, 31 Jul 2025 11:11:13 +1000 Subject: [PATCH 14/63] fix --- .github/workflows/engine-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/engine-ci.yml b/.github/workflows/engine-ci.yml index 8c6cb7cd..f31ab4ec 100644 --- a/.github/workflows/engine-ci.yml +++ b/.github/workflows/engine-ci.yml @@ -13,7 +13,7 @@ jobs: - name: Checkout engine branch code uses: actions/checkout@v3 with: - ref: engine + ref: Compliance-Engine - name: Confirm branch run: git branch From 8e0e4307bd8384a56b78533a05589bba1ec901d7 Mon Sep 17 00:00:00 2001 From: 223159756 <139199818+223159756@users.noreply.github.com> Date: Thu, 31 Jul 2025 13:33:51 +1000 Subject: [PATCH 15/63] Create gryp.yml --- .github/workflows/gryp.yml | 53 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 .github/workflows/gryp.yml diff --git a/.github/workflows/gryp.yml b/.github/workflows/gryp.yml new file mode 100644 index 00000000..2a26cc68 --- /dev/null +++ b/.github/workflows/gryp.yml @@ -0,0 +1,53 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +# This workflow checks out code, builds an image, performs a container image +# vulnerability scan with Anchore's Grype tool, and integrates the results with GitHub Advanced Security +# code scanning feature. For more information on the Anchore scan action usage +# and parameters, see https://github.com/anchore/scan-action. For more +# information on Anchore's container image scanning tool Grype, see +# https://github.com/anchore/grype +name: Anchore Grype vulnerability scan + +on: + push: + branches: [Compliance-Engine] + pull_request: + # The branches below must be a subset of the branches above + branches: [Compliance-Engine] + schedule: + - cron: '37 20 * * 4' + +permissions: + contents: read + +jobs: + Anchore-Build-Scan: + permissions: + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/upload-sarif to upload SARIF results + actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status + runs-on: ubuntu-latest + + steps: + - name: Check out the code + uses: actions/checkout@v4 + + - name: Build the Docker image + run: docker build -t devsecops-workflows:latest . + + - name: Run the Anchore Grype scan action + uses: anchore/scan-action@v3 + id: scan + + with: + image: devsecops-workflows:latest + fail-build: true + severity-cutoff: critical + + - name: Upload vulnerability report + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: ${{ steps.scan.outputs.sarif }} From 7a298391a1ccf2f614c273455cf7e92aeb322a2a Mon Sep 17 00:00:00 2001 From: 223159756 <139199818+223159756@users.noreply.github.com> Date: Thu, 31 Jul 2025 13:37:09 +1000 Subject: [PATCH 16/63] Update gryp.yml --- .github/workflows/gryp.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gryp.yml b/.github/workflows/gryp.yml index 2a26cc68..859df56a 100644 --- a/.github/workflows/gryp.yml +++ b/.github/workflows/gryp.yml @@ -36,14 +36,14 @@ jobs: uses: actions/checkout@v4 - name: Build the Docker image - run: docker build -t devsecops-workflows:latest . + run: docker build -t Compliance-Engine-workflows:latest . - name: Run the Anchore Grype scan action uses: anchore/scan-action@v3 id: scan with: - image: devsecops-workflows:latest + image: Compliance-Engine:latest fail-build: true severity-cutoff: critical From f37b7b0cc72a6009d5294bac1aa38dc8dc7393fd Mon Sep 17 00:00:00 2001 From: 223159756 <139199818+223159756@users.noreply.github.com> Date: Thu, 31 Jul 2025 13:38:24 +1000 Subject: [PATCH 17/63] Update gryp.yml --- .github/workflows/gryp.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gryp.yml b/.github/workflows/gryp.yml index 859df56a..56f95280 100644 --- a/.github/workflows/gryp.yml +++ b/.github/workflows/gryp.yml @@ -36,14 +36,14 @@ jobs: uses: actions/checkout@v4 - name: Build the Docker image - run: docker build -t Compliance-Engine-workflows:latest . + run: docker build -t compliance-engine-workflows:latest . - name: Run the Anchore Grype scan action uses: anchore/scan-action@v3 id: scan with: - image: Compliance-Engine:latest + image: compliance-engine:latest fail-build: true severity-cutoff: critical From af0724b735561aa3f98a107a71dcca915ab325a1 Mon Sep 17 00:00:00 2001 From: 223159756 <139199818+223159756@users.noreply.github.com> Date: Thu, 31 Jul 2025 13:41:00 +1000 Subject: [PATCH 18/63] Update gryp.yml --- .github/workflows/gryp.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gryp.yml b/.github/workflows/gryp.yml index 56f95280..fadf87a5 100644 --- a/.github/workflows/gryp.yml +++ b/.github/workflows/gryp.yml @@ -36,7 +36,7 @@ jobs: uses: actions/checkout@v4 - name: Build the Docker image - run: docker build -t compliance-engine-workflows:latest . + run: docker build -t compliance-engine-workflows:latest -f docker/engine.Dockerfile - name: Run the Anchore Grype scan action uses: anchore/scan-action@v3 From 475ab08346c7038ed6dd13a44b082703118a9773 Mon Sep 17 00:00:00 2001 From: 223159756 <139199818+223159756@users.noreply.github.com> Date: Thu, 31 Jul 2025 13:42:56 +1000 Subject: [PATCH 19/63] Update gryp.yml --- .github/workflows/gryp.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gryp.yml b/.github/workflows/gryp.yml index fadf87a5..25b8f308 100644 --- a/.github/workflows/gryp.yml +++ b/.github/workflows/gryp.yml @@ -36,7 +36,7 @@ jobs: uses: actions/checkout@v4 - name: Build the Docker image - run: docker build -t compliance-engine-workflows:latest -f docker/engine.Dockerfile + run: docker build -t compliance-engine-workflows:latest -f docker/engine.Dockerfile . - name: Run the Anchore Grype scan action uses: anchore/scan-action@v3 From 49212bce61851a8137f109e6e087d77a49b04790 Mon Sep 17 00:00:00 2001 From: 223159756 <139199818+223159756@users.noreply.github.com> Date: Thu, 31 Jul 2025 13:45:39 +1000 Subject: [PATCH 20/63] Update gryp.yml --- .github/workflows/gryp.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gryp.yml b/.github/workflows/gryp.yml index 25b8f308..87b73f6c 100644 --- a/.github/workflows/gryp.yml +++ b/.github/workflows/gryp.yml @@ -43,7 +43,7 @@ jobs: id: scan with: - image: compliance-engine:latest + image: docker:compliance-engine:latest fail-build: true severity-cutoff: critical From eb074538ddee112a6b133856cc9df475d8808a0d Mon Sep 17 00:00:00 2001 From: 223159756 <139199818+223159756@users.noreply.github.com> Date: Thu, 31 Jul 2025 13:49:00 +1000 Subject: [PATCH 21/63] Update gryp.yml --- .github/workflows/gryp.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gryp.yml b/.github/workflows/gryp.yml index 87b73f6c..efe78ee2 100644 --- a/.github/workflows/gryp.yml +++ b/.github/workflows/gryp.yml @@ -43,7 +43,7 @@ jobs: id: scan with: - image: docker:compliance-engine:latest + image: docker:compliance-engine-workflows:latest fail-build: true severity-cutoff: critical From c55405bc810e3ad948d54dbc125ee4b3e1d68f9c Mon Sep 17 00:00:00 2001 From: 223159756 <139199818+223159756@users.noreply.github.com> Date: Thu, 31 Jul 2025 15:59:06 +1000 Subject: [PATCH 22/63] Email test --- engine/.trigger | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/.trigger b/engine/.trigger index 5f6c6ab5..6183eec9 100644 --- a/engine/.trigger +++ b/engine/.trigger @@ -1 +1 @@ -abcda \ No newline at end of file +abcdaas From c8f8e5aa63da5b4ffb63d51bb169c3d163783579 Mon Sep 17 00:00:00 2001 From: 223159756 <139199818+223159756@users.noreply.github.com> Date: Thu, 31 Jul 2025 17:11:44 +1000 Subject: [PATCH 23/63] Add files via upload --- rules/rule schema (20250731).json | 301 ++++++++++++++++++++++++++++++ 1 file changed, 301 insertions(+) create mode 100644 rules/rule schema (20250731).json diff --git a/rules/rule schema (20250731).json b/rules/rule schema (20250731).json new file mode 100644 index 00000000..0473eb55 --- /dev/null +++ b/rules/rule schema (20250731).json @@ -0,0 +1,301 @@ +[ + { + "product": "Microsoft 365 admin center", + "id_level_1": 1.1, + "id_level_2": "", + "title": "Users", + "profile": "", + "level": "", + "status": "", + "description": "", + "expected_value": "", + "comparison": "", + "evaluation_path": "", + "remediation": "", + "risk": "", + "tags": "" + }, + { + "product": "Microsoft 365 admin center", + "id_level_1": 1.1, + "id_level_2": "1.1.1", + "title": "Ensure Administrative accounts are cloud-only", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Ensure administrative accounts are not On-premises sync enabled", + "expected_value": False, + "comparison": "equals", + "evaluation_path": "user.OnPremisesSyncEnabled", + "remediation": "Migrate hybrid admin accounts to new cloud-only accounts and update roles accordingly.", + "risk": "High", + "tags": "MFA +Identity +HybridEnvironment" + }, + { + "product": "Microsoft 365 admin center", + "id_level_1": 1.1, + "id_level_2": "1.1.2", + "title": "Ensure two emergency access accounts have been defined", + "profile": "E3 E5", + "level": "L1", + "status": "Manual", + "description": "Emergency access or �break glass� accounts are limited for emergency scenarios where normal administrative accounts are unavailable.", + "expected_value": "Two emergency access accounts defined", + "comparison": "Manual validation", + "evaluation_path": "Microsoft 365 admin center > Users > Active Users and Entra admin center > Protection > Conditional Access", + "remediation": "Create two cloud-only accounts with Global Admin role, no license, exclude from Conditional Access rules.", + "risk": "High", + "tags": "Accounts +EmergencyAccess +GlobalAdmin" + }, + { + "product": "Microsoft 365 admin center", + "id_level_1": 1.1, + "id_level_2": "1.1.3", + "title": "Ensure that between two and four global admins are designated", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Between two and four global administrators should be designated in the tenant to ensure redundancy and limit exposure.", + "expected_value": "2�4 Global Administrators", + "comparison": "Count and range check", + "evaluation_path": "Microsoft 365 admin center > Roles > Global Administrator", + "remediation": "Add or remove users from Global Admin role to maintain 2�4 total.", + "risk": "High", + "tags": "AdminAccounts +PrivilegeManagement" + }, + { + "product": "Microsoft 365 admin center", + "id_level_1": 1.1, + "id_level_2": "1.1.4", + "title": "Ensure administrative accounts use licenses with reduced application footprint", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Administrative accounts should not use licenses with applications to reduce attack surface.", + "expected_value": "License with no user applications (e.g. Entra ID P1/P2)", + "comparison": "License check", + "evaluation_path": "Microsoft 365 admin center > Users > Active users > License column", + "remediation": "Assign minimal license or Entra ID P1/P2 to admin accounts. Use PIM if applicable.", + "risk": "Medium", + "tags": "Licensing +AdminAccounts +LeastPrivilege" + }, + { + "product": "Microsoft 365 admin center", + "id_level_1": 1.2, + "id_level_2": "", + "title": "Teams & groups", + "profile": "", + "level": "", + "status": "", + "description": "", + "expected_value": "", + "comparison": "", + "evaluation_path": "", + "remediation": "", + "risk": "", + "tags": "" + }, + { + "product": "Microsoft 365 admin center", + "id_level_1": 1.2, + "id_level_2": "1.2.1", + "title": "Ensure that only organizationally managed/approved public groups exist", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Ensure that only organizationally managed and approved public groups exist to prevent unauthorized access to internal data.", + "expected_value": "No groups with public visibility", + "comparison": "Group.Visibility != Public", + "evaluation_path": "Microsoft 365 admin center > Teams & groups > Active teams & groups", + "remediation": "Change group privacy from Public to Private in group settings.", + "risk": "High", + "tags": "Groups +Privacy +AccessControl" + }, + { + "product": "Microsoft 365 admin center", + "id_level_1": 1.2, + "id_level_2": "1.2.2", + "title": "Ensure sign-in to shared mailboxes is blocked", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Block sign-in access for shared mailboxes to reduce exposure to unauthorized access.", + "expected_value": "Sign-in disabled for shared mailboxes", + "comparison": "user.AccountEnabled == false", + "evaluation_path": "Microsoft 365 admin center > Users > Active users > Shared mailbox properties", + "remediation": "Uncheck the 'Sign-in allowed' option under mailbox settings.", + "risk": "Medium", + "tags": "Mailbox +AccountAccess +Security" + }, + { + "product": "Microsoft 365 admin center", + "id_level_1": 1.3, + "id_level_2": "", + "title": "Settings", + "profile": "", + "level": "", + "status": "", + "description": "", + "expected_value": "", + "comparison": "", + "evaluation_path": "", + "remediation": "", + "risk": "", + "tags": "" + }, + { + "product": "Microsoft 365 admin center", + "id_level_1": 1.3, + "id_level_2": "1.3.1", + "title": "Ensure the 'Password expiration policy' is set to 'Set passwords to never expire (recommended)'", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Avoid enforcing periodic password changes unless a compromise is suspected.", + "expected_value": "Set passwords to never expire", + "comparison": "PasswordExpiration == Never", + "evaluation_path": "Microsoft 365 admin center > Org Settings > Security & Privacy > Password expiration policy", + "remediation": "Enable the 'Set passwords to never expire' option in org settings.", + "risk": "Medium", + "tags": "PasswordPolicy +UserSettings +Authentication" + }, + { + "product": "Microsoft 365 admin center", + "id_level_1": 1.3, + "id_level_2": "1.3.2", + "title": "Ensure 'Idle session timeout' is set to '3 hours (or less)' for unmanaged devices", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Limit idle session timeout for unmanaged devices to reduce session hijack risks.", + "expected_value": "Idle timeout set to = 3 hours", + "comparison": "IdleTimeout <= 3h", + "evaluation_path": "Microsoft 365 admin center > Org settings > Security & privacy > Idle session timeout", + "remediation": "Configure timeout policy in settings for unmanaged device sessions.", + "risk": "High", + "tags": "SessionTimeout +DeviceManagement +UnmanagedAccess" + }, + { + "product": "Microsoft 365 admin center", + "id_level_1": 1.3, + "id_level_2": "1.3.3", + "title": "Ensure 'External sharing' of calendars is not available", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Prevent external calendar sharing to avoid data leakage and preserve internal privacy.", + "expected_value": "External sharing disabled", + "comparison": "CalendarSharing == InternalOnly", + "evaluation_path": "Microsoft 365 admin center > Settings > Org settings > Calendar", + "remediation": "Disable external calendar sharing in org settings.", + "risk": "High", + "tags": "Calendar +ExternalSharing +Privacy" + }, + { + "product": "Microsoft 365 admin center", + "id_level_1": 1.3, + "id_level_2": "1.3.4", + "title": "Ensure 'User owned apps and services' is restricted", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Restrict user ability to register applications to control third-party integrations.", + "expected_value": "App registration disabled for users", + "comparison": "AppRegistration == Disabled", + "evaluation_path": "Microsoft Entra admin center > User settings > App registrations", + "remediation": "Disable 'Users can register applications' in user settings.", + "risk": "Medium", + "tags": "UserApps +ThirdPartyAccess +AppRegistration" + }, + { + "product": "Microsoft 365 admin center", + "id_level_1": 1.3, + "id_level_2": "1.3.5", + "title": "Ensure internal phishing protection for Forms is enabled", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Enable internal phishing detection for Microsoft Forms to prevent credential harvesting.", + "expected_value": "Phishing protection enabled", + "comparison": "FormsPhishingProtection == On", + "evaluation_path": "Microsoft 365 admin center > Settings > Org settings > Microsoft Forms", + "remediation": "Enable internal phishing protection in Microsoft Forms settings.", + "risk": "Medium", + "tags": "Forms +PhishingProtection +ThreatDetection" + }, + { + "product": "Microsoft 365 admin center", + "id_level_1": 1.3, + "id_level_2": "1.3.6", + "title": "Ensure the customer lockbox feature is enabled", + "profile": "E5", + "level": "L2", + "status": "Automated", + "description": "Require explicit customer approval before Microsoft can access customer content.", + "expected_value": "Customer lockbox enabled", + "comparison": "Lockbox == Enabled", + "evaluation_path": "Microsoft 365 compliance center > Solutions > Customer Lockbox", + "remediation": "Enable Customer Lockbox via Microsoft 365 compliance center.", + "risk": "High", + "tags": "CustomerLockbox +AccessControl +DataProtection" + }, + { + "product": "Microsoft 365 admin center", + "id_level_1": 1.3, + "id_level_2": "1.3.7", + "title": "Ensure 'third-party storage services' are restricted in 'Microsoft 365 on the web'", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Restrict access to third-party storage services like Dropbox or Google Drive to protect data.", + "expected_value": "Third-party storage access disabled", + "comparison": "ThirdPartyStorage == Disabled", + "evaluation_path": "Microsoft 365 admin center > Org settings > Services > Office for the web", + "remediation": "Disable integration with third-party storage services.", + "risk": "High", + "tags": "Storage +ExternalServices +DataControl" + }, + { + "product": "Microsoft 365 admin center", + "id_level_1": 1.3, + "id_level_2": "1.3.8", + "title": "Ensure that Sways cannot be shared with people outside of your organization", + "profile": "E3 E5", + "level": "L2", + "status": "Manual", + "description": "Prevent sharing of Microsoft Sway content outside the organization to maintain internal content privacy.", + "expected_value": "External sharing disabled for Sways", + "comparison": "SwaySharing == InternalOnly", + "evaluation_path": "Microsoft 365 admin center > Settings > Org settings > Sway", + "remediation": "Manually disable external sharing for Sway presentations.", + "risk": "Medium", + "tags": "Sway +ContentSharing +ExternalAccess" + }, + \ No newline at end of file From e414fe1b8cb249b15dc3a832770469158a8f2b5d Mon Sep 17 00:00:00 2001 From: calvinlinardy Date: Tue, 5 Aug 2025 20:54:28 +1000 Subject: [PATCH 24/63] Refactor main.py for scalability, error handling, and dynamic rule evaluation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This pull request enhances the main.py script in the compliance engine project with several key improvements: • Added error handling • Handles missing or unreadable configuration and rule files • Catches and reports invalid JSON formats gracefully • Implemented rule validation • Verifies that each rule JSON includes the required fields: id, tag, expected_setting, path, and description • Skips invalid rules while logging a warning • Replaced hardcoded tag mapping • Introduced get_value_by_path() function to dynamically evaluate configuration values based on rule-defined paths • Allows easier scalability for additional and more complex rule structures • Improved output and reporting • Clearly logs PASS/FAIL status for each rule along with the reason for failures • Summarizes total number of rules evaluated, with a count of passed and failed rules • Enhanced code readability • Added inline comments for clarity and maintainability • Organized logic to support easier team collaboration and future development --- engine/main.py | 78 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 17 deletions(-) diff --git a/engine/main.py b/engine/main.py index e90aaccb..2ed529bd 100644 --- a/engine/main.py +++ b/engine/main.py @@ -1,36 +1,72 @@ import json import os +# Load a JSON config file (mock tenant settings) def load_config(path="test-configs/compliant.json"): - with open(path) as f: - return json.load(f) + """Load the configuration JSON file. Returns an empty dict if file not found or invalid.""" + try: + with open(path) as f: + return json.load(f) + except FileNotFoundError: + print(f"❌ Config file not found: {path}") + return {} + except json.JSONDecodeError: + print(f"❌ Invalid JSON in config file: {path}") + return {} +# Load all JSON rules from the rules directory def load_rules(directory="rules"): + """Load all JSON rules from the given directory. Skips invalid files.""" rules = [] + if not os.path.exists(directory): + print(f"❌ Rules directory not found: {directory}") + return rules + for file in os.listdir(directory): - with open(os.path.join(directory, file)) as f: - rules.append(json.load(f)) + if file.endswith(".json"): + try: + with open(os.path.join(directory, file)) as f: + rule = json.load(f) + # Validate required keys + if all(k in rule for k in ("id", "tag", "expected_setting", "path", "description")): + rules.append(rule) + else: + print(f"⚠️ Skipping {file}: Missing required keys") + except json.JSONDecodeError: + print(f"⚠️ Invalid JSON in {file}") return rules +# Helper to get nested value using dot notation (e.g. "azure_ad.mfa_status") +def get_value_from_path(config, path): + """Extract a value from nested JSON using a dot-separated path.""" + keys = path.split(".") + for key in keys: + if isinstance(config, dict): + config = config.get(key, {}) + else: + return None + return config if config != {} else None + +# Evaluate one rule against the config def evaluate_rule(rule, config): + """Compare the expected setting with the actual config value.""" expected = rule.get("expected_setting") - tag = rule.get("tag") - - path_map = { - "MFA": config.get("azure_ad", {}).get("mfa_status"), - "LegacyAuth": config.get("azure_ad", {}).get("legacy_authentication"), - "PhishingProtection": config.get("microsoft_forms", {}).get("phishing_protection"), - } + value = get_value_from_path(config, rule.get("path")) - compliant = path_map.get(tag) - if compliant == expected: + if value == expected: return True, "Pass" - else: - return False, f"{tag} = {compliant}, but expected {expected}" + return False, f"{rule['tag']} = {value}, expected {expected}" +# Main function to run all rules and show results def main(): - config = load_config() - rules = load_rules() + config = load_config() # Load tenant configuration + rules = load_rules() # Load all CIS rules + + if not config or not rules: + print("❌ No config or rules found. Exiting.") + return + + passed, failed = 0, 0 for rule in rules: result, reason = evaluate_rule(rule, config) @@ -38,6 +74,14 @@ def main(): print(f"[{status}] {rule['id']} - {rule['description']}") if not result: print(f" Reason: {reason}") + passed += result + failed += not result + + # Summary output + print("\n📊 Summary:") + print(f" Total Rules: {len(rules)}") + print(f" ✅ Passed: {passed}") + print(f" ❌ Failed: {failed}") if __name__ == "__main__": main() \ No newline at end of file From bb80b02dfd0efd98dd20614711f3b9e319bfe368 Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Wed, 6 Aug 2025 23:00:32 +1000 Subject: [PATCH 25/63] Fixed Engine Script and parsed all rules --- .DS_Store | Bin 0 -> 6148 bytes engine/main.py | 10 +- rules/1.1.1.json | 20 ++ rules/1.1.2.json | 20 ++ rules/1.1.3.json | 19 ++ rules/1.1.4.json | 20 ++ rules/1.2.1.json | 20 ++ rules/1.2.2.json | 20 ++ rules/1.3.1.json | 20 ++ rules/1.3.2.json | 20 ++ rules/1.3.3.json | 20 ++ rules/1.3.4.json | 20 ++ rules/1.3.5.json | 20 ++ rules/1.3.6.json | 20 ++ rules/1.3.7.json | 20 ++ rules/1.3.8.json | 20 ++ rules/CIS_1.1.2.json | 9 - rules/CIS_2.10.json | 9 - rules/CIS_5.2.json | 9 - rules/rule schema (20250731).json | 301 ------------------------------ 20 files changed, 284 insertions(+), 333 deletions(-) create mode 100644 .DS_Store create mode 100644 rules/1.1.1.json create mode 100644 rules/1.1.2.json create mode 100644 rules/1.1.3.json create mode 100644 rules/1.1.4.json create mode 100644 rules/1.2.1.json create mode 100644 rules/1.2.2.json create mode 100644 rules/1.3.1.json create mode 100644 rules/1.3.2.json create mode 100644 rules/1.3.3.json create mode 100644 rules/1.3.4.json create mode 100644 rules/1.3.5.json create mode 100644 rules/1.3.6.json create mode 100644 rules/1.3.7.json create mode 100644 rules/1.3.8.json delete mode 100644 rules/CIS_1.1.2.json delete mode 100644 rules/CIS_2.10.json delete mode 100644 rules/CIS_5.2.json delete mode 100644 rules/rule schema (20250731).json diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 Users > Active Users and Entra admin center > Protection > Conditional Access", + "remediation": "Create two cloud-only accounts with Global Admin role, no license, exclude from Conditional Access rules.", + "risk": "High", + "tags": [ + "Accounts", + "EmergencyAccess", + "GlobalAdmin" + ] +} \ No newline at end of file diff --git a/rules/1.1.3.json b/rules/1.1.3.json new file mode 100644 index 00000000..760c70f8 --- /dev/null +++ b/rules/1.1.3.json @@ -0,0 +1,19 @@ +{ + "product": "Microsoft 365 admin center", + "id_level_1": 1.1, + "id_level_2": "1.1.3", + "title": "Ensure that between two and four global admins are designated", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Between two and four global administrators should be designated in the tenant to ensure redundancy and limit exposure.", + "expected_value": "2\ufffd4 Global Administrators", + "comparison": "Count and range check", + "evaluation_path": "Microsoft 365 admin center > Roles > Global Administrator", + "remediation": "Add or remove users from Global Admin role to maintain 2\ufffd4 total.", + "risk": "High", + "tags": [ + "AdminAccounts", + "PrivilegeManagement" + ] +} \ No newline at end of file diff --git a/rules/1.1.4.json b/rules/1.1.4.json new file mode 100644 index 00000000..f4613824 --- /dev/null +++ b/rules/1.1.4.json @@ -0,0 +1,20 @@ +{ + "product": "Microsoft 365 admin center", + "id_level_1": 1.1, + "id_level_2": "1.1.4", + "title": "Ensure administrative accounts use licenses with reduced application footprint", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Administrative accounts should not use licenses with applications to reduce attack surface.", + "expected_value": "License with no user applications (e.g. Entra ID P1/P2)", + "comparison": "License check", + "evaluation_path": "Microsoft 365 admin center > Users > Active users > License column", + "remediation": "Assign minimal license or Entra ID P1/P2 to admin accounts. Use PIM if applicable.", + "risk": "Medium", + "tags": [ + "Licensing", + "AdminAccounts", + "LeastPrivilege" + ] +} \ No newline at end of file diff --git a/rules/1.2.1.json b/rules/1.2.1.json new file mode 100644 index 00000000..9a14c94b --- /dev/null +++ b/rules/1.2.1.json @@ -0,0 +1,20 @@ +{ + "product": "Microsoft 365 admin center", + "id_level_1": 1.2, + "id_level_2": "1.2.1", + "title": "Ensure that only organizationally managed/approved public groups exist", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Ensure that only organizationally managed and approved public groups exist to prevent unauthorized access to internal data.", + "expected_value": "No groups with public visibility", + "comparison": "Group.Visibility != Public", + "evaluation_path": "Microsoft 365 admin center > Teams & groups > Active teams & groups", + "remediation": "Change group privacy from Public to Private in group settings.", + "risk": "High", + "tags": [ + "Groups", + "Privacy", + "AccessControl" + ] +} \ No newline at end of file diff --git a/rules/1.2.2.json b/rules/1.2.2.json new file mode 100644 index 00000000..edfeb44a --- /dev/null +++ b/rules/1.2.2.json @@ -0,0 +1,20 @@ +{ + "product": "Microsoft 365 admin center", + "id_level_1": 1.2, + "id_level_2": "1.2.2", + "title": "Ensure sign-in to shared mailboxes is blocked", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Block sign-in access for shared mailboxes to reduce exposure to unauthorized access.", + "expected_value": "Sign-in disabled for shared mailboxes", + "comparison": "user.AccountEnabled == false", + "evaluation_path": "Microsoft 365 admin center > Users > Active users > Shared mailbox properties", + "remediation": "Uncheck the 'Sign-in allowed' option under mailbox settings.", + "risk": "Medium", + "tags": [ + "Mailbox", + "AccountAccess", + "Security" + ] +} \ No newline at end of file diff --git a/rules/1.3.1.json b/rules/1.3.1.json new file mode 100644 index 00000000..157dd7b8 --- /dev/null +++ b/rules/1.3.1.json @@ -0,0 +1,20 @@ +{ + "product": "Microsoft 365 admin center", + "id_level_1": 1.3, + "id_level_2": "1.3.1", + "title": "Ensure the 'Password expiration policy' is set to 'Set passwords to never expire (recommended)'", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Avoid enforcing periodic password changes unless a compromise is suspected.", + "expected_value": "Set passwords to never expire", + "comparison": "PasswordExpiration == Never", + "evaluation_path": "Microsoft 365 admin center > Org Settings > Security & Privacy > Password expiration policy", + "remediation": "Enable the 'Set passwords to never expire' option in org settings.", + "risk": "Medium", + "tags": [ + "PasswordPolicy", + "UserSettings", + "Authentication" + ] +} \ No newline at end of file diff --git a/rules/1.3.2.json b/rules/1.3.2.json new file mode 100644 index 00000000..47303906 --- /dev/null +++ b/rules/1.3.2.json @@ -0,0 +1,20 @@ +{ + "product": "Microsoft 365 admin center", + "id_level_1": 1.3, + "id_level_2": "1.3.2", + "title": "Ensure 'Idle session timeout' is set to '3 hours (or less)' for unmanaged devices", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Limit idle session timeout for unmanaged devices to reduce session hijack risks.", + "expected_value": "Idle timeout set to = 3 hours", + "comparison": "IdleTimeout <= 3h", + "evaluation_path": "Microsoft 365 admin center > Org settings > Security & privacy > Idle session timeout", + "remediation": "Configure timeout policy in settings for unmanaged device sessions.", + "risk": "High", + "tags": [ + "SessionTimeout", + "DeviceManagement", + "UnmanagedAccess" + ] +} \ No newline at end of file diff --git a/rules/1.3.3.json b/rules/1.3.3.json new file mode 100644 index 00000000..22e57b74 --- /dev/null +++ b/rules/1.3.3.json @@ -0,0 +1,20 @@ +{ + "product": "Microsoft 365 admin center", + "id_level_1": 1.3, + "id_level_2": "1.3.3", + "title": "Ensure 'External sharing' of calendars is not available", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Prevent external calendar sharing to avoid data leakage and preserve internal privacy.", + "expected_value": "External sharing disabled", + "comparison": "CalendarSharing == InternalOnly", + "evaluation_path": "Microsoft 365 admin center > Settings > Org settings > Calendar", + "remediation": "Disable external calendar sharing in org settings.", + "risk": "High", + "tags": [ + "Calendar", + "ExternalSharing", + "Privacy" + ] +} \ No newline at end of file diff --git a/rules/1.3.4.json b/rules/1.3.4.json new file mode 100644 index 00000000..46a887f0 --- /dev/null +++ b/rules/1.3.4.json @@ -0,0 +1,20 @@ +{ + "product": "Microsoft 365 admin center", + "id_level_1": 1.3, + "id_level_2": "1.3.4", + "title": "Ensure 'User owned apps and services' is restricted", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Restrict user ability to register applications to control third-party integrations.", + "expected_value": "App registration disabled for users", + "comparison": "AppRegistration == Disabled", + "evaluation_path": "Microsoft Entra admin center > User settings > App registrations", + "remediation": "Disable 'Users can register applications' in user settings.", + "risk": "Medium", + "tags": [ + "UserApps", + "ThirdPartyAccess", + "AppRegistration" + ] +} \ No newline at end of file diff --git a/rules/1.3.5.json b/rules/1.3.5.json new file mode 100644 index 00000000..2c3cff99 --- /dev/null +++ b/rules/1.3.5.json @@ -0,0 +1,20 @@ +{ + "product": "Microsoft 365 admin center", + "id_level_1": 1.3, + "id_level_2": "1.3.5", + "title": "Ensure internal phishing protection for Forms is enabled", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Enable internal phishing detection for Microsoft Forms to prevent credential harvesting.", + "expected_value": "Phishing protection enabled", + "comparison": "FormsPhishingProtection == On", + "evaluation_path": "Microsoft 365 admin center > Settings > Org settings > Microsoft Forms", + "remediation": "Enable internal phishing protection in Microsoft Forms settings.", + "risk": "Medium", + "tags": [ + "Forms", + "PhishingProtection", + "ThreatDetection" + ] +} \ No newline at end of file diff --git a/rules/1.3.6.json b/rules/1.3.6.json new file mode 100644 index 00000000..1c4af230 --- /dev/null +++ b/rules/1.3.6.json @@ -0,0 +1,20 @@ +{ + "product": "Microsoft 365 admin center", + "id_level_1": 1.3, + "id_level_2": "1.3.6", + "title": "Ensure the customer lockbox feature is enabled", + "profile": "E5", + "level": "L2", + "status": "Automated", + "description": "Require explicit customer approval before Microsoft can access customer content.", + "expected_value": "Customer lockbox enabled", + "comparison": "Lockbox == Enabled", + "evaluation_path": "Microsoft 365 compliance center > Solutions > Customer Lockbox", + "remediation": "Enable Customer Lockbox via Microsoft 365 compliance center.", + "risk": "High", + "tags": [ + "CustomerLockbox", + "AccessControl", + "DataProtection" + ] +} \ No newline at end of file diff --git a/rules/1.3.7.json b/rules/1.3.7.json new file mode 100644 index 00000000..f40c2808 --- /dev/null +++ b/rules/1.3.7.json @@ -0,0 +1,20 @@ +{ + "product": "Microsoft 365 admin center", + "id_level_1": 1.3, + "id_level_2": "1.3.7", + "title": "Ensure 'third-party storage services' are restricted in 'Microsoft 365 on the web'", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Restrict access to third-party storage services like Dropbox or Google Drive to protect data.", + "expected_value": "Third-party storage access disabled", + "comparison": "ThirdPartyStorage == Disabled", + "evaluation_path": "Microsoft 365 admin center > Org settings > Services > Office for the web", + "remediation": "Disable integration with third-party storage services.", + "risk": "High", + "tags": [ + "Storage", + "ExternalServices", + "DataControl" + ] +} \ No newline at end of file diff --git a/rules/1.3.8.json b/rules/1.3.8.json new file mode 100644 index 00000000..2a65fc99 --- /dev/null +++ b/rules/1.3.8.json @@ -0,0 +1,20 @@ +{ + "product": "Microsoft 365 admin center", + "id_level_1": 1.3, + "id_level_2": "1.3.8", + "title": "Ensure that Sways cannot be shared with people outside of your organization", + "profile": "E3 E5", + "level": "L2", + "status": "Manual", + "description": "Prevent sharing of Microsoft Sway content outside the organization to maintain internal content privacy.", + "expected_value": "External sharing disabled for Sways", + "comparison": "SwaySharing == InternalOnly", + "evaluation_path": "Microsoft 365 admin center > Settings > Org settings > Sway", + "remediation": "Manually disable external sharing for Sway presentations.", + "risk": "Medium", + "tags": [ + "Sway", + "ContentSharing", + "ExternalAccess" + ] +} \ No newline at end of file diff --git a/rules/CIS_1.1.2.json b/rules/CIS_1.1.2.json deleted file mode 100644 index 4e45e417..00000000 --- a/rules/CIS_1.1.2.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "id": "CIS_1.1.2", - "description": "Ensure MFA is enabled", - "expected_setting": "enabled", - "severity": "High", - "score_weight": 5, - "remediation": "Enable MFA using Conditional Access or Security Defaults.", - "tag": "MFA" -} \ No newline at end of file diff --git a/rules/CIS_2.10.json b/rules/CIS_2.10.json deleted file mode 100644 index 6b3d9175..00000000 --- a/rules/CIS_2.10.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "id": "CIS_2.10", - "description": "Ensure phishing protection is enabled in Microsoft Forms", - "expected_setting": "enabled", - "severity": "High", - "score_weight": 5, - "remediation": "Enable 'Phishing protection' in Microsoft Forms settings to block suspicious forms.", - "tag": "Forms, PhishingProtection" -} diff --git a/rules/CIS_5.2.json b/rules/CIS_5.2.json deleted file mode 100644 index d86cae2d..00000000 --- a/rules/CIS_5.2.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "id": "CIS_5.2", - "description": "Ensure Microsoft 365 audit log search is enabled", - "expected_setting": "enabled", - "severity": "High", - "score_weight": 5, - "remediation": "Go to Microsoft Purview → Audit and enable 'Start recording user and admin activity'.", - "tag": "AuditLogging, Purview" -} diff --git a/rules/rule schema (20250731).json b/rules/rule schema (20250731).json deleted file mode 100644 index 0473eb55..00000000 --- a/rules/rule schema (20250731).json +++ /dev/null @@ -1,301 +0,0 @@ -[ - { - "product": "Microsoft 365 admin center", - "id_level_1": 1.1, - "id_level_2": "", - "title": "Users", - "profile": "", - "level": "", - "status": "", - "description": "", - "expected_value": "", - "comparison": "", - "evaluation_path": "", - "remediation": "", - "risk": "", - "tags": "" - }, - { - "product": "Microsoft 365 admin center", - "id_level_1": 1.1, - "id_level_2": "1.1.1", - "title": "Ensure Administrative accounts are cloud-only", - "profile": "E3 E5", - "level": "L1", - "status": "Automated", - "description": "Ensure administrative accounts are not On-premises sync enabled", - "expected_value": False, - "comparison": "equals", - "evaluation_path": "user.OnPremisesSyncEnabled", - "remediation": "Migrate hybrid admin accounts to new cloud-only accounts and update roles accordingly.", - "risk": "High", - "tags": "MFA -Identity -HybridEnvironment" - }, - { - "product": "Microsoft 365 admin center", - "id_level_1": 1.1, - "id_level_2": "1.1.2", - "title": "Ensure two emergency access accounts have been defined", - "profile": "E3 E5", - "level": "L1", - "status": "Manual", - "description": "Emergency access or �break glass� accounts are limited for emergency scenarios where normal administrative accounts are unavailable.", - "expected_value": "Two emergency access accounts defined", - "comparison": "Manual validation", - "evaluation_path": "Microsoft 365 admin center > Users > Active Users and Entra admin center > Protection > Conditional Access", - "remediation": "Create two cloud-only accounts with Global Admin role, no license, exclude from Conditional Access rules.", - "risk": "High", - "tags": "Accounts -EmergencyAccess -GlobalAdmin" - }, - { - "product": "Microsoft 365 admin center", - "id_level_1": 1.1, - "id_level_2": "1.1.3", - "title": "Ensure that between two and four global admins are designated", - "profile": "E3 E5", - "level": "L1", - "status": "Automated", - "description": "Between two and four global administrators should be designated in the tenant to ensure redundancy and limit exposure.", - "expected_value": "2�4 Global Administrators", - "comparison": "Count and range check", - "evaluation_path": "Microsoft 365 admin center > Roles > Global Administrator", - "remediation": "Add or remove users from Global Admin role to maintain 2�4 total.", - "risk": "High", - "tags": "AdminAccounts -PrivilegeManagement" - }, - { - "product": "Microsoft 365 admin center", - "id_level_1": 1.1, - "id_level_2": "1.1.4", - "title": "Ensure administrative accounts use licenses with reduced application footprint", - "profile": "E3 E5", - "level": "L1", - "status": "Automated", - "description": "Administrative accounts should not use licenses with applications to reduce attack surface.", - "expected_value": "License with no user applications (e.g. Entra ID P1/P2)", - "comparison": "License check", - "evaluation_path": "Microsoft 365 admin center > Users > Active users > License column", - "remediation": "Assign minimal license or Entra ID P1/P2 to admin accounts. Use PIM if applicable.", - "risk": "Medium", - "tags": "Licensing -AdminAccounts -LeastPrivilege" - }, - { - "product": "Microsoft 365 admin center", - "id_level_1": 1.2, - "id_level_2": "", - "title": "Teams & groups", - "profile": "", - "level": "", - "status": "", - "description": "", - "expected_value": "", - "comparison": "", - "evaluation_path": "", - "remediation": "", - "risk": "", - "tags": "" - }, - { - "product": "Microsoft 365 admin center", - "id_level_1": 1.2, - "id_level_2": "1.2.1", - "title": "Ensure that only organizationally managed/approved public groups exist", - "profile": "E3 E5", - "level": "L2", - "status": "Automated", - "description": "Ensure that only organizationally managed and approved public groups exist to prevent unauthorized access to internal data.", - "expected_value": "No groups with public visibility", - "comparison": "Group.Visibility != Public", - "evaluation_path": "Microsoft 365 admin center > Teams & groups > Active teams & groups", - "remediation": "Change group privacy from Public to Private in group settings.", - "risk": "High", - "tags": "Groups -Privacy -AccessControl" - }, - { - "product": "Microsoft 365 admin center", - "id_level_1": 1.2, - "id_level_2": "1.2.2", - "title": "Ensure sign-in to shared mailboxes is blocked", - "profile": "E3 E5", - "level": "L1", - "status": "Automated", - "description": "Block sign-in access for shared mailboxes to reduce exposure to unauthorized access.", - "expected_value": "Sign-in disabled for shared mailboxes", - "comparison": "user.AccountEnabled == false", - "evaluation_path": "Microsoft 365 admin center > Users > Active users > Shared mailbox properties", - "remediation": "Uncheck the 'Sign-in allowed' option under mailbox settings.", - "risk": "Medium", - "tags": "Mailbox -AccountAccess -Security" - }, - { - "product": "Microsoft 365 admin center", - "id_level_1": 1.3, - "id_level_2": "", - "title": "Settings", - "profile": "", - "level": "", - "status": "", - "description": "", - "expected_value": "", - "comparison": "", - "evaluation_path": "", - "remediation": "", - "risk": "", - "tags": "" - }, - { - "product": "Microsoft 365 admin center", - "id_level_1": 1.3, - "id_level_2": "1.3.1", - "title": "Ensure the 'Password expiration policy' is set to 'Set passwords to never expire (recommended)'", - "profile": "E3 E5", - "level": "L1", - "status": "Automated", - "description": "Avoid enforcing periodic password changes unless a compromise is suspected.", - "expected_value": "Set passwords to never expire", - "comparison": "PasswordExpiration == Never", - "evaluation_path": "Microsoft 365 admin center > Org Settings > Security & Privacy > Password expiration policy", - "remediation": "Enable the 'Set passwords to never expire' option in org settings.", - "risk": "Medium", - "tags": "PasswordPolicy -UserSettings -Authentication" - }, - { - "product": "Microsoft 365 admin center", - "id_level_1": 1.3, - "id_level_2": "1.3.2", - "title": "Ensure 'Idle session timeout' is set to '3 hours (or less)' for unmanaged devices", - "profile": "E3 E5", - "level": "L2", - "status": "Automated", - "description": "Limit idle session timeout for unmanaged devices to reduce session hijack risks.", - "expected_value": "Idle timeout set to = 3 hours", - "comparison": "IdleTimeout <= 3h", - "evaluation_path": "Microsoft 365 admin center > Org settings > Security & privacy > Idle session timeout", - "remediation": "Configure timeout policy in settings for unmanaged device sessions.", - "risk": "High", - "tags": "SessionTimeout -DeviceManagement -UnmanagedAccess" - }, - { - "product": "Microsoft 365 admin center", - "id_level_1": 1.3, - "id_level_2": "1.3.3", - "title": "Ensure 'External sharing' of calendars is not available", - "profile": "E3 E5", - "level": "L2", - "status": "Automated", - "description": "Prevent external calendar sharing to avoid data leakage and preserve internal privacy.", - "expected_value": "External sharing disabled", - "comparison": "CalendarSharing == InternalOnly", - "evaluation_path": "Microsoft 365 admin center > Settings > Org settings > Calendar", - "remediation": "Disable external calendar sharing in org settings.", - "risk": "High", - "tags": "Calendar -ExternalSharing -Privacy" - }, - { - "product": "Microsoft 365 admin center", - "id_level_1": 1.3, - "id_level_2": "1.3.4", - "title": "Ensure 'User owned apps and services' is restricted", - "profile": "E3 E5", - "level": "L1", - "status": "Automated", - "description": "Restrict user ability to register applications to control third-party integrations.", - "expected_value": "App registration disabled for users", - "comparison": "AppRegistration == Disabled", - "evaluation_path": "Microsoft Entra admin center > User settings > App registrations", - "remediation": "Disable 'Users can register applications' in user settings.", - "risk": "Medium", - "tags": "UserApps -ThirdPartyAccess -AppRegistration" - }, - { - "product": "Microsoft 365 admin center", - "id_level_1": 1.3, - "id_level_2": "1.3.5", - "title": "Ensure internal phishing protection for Forms is enabled", - "profile": "E3 E5", - "level": "L1", - "status": "Automated", - "description": "Enable internal phishing detection for Microsoft Forms to prevent credential harvesting.", - "expected_value": "Phishing protection enabled", - "comparison": "FormsPhishingProtection == On", - "evaluation_path": "Microsoft 365 admin center > Settings > Org settings > Microsoft Forms", - "remediation": "Enable internal phishing protection in Microsoft Forms settings.", - "risk": "Medium", - "tags": "Forms -PhishingProtection -ThreatDetection" - }, - { - "product": "Microsoft 365 admin center", - "id_level_1": 1.3, - "id_level_2": "1.3.6", - "title": "Ensure the customer lockbox feature is enabled", - "profile": "E5", - "level": "L2", - "status": "Automated", - "description": "Require explicit customer approval before Microsoft can access customer content.", - "expected_value": "Customer lockbox enabled", - "comparison": "Lockbox == Enabled", - "evaluation_path": "Microsoft 365 compliance center > Solutions > Customer Lockbox", - "remediation": "Enable Customer Lockbox via Microsoft 365 compliance center.", - "risk": "High", - "tags": "CustomerLockbox -AccessControl -DataProtection" - }, - { - "product": "Microsoft 365 admin center", - "id_level_1": 1.3, - "id_level_2": "1.3.7", - "title": "Ensure 'third-party storage services' are restricted in 'Microsoft 365 on the web'", - "profile": "E3 E5", - "level": "L2", - "status": "Automated", - "description": "Restrict access to third-party storage services like Dropbox or Google Drive to protect data.", - "expected_value": "Third-party storage access disabled", - "comparison": "ThirdPartyStorage == Disabled", - "evaluation_path": "Microsoft 365 admin center > Org settings > Services > Office for the web", - "remediation": "Disable integration with third-party storage services.", - "risk": "High", - "tags": "Storage -ExternalServices -DataControl" - }, - { - "product": "Microsoft 365 admin center", - "id_level_1": 1.3, - "id_level_2": "1.3.8", - "title": "Ensure that Sways cannot be shared with people outside of your organization", - "profile": "E3 E5", - "level": "L2", - "status": "Manual", - "description": "Prevent sharing of Microsoft Sway content outside the organization to maintain internal content privacy.", - "expected_value": "External sharing disabled for Sways", - "comparison": "SwaySharing == InternalOnly", - "evaluation_path": "Microsoft 365 admin center > Settings > Org settings > Sway", - "remediation": "Manually disable external sharing for Sway presentations.", - "risk": "Medium", - "tags": "Sway -ContentSharing -ExternalAccess" - }, - \ No newline at end of file From 5aa2c558a035af4fac6109a49c2dfbfb3594d4ba Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Fri, 15 Aug 2025 00:07:52 +1000 Subject: [PATCH 26/63] rules update --- engine/main.py | 41 ++++++++++++++----------------------- rules/5.2.2.3.json | 21 +++++++++++++++++++ test-configs/compliant.json | 9 ++++++++ 3 files changed, 45 insertions(+), 26 deletions(-) create mode 100644 rules/5.2.2.3.json diff --git a/engine/main.py b/engine/main.py index 57faaf4f..a426b51c 100644 --- a/engine/main.py +++ b/engine/main.py @@ -1,55 +1,44 @@ import json import os -# Load a JSON config file (mock tenant settings) -def load_config(path="test-configs/compliant.json"): - """Load the configuration JSON file. Returns an empty dict if file not found or invalid.""" +# Load a mock JSON config file +def load_mock_config(path="test-configs/compliant.json"): try: with open(path) as f: return json.load(f) except FileNotFoundError: - print(f"❌ Config file not found: {path}") + print(f"Config file not found: {path}") return {} except json.JSONDecodeError: - print(f"❌ Invalid JSON in config file: {path}") + print(f"Invalid JSON in config file: {path}") return {} # Load all JSON rules from the rules directory def load_rules(directory="rules"): - """Load all JSON rules from the given directory. Skips invalid files.""" rules = [] - if not os.path.exists(directory): - print(f"❌ Rules directory not found: {directory}") - return rules - for file in os.listdir(directory): if file.endswith(".json"): try: with open(os.path.join(directory, file)) as f: rule = json.load(f) - # Validate required keys - if all(k in rule for k in ("id_level_2", "tags", "expected_value", "evaluation_path", "description")): - rules.append(rule) - else: - print(f"⚠️ Skipping {file}: Missing required keys") + rules.append(rule) except json.JSONDecodeError: - print(f"⚠️ Invalid JSON in {file}") + print(f"Invalid JSON in {file}") return rules -# Helper to get nested value using dot notation (e.g. "azure_ad.mfa_status") +# Getting Nested values def get_value_from_path(config, path): - """Extract a value from nested JSON using a dot-separated path.""" - keys = path.split(".") - for key in keys: - if isinstance(config, dict): - config = config.get(key, {}) + placeholder_value = config + for key in path.split("."): + if isinstance(placeholder_value, dict): + placeholder_value = placeholder_value.get(key, {}) else: return None - return config if config != {} else None + return placeholder_value + # Evaluate one rule against the config def evaluate_rule(rule, config): - """Compare the expected setting with the actual config value.""" expected = rule.get("expected_value") value = get_value_from_path(config, rule.get("evaluation_path")) @@ -59,11 +48,11 @@ def evaluate_rule(rule, config): # Main function to run all rules and show results def main(): - config = load_config() # Load tenant configuration + config = load_mock_config() # Load tenant configuration rules = load_rules() # Load all CIS rules if not config or not rules: - print("❌ No config or rules found. Exiting.") + print("No config or rules found. Exiting.") return passed, failed = 0, 0 diff --git a/rules/5.2.2.3.json b/rules/5.2.2.3.json new file mode 100644 index 00000000..0a425e7d --- /dev/null +++ b/rules/5.2.2.3.json @@ -0,0 +1,21 @@ +{ + "product": "Microsoft Entra admin center", + "id_level_1": 5.2, + "id_level_2": "5.2.2.3", + "title": "Enable Conditional Access policies to block legacy authentication", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Ensure Conditional Access policies are configured to block all legacy authentication protocols to prevent attacks that bypass MFA.", + "expected_value": "Legacy authentication blocked", + "comparison": "equals", + "evaluation_path": "user.conditional_access.policies.block_legacy_auth", + "remediation": "Configure a Conditional Access policy in Microsoft Entra ID that targets all users and resources, blocks Exchange ActiveSync and other legacy clients, and excludes only documented break-glass accounts.", + "risk": "High", + "tags": [ + "ConditionalAccess", + "LegacyAuth", + "Authentication", + "MFA" + ] +} diff --git a/test-configs/compliant.json b/test-configs/compliant.json index b4d27026..292a4a42 100644 --- a/test-configs/compliant.json +++ b/test-configs/compliant.json @@ -5,5 +5,14 @@ }, "microsoft_forms": { "phishing_protection": "enabled" + }, + "user" : { + "OnPremisesSyncEnabled" : "False", + "conditional_access": { + "policies": { + "block_legacy_auth": "Legacy authentication blocked" + } + } } + } \ No newline at end of file From 3e58a68249b868634f755f1d3159820c86a3a940 Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Wed, 20 Aug 2025 16:40:44 +1000 Subject: [PATCH 27/63] All CIS Rule Mappings --- engine/main.py | 6 +++--- rules/2.1.1.json | 22 ++++++++++++++++++++++ rules/2.1.10.json | 22 ++++++++++++++++++++++ rules/2.1.11.json | 22 ++++++++++++++++++++++ rules/2.1.12.json | 22 ++++++++++++++++++++++ rules/2.1.13.json | 22 ++++++++++++++++++++++ rules/2.1.14.json | 22 ++++++++++++++++++++++ rules/2.1.2.json | 22 ++++++++++++++++++++++ rules/2.1.3.json | 22 ++++++++++++++++++++++ rules/2.1.4.json | 22 ++++++++++++++++++++++ rules/2.1.5.json | 23 +++++++++++++++++++++++ rules/2.1.6.json | 22 ++++++++++++++++++++++ rules/2.1.7.json | 22 ++++++++++++++++++++++ rules/2.1.8.json | 22 ++++++++++++++++++++++ rules/2.1.9.json | 22 ++++++++++++++++++++++ rules/2.2.1.json | 22 ++++++++++++++++++++++ rules/2.4.1.json | 22 ++++++++++++++++++++++ rules/2.4.2.json | 22 ++++++++++++++++++++++ rules/2.4.3.json | 22 ++++++++++++++++++++++ rules/2.4.4.json | 22 ++++++++++++++++++++++ rules/3.1.1.json | 22 ++++++++++++++++++++++ rules/3.2.1.json | 22 ++++++++++++++++++++++ rules/3.2.2.json | 22 ++++++++++++++++++++++ rules/3.3.1.json | 22 ++++++++++++++++++++++ rules/5.1.1.json | 19 +++++++++++++++++++ rules/5.1.2.json | 21 +++++++++++++++++++++ rules/5.1.3.json | 22 ++++++++++++++++++++++ rules/5.1.4.json | 19 +++++++++++++++++++ rules/5.1.5.json | 22 ++++++++++++++++++++++ rules/5.1.6.json | 22 ++++++++++++++++++++++ rules/5.1.7.json | 19 +++++++++++++++++++ rules/5.1.8.json | 22 ++++++++++++++++++++++ rules/5.2.1.json | 19 +++++++++++++++++++ rules/5.2.2.json | 22 ++++++++++++++++++++++ rules/5.2.3.json | 21 +++++++++++++++++++++ rules/5.2.4.json | 21 +++++++++++++++++++++ rules/5.3.1.json | 22 ++++++++++++++++++++++ rules/5.3.2.json | 22 ++++++++++++++++++++++ rules/5.3.3.json | 22 ++++++++++++++++++++++ rules/5.3.4.json | 22 ++++++++++++++++++++++ rules/5.3.5.json | 22 ++++++++++++++++++++++ rules/6.1.1.json | 22 ++++++++++++++++++++++ rules/6.1.2.json | 22 ++++++++++++++++++++++ rules/6.1.3.json | 22 ++++++++++++++++++++++ rules/6.2.1.json | 22 ++++++++++++++++++++++ rules/6.2.2.json | 22 ++++++++++++++++++++++ rules/6.2.3.json | 22 ++++++++++++++++++++++ rules/6.3.1.json | 22 ++++++++++++++++++++++ rules/6.5.1.json | 22 ++++++++++++++++++++++ rules/6.5.2.json | 21 +++++++++++++++++++++ rules/6.5.3.json | 22 ++++++++++++++++++++++ rules/6.5.4.json | 22 ++++++++++++++++++++++ rules/7.2.1.json | 22 ++++++++++++++++++++++ rules/7.2.10.json | 22 ++++++++++++++++++++++ rules/7.2.11.json | 22 ++++++++++++++++++++++ rules/7.2.2.json | 22 ++++++++++++++++++++++ rules/7.2.3.json | 22 ++++++++++++++++++++++ rules/7.2.4.json | 22 ++++++++++++++++++++++ rules/7.2.5.json | 22 ++++++++++++++++++++++ rules/7.2.6.json | 22 ++++++++++++++++++++++ rules/7.2.7.json | 22 ++++++++++++++++++++++ rules/7.2.8.json | 22 ++++++++++++++++++++++ rules/7.2.9.json | 22 ++++++++++++++++++++++ rules/7.3.1.json | 22 ++++++++++++++++++++++ rules/7.3.2.json | 22 ++++++++++++++++++++++ rules/7.3.3.json | 22 ++++++++++++++++++++++ rules/7.3.4.json | 22 ++++++++++++++++++++++ rules/8.1.1.json | 22 ++++++++++++++++++++++ rules/8.1.2.json | 22 ++++++++++++++++++++++ rules/8.2.1.json | 22 ++++++++++++++++++++++ rules/8.2.2.json | 22 ++++++++++++++++++++++ rules/8.2.3.json | 22 ++++++++++++++++++++++ rules/8.2.4.json | 22 ++++++++++++++++++++++ rules/8.4.1.json | 22 ++++++++++++++++++++++ rules/8.5.1.json | 22 ++++++++++++++++++++++ rules/8.5.2.json | 22 ++++++++++++++++++++++ rules/8.5.3.json | 22 ++++++++++++++++++++++ rules/8.5.4.json | 22 ++++++++++++++++++++++ rules/8.5.5.json | 22 ++++++++++++++++++++++ rules/8.5.6.json | 22 ++++++++++++++++++++++ rules/8.5.7.json | 22 ++++++++++++++++++++++ rules/8.5.8.json | 22 ++++++++++++++++++++++ rules/8.5.9.json | 22 ++++++++++++++++++++++ rules/8.6.1.json | 22 ++++++++++++++++++++++ rules/9.1.1.json | 22 ++++++++++++++++++++++ rules/9.1.10.json | 22 ++++++++++++++++++++++ rules/9.1.11.json | 22 ++++++++++++++++++++++ rules/9.1.2.json | 22 ++++++++++++++++++++++ rules/9.1.3.json | 22 ++++++++++++++++++++++ rules/9.1.4.json | 22 ++++++++++++++++++++++ rules/9.1.5.json | 22 ++++++++++++++++++++++ rules/9.1.6.json | 22 ++++++++++++++++++++++ rules/9.1.7.json | 22 ++++++++++++++++++++++ rules/9.1.8.json | 22 ++++++++++++++++++++++ rules/9.1.9.json | 22 ++++++++++++++++++++++ 95 files changed, 2056 insertions(+), 3 deletions(-) create mode 100644 rules/2.1.1.json create mode 100644 rules/2.1.10.json create mode 100644 rules/2.1.11.json create mode 100644 rules/2.1.12.json create mode 100644 rules/2.1.13.json create mode 100644 rules/2.1.14.json create mode 100644 rules/2.1.2.json create mode 100644 rules/2.1.3.json create mode 100644 rules/2.1.4.json create mode 100644 rules/2.1.5.json create mode 100644 rules/2.1.6.json create mode 100644 rules/2.1.7.json create mode 100644 rules/2.1.8.json create mode 100644 rules/2.1.9.json create mode 100644 rules/2.2.1.json create mode 100644 rules/2.4.1.json create mode 100644 rules/2.4.2.json create mode 100644 rules/2.4.3.json create mode 100644 rules/2.4.4.json create mode 100644 rules/3.1.1.json create mode 100644 rules/3.2.1.json create mode 100644 rules/3.2.2.json create mode 100644 rules/3.3.1.json create mode 100644 rules/5.1.1.json create mode 100644 rules/5.1.2.json create mode 100644 rules/5.1.3.json create mode 100644 rules/5.1.4.json create mode 100644 rules/5.1.5.json create mode 100644 rules/5.1.6.json create mode 100644 rules/5.1.7.json create mode 100644 rules/5.1.8.json create mode 100644 rules/5.2.1.json create mode 100644 rules/5.2.2.json create mode 100644 rules/5.2.3.json create mode 100644 rules/5.2.4.json create mode 100644 rules/5.3.1.json create mode 100644 rules/5.3.2.json create mode 100644 rules/5.3.3.json create mode 100644 rules/5.3.4.json create mode 100644 rules/5.3.5.json create mode 100644 rules/6.1.1.json create mode 100644 rules/6.1.2.json create mode 100644 rules/6.1.3.json create mode 100644 rules/6.2.1.json create mode 100644 rules/6.2.2.json create mode 100644 rules/6.2.3.json create mode 100644 rules/6.3.1.json create mode 100644 rules/6.5.1.json create mode 100644 rules/6.5.2.json create mode 100644 rules/6.5.3.json create mode 100644 rules/6.5.4.json create mode 100644 rules/7.2.1.json create mode 100644 rules/7.2.10.json create mode 100644 rules/7.2.11.json create mode 100644 rules/7.2.2.json create mode 100644 rules/7.2.3.json create mode 100644 rules/7.2.4.json create mode 100644 rules/7.2.5.json create mode 100644 rules/7.2.6.json create mode 100644 rules/7.2.7.json create mode 100644 rules/7.2.8.json create mode 100644 rules/7.2.9.json create mode 100644 rules/7.3.1.json create mode 100644 rules/7.3.2.json create mode 100644 rules/7.3.3.json create mode 100644 rules/7.3.4.json create mode 100644 rules/8.1.1.json create mode 100644 rules/8.1.2.json create mode 100644 rules/8.2.1.json create mode 100644 rules/8.2.2.json create mode 100644 rules/8.2.3.json create mode 100644 rules/8.2.4.json create mode 100644 rules/8.4.1.json create mode 100644 rules/8.5.1.json create mode 100644 rules/8.5.2.json create mode 100644 rules/8.5.3.json create mode 100644 rules/8.5.4.json create mode 100644 rules/8.5.5.json create mode 100644 rules/8.5.6.json create mode 100644 rules/8.5.7.json create mode 100644 rules/8.5.8.json create mode 100644 rules/8.5.9.json create mode 100644 rules/8.6.1.json create mode 100644 rules/9.1.1.json create mode 100644 rules/9.1.10.json create mode 100644 rules/9.1.11.json create mode 100644 rules/9.1.2.json create mode 100644 rules/9.1.3.json create mode 100644 rules/9.1.4.json create mode 100644 rules/9.1.5.json create mode 100644 rules/9.1.6.json create mode 100644 rules/9.1.7.json create mode 100644 rules/9.1.8.json create mode 100644 rules/9.1.9.json diff --git a/engine/main.py b/engine/main.py index a426b51c..dc32f450 100644 --- a/engine/main.py +++ b/engine/main.py @@ -67,10 +67,10 @@ def main(): failed += not result # Summary output - print("\n📊 Summary:") + print("Summary:") print(f" Total Rules: {len(rules)}") - print(f" ✅ Passed: {passed}") - print(f" ❌ Failed: {failed}") + print(f" Passed: {passed}") + print(f" Failed: {failed}") if __name__ == "__main__": main() \ No newline at end of file diff --git a/rules/2.1.1.json b/rules/2.1.1.json new file mode 100644 index 00000000..ca27f666 --- /dev/null +++ b/rules/2.1.1.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft 365 Defender", + "id_level_1": 2.1, + "id_level_2": "2.1.1", + "title": "Ensure Safe Links for Office Applications is Enabled", + "profile": "E5", + "level": "L2", + "status": "Automated", + "description": "Safe Links scans URLs in Office docs to prevent malicious site access.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "defender.safeLinksOfficeEnabled", + "remediation": "Enable Safe Links for Office via Microsoft 365 Defender portal.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "SafeLinks", + "Office" + ] +} diff --git a/rules/2.1.10.json b/rules/2.1.10.json new file mode 100644 index 00000000..dcc6b33d --- /dev/null +++ b/rules/2.1.10.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft 365 Defender", + "id_level_1": 2.1, + "id_level_2": "2.1.10", + "title": "Ensure DMARC Records for all Exchange Online domains are published", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "DMARC verifies alignment between SPF, DKIM, and sender domain.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "exchange.dmarcRecordsPublished", + "remediation": "Publish DMARC DNS TXT records for all Exchange Online domains.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "DMARC", + "EmailAuth" + ] +} diff --git a/rules/2.1.11.json b/rules/2.1.11.json new file mode 100644 index 00000000..d57c64d2 --- /dev/null +++ b/rules/2.1.11.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft 365 Defender", + "id_level_1": 2.1, + "id_level_2": "2.1.11", + "title": "Ensure comprehensive attachment filtering is applied", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Applies filtering for a wide range of risky file types.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "defender.comprehensiveAttachmentFilterEnabled", + "remediation": "Configure comprehensive attachment filtering in Microsoft Defender.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Attachments", + "Malware" + ] +} diff --git a/rules/2.1.12.json b/rules/2.1.12.json new file mode 100644 index 00000000..6ea9b272 --- /dev/null +++ b/rules/2.1.12.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft 365 Defender", + "id_level_1": 2.1, + "id_level_2": "2.1.12", + "title": "Ensure the connection filter IP allow list is not used", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Prevents bypassing spam filters via IP allow lists.", + "expected_value": "FALSE", + "comparison": "equals", + "evaluation_path": "exchange.connectionFilterIpAllowListUsed", + "remediation": "Remove IP addresses from connection filter allow list.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Spam", + "EmailFiltering" + ] +} diff --git a/rules/2.1.13.json b/rules/2.1.13.json new file mode 100644 index 00000000..929c266a --- /dev/null +++ b/rules/2.1.13.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft 365 Defender", + "id_level_1": 2.1, + "id_level_2": "2.1.13", + "title": "Ensure the connection filter safe list is off", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Prevents safe list from bypassing spam/malware detection.", + "expected_value": "FALSE", + "comparison": "equals", + "evaluation_path": "exchange.connectionFilterSafeListEnabled", + "remediation": "Disable safe list in connection filter settings.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Spam", + "EmailFiltering" + ] +} diff --git a/rules/2.1.14.json b/rules/2.1.14.json new file mode 100644 index 00000000..43e48aad --- /dev/null +++ b/rules/2.1.14.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft 365 Defender", + "id_level_1": 2.1, + "id_level_2": "2.1.14", + "title": "Ensure inbound anti-spam policies do not contain allowed domains", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Prevents whitelisted domains from bypassing spam filters.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "exchange.inboundAntiSpamNoAllowedDomains", + "remediation": "Remove allowed domains from inbound anti-spam policies.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Spam", + "EmailFiltering" + ] +} diff --git a/rules/2.1.2.json b/rules/2.1.2.json new file mode 100644 index 00000000..d0df4e57 --- /dev/null +++ b/rules/2.1.2.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft 365 Defender", + "id_level_1": 2.1, + "id_level_2": "2.1.2", + "title": "Ensure the Common Attachment Types Filter is enabled", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Blocks common dangerous file types from being received.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "defender.commonAttachmentFilterEnabled", + "remediation": "Enable common attachment filter in Microsoft 365 security settings.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Attachments", + "Malware" + ] +} diff --git a/rules/2.1.3.json b/rules/2.1.3.json new file mode 100644 index 00000000..ade49e2c --- /dev/null +++ b/rules/2.1.3.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft 365 Defender", + "id_level_1": 2.1, + "id_level_2": "2.1.3", + "title": "Ensure notifications to internal users sending malware is Enabled", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Notifies senders if they attempt to send malware internally.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "defender.internalUserNotificationMalwareEnabled", + "remediation": "Enable malware notification to internal senders in security policies.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Notifications", + "Malware" + ] +} diff --git a/rules/2.1.4.json b/rules/2.1.4.json new file mode 100644 index 00000000..5e5876e1 --- /dev/null +++ b/rules/2.1.4.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft 365 Defender", + "id_level_1": 2.1, + "id_level_2": "2.1.4", + "title": "Ensure Safe Attachments policy is enabled", + "profile": "E5", + "level": "L1", + "status": "Automated", + "description": "Scans email attachments for malware before delivery.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "defender.safeAttachmentsPolicyEnabled", + "remediation": "Configure and enable Safe Attachments policy in Microsoft Defender.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "SafeAttachments", + "Malware" + ] +} diff --git a/rules/2.1.5.json b/rules/2.1.5.json new file mode 100644 index 00000000..cebf8367 --- /dev/null +++ b/rules/2.1.5.json @@ -0,0 +1,23 @@ +{ + "product": "Microsoft 365 Defender", + "id_level_1": 2.1, + "id_level_2": "2.1.5", + "title": "Ensure Safe Attachments for SharePoint, OneDrive, and Microsoft Teams is Enabled", + "profile": "E5", + "level": "L1", + "status": "Automated", + "description": "Extends Safe Attachments scanning to cloud storage and Teams content.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "defender.safeAttachmentsSPOTEnabled", + "remediation": "Enable Safe Attachments for SharePoint, OneDrive, and Teams in security settings.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "SafeAttachments", + "SharePoint", + "Teams" + ] +} diff --git a/rules/2.1.6.json b/rules/2.1.6.json new file mode 100644 index 00000000..ffd53989 --- /dev/null +++ b/rules/2.1.6.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft 365 Defender", + "id_level_1": 2.1, + "id_level_2": "2.1.6", + "title": "Ensure Exchange Online Spam Policies are set to notify administrators", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Configures spam policies to alert admins when spam is detected.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "defender.exchangeSpamNotifyAdmins", + "remediation": "Configure spam notification settings in Exchange Online Protection.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Spam", + "Exchange" + ] +} diff --git a/rules/2.1.7.json b/rules/2.1.7.json new file mode 100644 index 00000000..850c927b --- /dev/null +++ b/rules/2.1.7.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft 365 Defender", + "id_level_1": 2.1, + "id_level_2": "2.1.7", + "title": "Ensure that an anti-phishing policy has been created", + "profile": "E5", + "level": "L2", + "status": "Manual", + "description": "Anti-phishing policies detect and block impersonation and phishing attempts.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "defender.antiPhishPolicyCreated", + "remediation": "Create anti-phishing policies in Microsoft 365 Security & Compliance center.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "AntiPhishing", + "Identity" + ] +} diff --git a/rules/2.1.8.json b/rules/2.1.8.json new file mode 100644 index 00000000..8629abad --- /dev/null +++ b/rules/2.1.8.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft 365 Defender", + "id_level_1": 2.1, + "id_level_2": "2.1.8", + "title": "Ensure that SPF records are published for all Exchange Domains", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "SPF prevents spoofed mail by specifying authorized sending servers.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "exchange.spfRecordsPublished", + "remediation": "Publish SPF DNS TXT records for all Exchange domains.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "SPF", + "DNS" + ] +} diff --git a/rules/2.1.9.json b/rules/2.1.9.json new file mode 100644 index 00000000..51ef91eb --- /dev/null +++ b/rules/2.1.9.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft 365 Defender", + "id_level_1": 2.1, + "id_level_2": "2.1.9", + "title": "Ensure that DKIM is enabled for all Exchange Online Domains", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "DKIM adds a digital signature to verify sender identity.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "exchange.dkimEnabled", + "remediation": "Enable DKIM signing for all Exchange Online domains.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "DKIM", + "EmailAuth" + ] +} diff --git a/rules/2.2.1.json b/rules/2.2.1.json new file mode 100644 index 00000000..d14bcaea --- /dev/null +++ b/rules/2.2.1.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft 365 Defender", + "id_level_1": 2.2, + "id_level_2": "2.2.1", + "title": "Ensure emergency access account activity is monitored", + "profile": "E5", + "level": "L1", + "status": "Manual", + "description": "Monitors usage of emergency access accounts to detect abuse.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "cloudApps.emergencyAccessMonitored", + "remediation": "Configure monitoring for emergency access accounts in Defender for Cloud Apps.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "EmergencyAccess", + "Monitoring" + ] +} diff --git a/rules/2.4.1.json b/rules/2.4.1.json new file mode 100644 index 00000000..bf32db14 --- /dev/null +++ b/rules/2.4.1.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft 365 Defender", + "id_level_1": 2.4, + "id_level_2": "2.4.1", + "title": "Ensure Priority account protection is enabled and configured", + "profile": "E5", + "level": "L1", + "status": "Automated", + "description": "Provides enhanced protection for high-value accounts.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "system.priorityAccountProtectionEnabled", + "remediation": "Enable Priority Account Protection in Microsoft Defender.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "PriorityAccount", + "Identity" + ] +} diff --git a/rules/2.4.2.json b/rules/2.4.2.json new file mode 100644 index 00000000..840c38ad --- /dev/null +++ b/rules/2.4.2.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft 365 Defender", + "id_level_1": 2.4, + "id_level_2": "2.4.2", + "title": "Ensure Priority accounts have 'Strict protection' presets applied", + "profile": "E5", + "level": "L1", + "status": "Automated", + "description": "Applies stricter security settings to priority accounts.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "system.priorityAccountStrictProtectionApplied", + "remediation": "Apply strict protection presets to all priority accounts.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "PriorityAccount", + "Identity" + ] +} diff --git a/rules/2.4.3.json b/rules/2.4.3.json new file mode 100644 index 00000000..e7dec073 --- /dev/null +++ b/rules/2.4.3.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft 365 Defender", + "id_level_1": 2.4, + "id_level_2": "2.4.3", + "title": "Ensure Microsoft Defender for Cloud Apps is enabled and configured", + "profile": "E5", + "level": "L1", + "status": "Manual", + "description": "Activates Defender for Cloud Apps for monitoring and control.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "system.defenderCloudAppsEnabled", + "remediation": "Enable and configure Defender for Cloud Apps in Microsoft 365 Security portal.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "CloudApps", + "CASB" + ] +} diff --git a/rules/2.4.4.json b/rules/2.4.4.json new file mode 100644 index 00000000..33447968 --- /dev/null +++ b/rules/2.4.4.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft 365 Defender", + "id_level_1": 2.4, + "id_level_2": "2.4.4", + "title": "Ensure Zero-hour auto purge for Microsoft Teams is on", + "profile": "E5", + "level": "L1", + "status": "Automated", + "description": "Automatically removes suspected phishing/malware messages from Teams chats.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "system.zeroHourAutoPurgeTeamsEnabled", + "remediation": "Enable Zero-hour auto purge in Microsoft Teams security settings.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Teams", + "Malware" + ] +} diff --git a/rules/3.1.1.json b/rules/3.1.1.json new file mode 100644 index 00000000..ca3dec99 --- /dev/null +++ b/rules/3.1.1.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Purview", + "id_level_1": 3.1, + "id_level_2": "3.1.1", + "title": "Ensure Microsoft 365 audit log search is Enabled", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Enables centralized logging and search capabilities for compliance and security investigations.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "purview.auditLogSearchEnabled", + "remediation": "Enable Microsoft 365 audit log search in the Purview compliance portal.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Audit", + "Logging" + ] +} diff --git a/rules/3.2.1.json b/rules/3.2.1.json new file mode 100644 index 00000000..110db8a9 --- /dev/null +++ b/rules/3.2.1.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Purview", + "id_level_1": 3.2, + "id_level_2": "3.2.1", + "title": "Ensure DLP policies are enabled", + "profile": "E3 E5", + "level": "L1", + "status": "Manual", + "description": "Data Loss Prevention policies monitor and restrict sharing of sensitive content.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "purview.dlpPoliciesEnabled", + "remediation": "Create and enable DLP policies in Purview to protect sensitive information.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "DLP", + "DataProtection" + ] +} diff --git a/rules/3.2.2.json b/rules/3.2.2.json new file mode 100644 index 00000000..10c12aae --- /dev/null +++ b/rules/3.2.2.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Purview", + "id_level_1": 3.2, + "id_level_2": "3.2.2", + "title": "Ensure DLP policies are enabled for Microsoft Teams", + "profile": "E5", + "level": "L1", + "status": "Automated", + "description": "Extends DLP protections to chats and files shared in Microsoft Teams.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "purview.dlpPoliciesTeamsEnabled", + "remediation": "Enable DLP policies for Teams in Purview compliance portal.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "DLP", + "Teams" + ] +} diff --git a/rules/3.3.1.json b/rules/3.3.1.json new file mode 100644 index 00000000..eef29517 --- /dev/null +++ b/rules/3.3.1.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Purview", + "id_level_1": 3.3, + "id_level_2": "3.3.1", + "title": "Ensure Information Protection sensitivity label policies are published", + "profile": "E3 E5", + "level": "L1", + "status": "Manual", + "description": "Publishes sensitivity label policies to classify and protect documents and emails.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "purview.sensitivityLabelPoliciesPublished", + "remediation": "Publish sensitivity label policies in Purview compliance portal.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "SensitivityLabels", + "DataProtection" + ] +} diff --git a/rules/5.1.1.json b/rules/5.1.1.json new file mode 100644 index 00000000..63aa413d --- /dev/null +++ b/rules/5.1.1.json @@ -0,0 +1,19 @@ +{ + "product": "Microsoft Entra admin center", + "id_level_1": 5.1, + "id_level_2": "5.1.1", + "title": "Overview", + "profile": "nan", + "level": "nan", + "status": "nan", + "description": "nan", + "expected_value": "", + "comparison": "nan", + "evaluation_path": "nan", + "remediation": "nan", + "risk": "nan", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [] +} diff --git a/rules/5.1.2.json b/rules/5.1.2.json new file mode 100644 index 00000000..39edfd93 --- /dev/null +++ b/rules/5.1.2.json @@ -0,0 +1,21 @@ +{ + "product": "Microsoft Entra admin center", + "id_level_1": 5.1, + "id_level_2": "5.1.2", + "title": "Ensure 'LinkedIn account connections' is disabled", + "profile": "E3 E5", + "level": "L2", + "status": "Manual", + "description": "Disables LinkedIn connections integration to reduce data exposure.", + "expected_value": "FALSE", + "comparison": "equals", + "evaluation_path": "entra.linkedInAccountConnectionsEnabled", + "remediation": "Turn off LinkedIn account connections in User settings.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Privacy" + ] +} diff --git a/rules/5.1.3.json b/rules/5.1.3.json new file mode 100644 index 00000000..7bf78b97 --- /dev/null +++ b/rules/5.1.3.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Entra admin center", + "id_level_1": 5.1, + "id_level_2": "5.1.3", + "title": "Ensure a dynamic group for guest users is created", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Maintains a dynamic group containing all guests for easier targeting of policies and reviews.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "entra.dynamicGroupGuestsExists", + "remediation": "Create a dynamic group with rule “(user.userType -eq 'Guest')”.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Guests", + "Groups" + ] +} diff --git a/rules/5.1.4.json b/rules/5.1.4.json new file mode 100644 index 00000000..f673656c --- /dev/null +++ b/rules/5.1.4.json @@ -0,0 +1,19 @@ +{ + "product": "Microsoft Entra admin center", + "id_level_1": 5.1, + "id_level_2": "5.1.4", + "title": "Devices", + "profile": "nan", + "level": "nan", + "status": "nan", + "description": "nan", + "expected_value": "", + "comparison": "nan", + "evaluation_path": "nan", + "remediation": "nan", + "risk": "nan", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [] +} diff --git a/rules/5.1.5.json b/rules/5.1.5.json new file mode 100644 index 00000000..d284cfc7 --- /dev/null +++ b/rules/5.1.5.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Entra admin center", + "id_level_1": 5.1, + "id_level_2": "5.1.5", + "title": "Ensure the admin consent workflow is enabled", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Enables admin consent workflow so users can request app access securely.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "entra.adminConsentWorkflowEnabled", + "remediation": "Turn on admin consent workflow and designate reviewers.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Apps", + "Consent" + ] +} diff --git a/rules/5.1.6.json b/rules/5.1.6.json new file mode 100644 index 00000000..b7f35fe9 --- /dev/null +++ b/rules/5.1.6.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Entra admin center", + "id_level_1": 5.1, + "id_level_2": "5.1.6", + "title": "Ensure guest user invitations are limited to the Guest Inviter role", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Only users in Guest Inviter (or designated roles) can invite guests.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "entra.guestInvitationRoleLimited", + "remediation": "Limit guest invitation permissions to “Guest Inviter” or specific roles/groups.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Guests", + "Governance" + ] +} diff --git a/rules/5.1.7.json b/rules/5.1.7.json new file mode 100644 index 00000000..8c166ee8 --- /dev/null +++ b/rules/5.1.7.json @@ -0,0 +1,19 @@ +{ + "product": "Microsoft Entra admin center", + "id_level_1": 5.1, + "id_level_2": "5.1.7", + "title": "User experiences", + "profile": "nan", + "level": "nan", + "status": "nan", + "description": "nan", + "expected_value": "", + "comparison": "nan", + "evaluation_path": "nan", + "remediation": "nan", + "risk": "nan", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [] +} diff --git a/rules/5.1.8.json b/rules/5.1.8.json new file mode 100644 index 00000000..9ab47742 --- /dev/null +++ b/rules/5.1.8.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Entra admin center", + "id_level_1": 5.1, + "id_level_2": "5.1.8", + "title": "Ensure that password hash sync is enabled for hybrid deployments", + "profile": "E3 E5", + "level": "L1", + "status": "Manual", + "description": "Enables PHS for resilient hybrid authentication and risk evaluation.", + "expected_value": true, + "comparison": "equals", + "evaluation_path": "entra.passwordHashSyncEnabled", + "remediation": "Enable Password Hash Synchronization (or document equivalent secure sign-in approach).", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Hybrid", + "Auth" + ] +} diff --git a/rules/5.2.1.json b/rules/5.2.1.json new file mode 100644 index 00000000..5dd59f23 --- /dev/null +++ b/rules/5.2.1.json @@ -0,0 +1,19 @@ +{ + "product": "Microsoft Entra admin center", + "id_level_1": 5.2, + "id_level_2": "5.2.1", + "title": "Identity Protection", + "profile": "nan", + "level": "nan", + "status": "nan", + "description": "nan", + "expected_value": "", + "comparison": "nan", + "evaluation_path": "nan", + "remediation": "nan", + "risk": "nan", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [] +} diff --git a/rules/5.2.2.json b/rules/5.2.2.json new file mode 100644 index 00000000..65256f81 --- /dev/null +++ b/rules/5.2.2.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Entra admin center", + "id_level_1": 5.2, + "id_level_2": "5.2.2", + "title": "Ensure the device code sign-in flow is blocked", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Blocks device code flow to reduce phishing/device compromise paths.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "entra.ca.blockDeviceCodeFlow", + "remediation": "Conditional Access authentication flows: disable device code flow.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "CA", + "AuthFlow" + ] +} diff --git a/rules/5.2.3.json b/rules/5.2.3.json new file mode 100644 index 00000000..03a83e1e --- /dev/null +++ b/rules/5.2.3.json @@ -0,0 +1,21 @@ +{ + "product": "Microsoft Entra admin center", + "id_level_1": 5.2, + "id_level_2": "5.2.3", + "title": "Ensure system-preferred multifactor authentication is enabled", + "profile": "E3 E5", + "level": "L1", + "status": "Manual", + "description": "Uses system‑preferred MFA to automatically choose strongest available factor.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "entra.authMethods.systemPreferredMfa", + "remediation": "Enable system‑preferred MFA in Authentication Methods policy.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "MFA" + ] +} diff --git a/rules/5.2.4.json b/rules/5.2.4.json new file mode 100644 index 00000000..2b4ff16d --- /dev/null +++ b/rules/5.2.4.json @@ -0,0 +1,21 @@ +{ + "product": "Microsoft Entra admin center", + "id_level_1": 5.2, + "id_level_2": "5.2.4", + "title": "Ensure 'Self service password reset enabled' is set to 'All'", + "profile": "E3 E5", + "level": "L1", + "status": "Manual", + "description": "Enables SSPR for all users.", + "expected_value": "All", + "comparison": "equals", + "evaluation_path": "entra.ssprScope", + "remediation": "Set SSPR “Enabled” scope to All.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "SSPR" + ] +} diff --git a/rules/5.3.1.json b/rules/5.3.1.json new file mode 100644 index 00000000..b5300b58 --- /dev/null +++ b/rules/5.3.1.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Entra admin center", + "id_level_1": 5.3, + "id_level_2": "5.3.1", + "title": "Ensure 'Privileged Identity Management' is used to manage roles", + "profile": "E5", + "level": "L2", + "status": "Automated", + "description": "Uses PIM for time‑bound/elevated access and approvals/auditing.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "entra.pimUsedForRoles", + "remediation": "Enable PIM; convert permanent assignments to eligible; configure approvals/notifications.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "PIM", + "LeastPrivilege" + ] +} diff --git a/rules/5.3.2.json b/rules/5.3.2.json new file mode 100644 index 00000000..ae9afae9 --- /dev/null +++ b/rules/5.3.2.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Entra admin center", + "id_level_1": 5.3, + "id_level_2": "5.3.2", + "title": "Ensure 'Access reviews' for Guest Users are configured", + "profile": "E5", + "level": "L1", + "status": "Automated", + "description": "Periodic reviews of guest user access.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "entra.accessReviews.guestsConfigured", + "remediation": "Create recurring access reviews targeting guest users/dynamic guest group.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "AccessReviews", + "Guests" + ] +} diff --git a/rules/5.3.3.json b/rules/5.3.3.json new file mode 100644 index 00000000..7f4d7567 --- /dev/null +++ b/rules/5.3.3.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Entra admin center", + "id_level_1": 5.3, + "id_level_2": "5.3.3", + "title": "Ensure 'Access reviews' for privileged roles are configured", + "profile": "E5", + "level": "L1", + "status": "Automated", + "description": "Periodic reviews of users with privileged roles.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "entra.accessReviews.privilegedConfigured", + "remediation": "Create recurring access reviews for admin roles/groups.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "AccessReviews", + "Privileged" + ] +} diff --git a/rules/5.3.4.json b/rules/5.3.4.json new file mode 100644 index 00000000..ea9e2585 --- /dev/null +++ b/rules/5.3.4.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Entra admin center", + "id_level_1": 5.3, + "id_level_2": "5.3.4", + "title": "Ensure approval is required for Global Administrator role activation", + "profile": "E5", + "level": "L1", + "status": "Manual", + "description": "Requires approval before GA role elevation (PIM).", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "entra.pim.gaActivationRequiresApproval", + "remediation": "In PIM, require approval for GA activation and assign approvers.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "PIM", + "Approvals" + ] +} diff --git a/rules/5.3.5.json b/rules/5.3.5.json new file mode 100644 index 00000000..2090dcf7 --- /dev/null +++ b/rules/5.3.5.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Entra admin center", + "id_level_1": 5.3, + "id_level_2": "5.3.5", + "title": "Ensure approval is required for Privileged Role Administrator activation", + "profile": "E5", + "level": "L1", + "status": "Manual", + "description": "Requires approval before PRA role elevation (PIM).", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "entra.pim.praActivationRequiresApproval", + "remediation": "In PIM, require approval for PRA activation and assign approvers.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "PIM", + "Approvals" + ] +} diff --git a/rules/6.1.1.json b/rules/6.1.1.json new file mode 100644 index 00000000..151f46fe --- /dev/null +++ b/rules/6.1.1.json @@ -0,0 +1,22 @@ +{ + "product": "Exchange admin center", + "id_level_1": 6.1, + "id_level_2": "6.1.1", + "title": "Ensure 'AuditDisabled' organizationally is set to 'False'", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Ensures mailbox audit logging is not globally disabled.", + "expected_value": "FALSE", + "comparison": "equals", + "evaluation_path": "exchange.auditDisabled", + "remediation": "Set `AuditDisabled` to False in Exchange Online organization config.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Audit", + "Logging" + ] +} diff --git a/rules/6.1.2.json b/rules/6.1.2.json new file mode 100644 index 00000000..96e71f67 --- /dev/null +++ b/rules/6.1.2.json @@ -0,0 +1,22 @@ +{ + "product": "Exchange admin center", + "id_level_1": 6.1, + "id_level_2": "6.1.2", + "title": "Ensure mailbox audit actions are configured", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Configures mailbox actions to log for owner/delegate/admin access.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "exchange.mailboxAuditActionsConfigured", + "remediation": "Configure mailbox audit log actions in Exchange Online.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Audit", + "Logging" + ] +} diff --git a/rules/6.1.3.json b/rules/6.1.3.json new file mode 100644 index 00000000..679bab44 --- /dev/null +++ b/rules/6.1.3.json @@ -0,0 +1,22 @@ +{ + "product": "Exchange admin center", + "id_level_1": 6.1, + "id_level_2": "6.1.3", + "title": "Ensure 'AuditBypassEnabled' is not enabled on mailboxes", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Prevents bypassing mailbox audit logging.", + "expected_value": "FALSE", + "comparison": "equals", + "evaluation_path": "exchange.auditBypassEnabled", + "remediation": "Ensure `AuditBypassEnabled` is False for all mailboxes.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Audit", + "Logging" + ] +} diff --git a/rules/6.2.1.json b/rules/6.2.1.json new file mode 100644 index 00000000..532a4926 --- /dev/null +++ b/rules/6.2.1.json @@ -0,0 +1,22 @@ +{ + "product": "Exchange admin center", + "id_level_1": 6.2, + "id_level_2": "6.2.1", + "title": "Ensure all forms of mail forwarding are blocked and/or disabled", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Prevents automatic forwarding to external recipients.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "exchange.mailForwardingDisabled", + "remediation": "Disable mail forwarding in transport rules and mailbox settings.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "MailFlow", + "DataLeak" + ] +} diff --git a/rules/6.2.2.json b/rules/6.2.2.json new file mode 100644 index 00000000..d74218ee --- /dev/null +++ b/rules/6.2.2.json @@ -0,0 +1,22 @@ +{ + "product": "Exchange admin center", + "id_level_1": 6.2, + "id_level_2": "6.2.2", + "title": "Ensure mail transport rules do not whitelist specific domains", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Prevents bypassing spam/malware filters by whitelisting domains.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "exchange.transportRulesNoWhitelist", + "remediation": "Remove domain whitelist conditions from transport rules.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "MailFlow", + "Filtering" + ] +} diff --git a/rules/6.2.3.json b/rules/6.2.3.json new file mode 100644 index 00000000..227dc73c --- /dev/null +++ b/rules/6.2.3.json @@ -0,0 +1,22 @@ +{ + "product": "Exchange admin center", + "id_level_1": 6.2, + "id_level_2": "6.2.3", + "title": "Ensure email from external senders is identified", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Adds an external sender warning tag to emails.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "exchange.externalSenderIdentification", + "remediation": "Enable external sender identification in Exchange Online.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "MailFlow", + "Awareness" + ] +} diff --git a/rules/6.3.1.json b/rules/6.3.1.json new file mode 100644 index 00000000..a6a469ea --- /dev/null +++ b/rules/6.3.1.json @@ -0,0 +1,22 @@ +{ + "product": "Exchange admin center", + "id_level_1": 6.3, + "id_level_2": "6.3.1", + "title": "Ensure users installing Outlook add-ins is not allowed", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Prevents users from installing add-ins that may introduce vulnerabilities.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "exchange.blockOutlookAddIns", + "remediation": "Restrict add-in installation via Outlook settings or admin controls.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Outlook", + "AddIns" + ] +} diff --git a/rules/6.5.1.json b/rules/6.5.1.json new file mode 100644 index 00000000..59b817b0 --- /dev/null +++ b/rules/6.5.1.json @@ -0,0 +1,22 @@ +{ + "product": "Exchange admin center", + "id_level_1": 6.5, + "id_level_2": "6.5.1", + "title": "Ensure modern authentication for Exchange Online is enabled", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Enables modern authentication to replace legacy/basic auth protocols.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "exchange.modernAuthEnabled", + "remediation": "Enable modern authentication in Exchange Online organization settings.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Auth", + "ModernAuth" + ] +} diff --git a/rules/6.5.2.json b/rules/6.5.2.json new file mode 100644 index 00000000..17dc58b6 --- /dev/null +++ b/rules/6.5.2.json @@ -0,0 +1,21 @@ +{ + "product": "Exchange admin center", + "id_level_1": 6.5, + "id_level_2": "6.5.2", + "title": "Ensure MailTips are enabled for end users", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Provides MailTips warnings to help avoid misdirected messages.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "exchange.mailTipsEnabled", + "remediation": "Enable MailTips in Exchange Online organization config.", + "risk": "Low", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Awareness" + ] +} diff --git a/rules/6.5.3.json b/rules/6.5.3.json new file mode 100644 index 00000000..9331ffcc --- /dev/null +++ b/rules/6.5.3.json @@ -0,0 +1,22 @@ +{ + "product": "Exchange admin center", + "id_level_1": 6.5, + "id_level_2": "6.5.3", + "title": "Ensure additional storage providers are restricted in Outlook on the web", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Prevents use of external storage providers that may bypass security controls.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "exchange.restrictExternalStorageProviders", + "remediation": "Restrict additional storage providers via OWA mailbox policies.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Outlook", + "DataLeak" + ] +} diff --git a/rules/6.5.4.json b/rules/6.5.4.json new file mode 100644 index 00000000..467272b0 --- /dev/null +++ b/rules/6.5.4.json @@ -0,0 +1,22 @@ +{ + "product": "Exchange admin center", + "id_level_1": 6.5, + "id_level_2": "6.5.4", + "title": "Ensure SMTP AUTH is disabled", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Disables SMTP AUTH protocol unless specifically required.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "exchange.smtpAuthDisabled", + "remediation": "Disable SMTP AUTH in tenant settings; enable only for approved accounts.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Auth", + "LegacyAuth" + ] +} diff --git a/rules/7.2.1.json b/rules/7.2.1.json new file mode 100644 index 00000000..8bf6c0a2 --- /dev/null +++ b/rules/7.2.1.json @@ -0,0 +1,22 @@ +{ + "product": "SharePoint admin center", + "id_level_1": 7.2, + "id_level_2": "7.2.1", + "title": "Ensure modern authentication for SharePoint applications is required", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Requires modern authentication to block basic auth access to SharePoint.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "sharepoint.modernAuthRequired", + "remediation": "Enable modern auth for SharePoint in tenant settings.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Auth", + "ModernAuth" + ] +} diff --git a/rules/7.2.10.json b/rules/7.2.10.json new file mode 100644 index 00000000..1b813f11 --- /dev/null +++ b/rules/7.2.10.json @@ -0,0 +1,22 @@ +{ + "product": "SharePoint admin center", + "id_level_1": 7.2, + "id_level_2": "7.2.10", + "title": "Ensure reauthentication with verification code is restricted", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Requires reauth with verification code only when appropriate.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "sharepoint.reauthVerificationCodeRestricted", + "remediation": "Configure reauth restrictions for verification codes in SharePoint admin center.", + "risk": "Low", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Auth", + "Reauth" + ] +} diff --git a/rules/7.2.11.json b/rules/7.2.11.json new file mode 100644 index 00000000..77e05132 --- /dev/null +++ b/rules/7.2.11.json @@ -0,0 +1,22 @@ +{ + "product": "SharePoint admin center", + "id_level_1": 7.2, + "id_level_2": "7.2.11", + "title": "Ensure the SharePoint default sharing link permission is set", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Sets default sharing link permission to least privilege.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "sharepoint.defaultSharingLinkPermissionSet", + "remediation": "Configure default sharing link permission in SharePoint admin center.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Sharing", + "External" + ] +} diff --git a/rules/7.2.2.json b/rules/7.2.2.json new file mode 100644 index 00000000..4af516ea --- /dev/null +++ b/rules/7.2.2.json @@ -0,0 +1,22 @@ +{ + "product": "SharePoint admin center", + "id_level_1": 7.2, + "id_level_2": "7.2.2", + "title": "Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Enables secure B2B collaboration for SharePoint and OneDrive via Entra ID.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "sharepoint.azureAdB2BIntegrationEnabled", + "remediation": "Enable Azure AD B2B integration in SharePoint admin settings.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "B2B", + "Collaboration" + ] +} diff --git a/rules/7.2.3.json b/rules/7.2.3.json new file mode 100644 index 00000000..3a77327d --- /dev/null +++ b/rules/7.2.3.json @@ -0,0 +1,22 @@ +{ + "product": "SharePoint admin center", + "id_level_1": 7.2, + "id_level_2": "7.2.3", + "title": "Ensure external content sharing is restricted", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Restricts external sharing to approved levels (e.g., specific people).", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "sharepoint.externalSharingRestricted", + "remediation": "Configure external sharing settings for SharePoint to most restrictive necessary.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Sharing", + "External" + ] +} diff --git a/rules/7.2.4.json b/rules/7.2.4.json new file mode 100644 index 00000000..6c75aa13 --- /dev/null +++ b/rules/7.2.4.json @@ -0,0 +1,22 @@ +{ + "product": "SharePoint admin center", + "id_level_1": 7.2, + "id_level_2": "7.2.4", + "title": "Ensure OneDrive content sharing is restricted", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Restricts OneDrive content sharing to approved levels.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "onedrive.contentSharingRestricted", + "remediation": "Configure OneDrive external sharing settings in admin center.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Sharing", + "External" + ] +} diff --git a/rules/7.2.5.json b/rules/7.2.5.json new file mode 100644 index 00000000..2522442a --- /dev/null +++ b/rules/7.2.5.json @@ -0,0 +1,22 @@ +{ + "product": "SharePoint admin center", + "id_level_1": 7.2, + "id_level_2": "7.2.5", + "title": "Ensure SharePoint guest users cannot share items they don't own", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Prevents guest users from sharing files/folders they are not the owner of.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "sharepoint.guestsCannotShareNotOwned", + "remediation": "Disable sharing for guest users without ownership in SharePoint settings.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Sharing", + "Guests" + ] +} diff --git a/rules/7.2.6.json b/rules/7.2.6.json new file mode 100644 index 00000000..63b0a47b --- /dev/null +++ b/rules/7.2.6.json @@ -0,0 +1,22 @@ +{ + "product": "SharePoint admin center", + "id_level_1": 7.2, + "id_level_2": "7.2.6", + "title": "Ensure SharePoint external sharing is managed through domain whitelist/blacklist", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Controls external sharing using domain-based allow/block lists.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "sharepoint.externalDomainAllowBlockList", + "remediation": "Configure SharePoint domain restrictions for sharing.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Sharing", + "External" + ] +} diff --git a/rules/7.2.7.json b/rules/7.2.7.json new file mode 100644 index 00000000..286df79c --- /dev/null +++ b/rules/7.2.7.json @@ -0,0 +1,22 @@ +{ + "product": "SharePoint admin center", + "id_level_1": 7.2, + "id_level_2": "7.2.7", + "title": "Ensure link sharing is restricted in SharePoint and OneDrive", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Limits link sharing to secure link types (e.g., specific people).", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "sharepoint.linkSharingRestricted", + "remediation": "Configure link sharing settings in SharePoint and OneDrive admin centers.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Sharing", + "External" + ] +} diff --git a/rules/7.2.8.json b/rules/7.2.8.json new file mode 100644 index 00000000..3b290f0b --- /dev/null +++ b/rules/7.2.8.json @@ -0,0 +1,22 @@ +{ + "product": "SharePoint admin center", + "id_level_1": 7.2, + "id_level_2": "7.2.8", + "title": "Ensure external sharing is restricted by security group", + "profile": "E3 E5", + "level": "L2", + "status": "Manual", + "description": "Restricts sharing privileges to members of a designated security group.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "sharepoint.externalSharingBySecurityGroup", + "remediation": "Configure security group for sharing privileges in SharePoint admin center.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Sharing", + "Governance" + ] +} diff --git a/rules/7.2.9.json b/rules/7.2.9.json new file mode 100644 index 00000000..0aae0125 --- /dev/null +++ b/rules/7.2.9.json @@ -0,0 +1,22 @@ +{ + "product": "SharePoint admin center", + "id_level_1": 7.2, + "id_level_2": "7.2.9", + "title": "Ensure guest access to a site or OneDrive will expire automatically", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Sets expiration period for guest access to resources.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "sharepoint.guestAccessExpiryConfigured", + "remediation": "Configure expiration policy for guest access in SharePoint/OneDrive.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Guests", + "Governance" + ] +} diff --git a/rules/7.3.1.json b/rules/7.3.1.json new file mode 100644 index 00000000..3739476f --- /dev/null +++ b/rules/7.3.1.json @@ -0,0 +1,22 @@ +{ + "product": "SharePoint admin center", + "id_level_1": 7.3, + "id_level_2": "7.3.1", + "title": "Ensure Office 365 SharePoint infected files are disallowed for download", + "profile": "E5", + "level": "L2", + "status": "Automated", + "description": "Blocks download of detected infected files in SharePoint.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "sharepoint.blockInfectedFileDownload", + "remediation": "Configure malware detection and blocking in SharePoint admin settings.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Malware", + "Download" + ] +} diff --git a/rules/7.3.2.json b/rules/7.3.2.json new file mode 100644 index 00000000..954005de --- /dev/null +++ b/rules/7.3.2.json @@ -0,0 +1,22 @@ +{ + "product": "SharePoint admin center", + "id_level_1": 7.3, + "id_level_2": "7.3.2", + "title": "Ensure OneDrive sync is restricted for unmanaged devices", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Prevents syncing files to unmanaged/unknown devices.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "onedrive.restrictSyncUnmanagedDevices", + "remediation": "Configure OneDrive admin center to block sync on unmanaged devices.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Sync", + "Devices" + ] +} diff --git a/rules/7.3.3.json b/rules/7.3.3.json new file mode 100644 index 00000000..bbaff429 --- /dev/null +++ b/rules/7.3.3.json @@ -0,0 +1,22 @@ +{ + "product": "SharePoint admin center", + "id_level_1": 7.3, + "id_level_2": "7.3.3", + "title": "Ensure custom script execution is restricted on personal sites", + "profile": "E3 E5", + "level": "L1", + "status": "Manual", + "description": "Prevents running custom scripts on personal OneDrive/SharePoint sites.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "sharepoint.restrictCustomScriptsPersonalSites", + "remediation": "Configure custom script setting in SharePoint admin center.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Scripts", + "Governance" + ] +} diff --git a/rules/7.3.4.json b/rules/7.3.4.json new file mode 100644 index 00000000..25b606e5 --- /dev/null +++ b/rules/7.3.4.json @@ -0,0 +1,22 @@ +{ + "product": "SharePoint admin center", + "id_level_1": 7.3, + "id_level_2": "7.3.4", + "title": "Ensure custom script execution is restricted on site collections", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Prevents running custom scripts on all site collections.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "sharepoint.restrictCustomScriptsSiteCollections", + "remediation": "Configure custom script setting in SharePoint admin center.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Scripts", + "Governance" + ] +} diff --git a/rules/8.1.1.json b/rules/8.1.1.json new file mode 100644 index 00000000..25b3b564 --- /dev/null +++ b/rules/8.1.1.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Teams admin center", + "id_level_1": 8.1, + "id_level_2": "8.1.1", + "title": "Ensure external file sharing in Teams is enabled for only approved cloud storage services", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Restricts external file sharing to approved cloud storage providers.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "teams.externalFileSharingApprovedProviders", + "remediation": "Configure Teams external file sharing settings to limit to approved providers.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Sharing", + "External" + ] +} diff --git a/rules/8.1.2.json b/rules/8.1.2.json new file mode 100644 index 00000000..39d44fbb --- /dev/null +++ b/rules/8.1.2.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Teams admin center", + "id_level_1": 8.1, + "id_level_2": "8.1.2", + "title": "Ensure users can't send emails to a channel email address", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Prevents sending email to Teams channels to reduce spam/phishing risk.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "teams.blockChannelEmail", + "remediation": "Disable channel email addresses in Teams settings.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Email", + "Teams" + ] +} diff --git a/rules/8.2.1.json b/rules/8.2.1.json new file mode 100644 index 00000000..894e8d37 --- /dev/null +++ b/rules/8.2.1.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Teams admin center", + "id_level_1": 8.2, + "id_level_2": "8.2.1", + "title": "Ensure external domains are restricted in the Teams admin center", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Limits Teams communication to approved external domains.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "teams.externalDomainsRestricted", + "remediation": "Configure allowed/blocked domain list for external access.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "External", + "Teams" + ] +} diff --git a/rules/8.2.2.json b/rules/8.2.2.json new file mode 100644 index 00000000..a11fdbf2 --- /dev/null +++ b/rules/8.2.2.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Teams admin center", + "id_level_1": 8.2, + "id_level_2": "8.2.2", + "title": "Ensure communication with unmanaged Teams users is disabled", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Blocks Teams chats/meetings with unmanaged users.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "teams.blockUnmanagedUsers", + "remediation": "Disable communication with unmanaged users in Teams external access settings.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "External", + "Teams" + ] +} diff --git a/rules/8.2.3.json b/rules/8.2.3.json new file mode 100644 index 00000000..4ddd3620 --- /dev/null +++ b/rules/8.2.3.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Teams admin center", + "id_level_1": 8.2, + "id_level_2": "8.2.3", + "title": "Ensure external Teams users cannot initiate conversations", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Prevents external users from initiating new chats.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "teams.blockExternalUsersInitiateChats", + "remediation": "Configure Teams external access to block chat initiation from external users.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "External", + "Chat" + ] +} diff --git a/rules/8.2.4.json b/rules/8.2.4.json new file mode 100644 index 00000000..3c896150 --- /dev/null +++ b/rules/8.2.4.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Teams admin center", + "id_level_1": 8.2, + "id_level_2": "8.2.4", + "title": "Ensure communication with Skype users is disabled", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Blocks Teams communication with Skype consumer accounts.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "teams.blockSkypeUsers", + "remediation": "Disable Skype federation in Teams settings.", + "risk": "Low", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "External", + "Skype" + ] +} diff --git a/rules/8.4.1.json b/rules/8.4.1.json new file mode 100644 index 00000000..e8efa025 --- /dev/null +++ b/rules/8.4.1.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Teams admin center", + "id_level_1": 8.4, + "id_level_2": "8.4.1", + "title": "Ensure app permission policies are configured", + "profile": "E3 E5", + "level": "L1", + "status": "Manual", + "description": "Defines which apps are allowed/blocked for Teams users.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "teams.appPermissionPoliciesConfigured", + "remediation": "Configure Teams app permission policies in Teams admin center.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Apps", + "Governance" + ] +} diff --git a/rules/8.5.1.json b/rules/8.5.1.json new file mode 100644 index 00000000..24b96f73 --- /dev/null +++ b/rules/8.5.1.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Teams admin center", + "id_level_1": 8.5, + "id_level_2": "8.5.1", + "title": "Ensure anonymous users can't join a meeting", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Blocks anonymous users from joining meetings.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "teams.meetings.blockAnonymousJoin", + "remediation": "Set meeting policy to block anonymous users.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Meetings", + "External" + ] +} diff --git a/rules/8.5.2.json b/rules/8.5.2.json new file mode 100644 index 00000000..205d9673 --- /dev/null +++ b/rules/8.5.2.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Teams admin center", + "id_level_1": 8.5, + "id_level_2": "8.5.2", + "title": "Ensure anonymous users and dial-in callers can't start a meeting", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Prevents unauthenticated users from starting meetings.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "teams.meetings.blockAnonymousStart", + "remediation": "Disable anonymous and PSTN callers from starting meetings.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Meetings", + "External" + ] +} diff --git a/rules/8.5.3.json b/rules/8.5.3.json new file mode 100644 index 00000000..7f879fd8 --- /dev/null +++ b/rules/8.5.3.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Teams admin center", + "id_level_1": 8.5, + "id_level_2": "8.5.3", + "title": "Ensure only people in my org can bypass the lobby", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Restricts lobby bypass to internal users only.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "teams.meetings.lobbyBypassInternalOnly", + "remediation": "Configure lobby bypass to internal users in meeting policies.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Meetings", + "Lobby" + ] +} diff --git a/rules/8.5.4.json b/rules/8.5.4.json new file mode 100644 index 00000000..8a81380a --- /dev/null +++ b/rules/8.5.4.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Teams admin center", + "id_level_1": 8.5, + "id_level_2": "8.5.4", + "title": "Ensure users dialing in can't bypass the lobby", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "PSTN dial-in participants must wait in lobby until admitted.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "teams.meetings.pstnBypassLobbyDisabled", + "remediation": "Disable PSTN lobby bypass in meeting settings.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Meetings", + "PSTN" + ] +} diff --git a/rules/8.5.5.json b/rules/8.5.5.json new file mode 100644 index 00000000..5d626838 --- /dev/null +++ b/rules/8.5.5.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Teams admin center", + "id_level_1": 8.5, + "id_level_2": "8.5.5", + "title": "Ensure meeting that does not allow anonymous users", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Blocks meeting creation that allows anonymous join.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "teams.meetings.noAnonymousAllowed", + "remediation": "Restrict meeting creation to authenticated participants only.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Meetings", + "Policy" + ] +} diff --git a/rules/8.5.6.json b/rules/8.5.6.json new file mode 100644 index 00000000..5103a86a --- /dev/null +++ b/rules/8.5.6.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Teams admin center", + "id_level_1": 8.5, + "id_level_2": "8.5.6", + "title": "Ensure only organizers and co-organizers can present", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Restricts presenter role to meeting organizers/co-organizers.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "teams.meetings.onlyOrganizersCanPresent", + "remediation": "Set meeting policy to restrict presenters to organizers.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Meetings", + "Roles" + ] +} diff --git a/rules/8.5.7.json b/rules/8.5.7.json new file mode 100644 index 00000000..0074090f --- /dev/null +++ b/rules/8.5.7.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Teams admin center", + "id_level_1": 8.5, + "id_level_2": "8.5.7", + "title": "Ensure external participants can't give or request control", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Prevents external meeting participants from taking/requesting screen control.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "teams.meetings.blockExternalControl", + "remediation": "Disable “Allow external control” in Teams meeting policy.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Meetings", + "Sharing" + ] +} diff --git a/rules/8.5.8.json b/rules/8.5.8.json new file mode 100644 index 00000000..2e082922 --- /dev/null +++ b/rules/8.5.8.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Teams admin center", + "id_level_1": 8.5, + "id_level_2": "8.5.8", + "title": "Ensure external meeting chat is off", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Disables chat for meetings with external participants.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "teams.meetings.externalChatOff", + "remediation": "Turn off chat in meeting policy for external participants.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Meetings", + "Chat" + ] +} diff --git a/rules/8.5.9.json b/rules/8.5.9.json new file mode 100644 index 00000000..2d19a7e2 --- /dev/null +++ b/rules/8.5.9.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Teams admin center", + "id_level_1": 8.5, + "id_level_2": "8.5.9", + "title": "Ensure meeting recording is off by default", + "profile": "E3 E5", + "level": "L2", + "status": "Automated", + "description": "Disables automatic meeting recording.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "teams.meetings.recordingOffByDefault", + "remediation": "Set meeting policy default recording option to Off.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Meetings", + "Recording" + ] +} diff --git a/rules/8.6.1.json b/rules/8.6.1.json new file mode 100644 index 00000000..8e1b027e --- /dev/null +++ b/rules/8.6.1.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Teams admin center", + "id_level_1": 8.6, + "id_level_2": "8.6.1", + "title": "Ensure users can report security concerns in Teams", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Allows reporting of suspicious messages within Teams.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "teams.messaging.securityReportEnabled", + "remediation": "Enable “Report a security concern” in Teams messaging policy.", + "risk": "Low", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Security", + "Awareness" + ] +} diff --git a/rules/9.1.1.json b/rules/9.1.1.json new file mode 100644 index 00000000..5a223776 --- /dev/null +++ b/rules/9.1.1.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Fabric", + "id_level_1": 9.1, + "id_level_2": "9.1.1", + "title": "Ensure guest user access is restricted", + "profile": "E3 E5", + "level": "L1", + "status": "Manual", + "description": "Restricts Fabric guest user access permissions.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "fabric.restrictGuestAccess", + "remediation": "Configure guest access restrictions in Fabric admin center.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Guests", + "Governance" + ] +} diff --git a/rules/9.1.10.json b/rules/9.1.10.json new file mode 100644 index 00000000..0e7e29e9 --- /dev/null +++ b/rules/9.1.10.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Fabric", + "id_level_1": 9.1, + "id_level_2": "9.1.10", + "title": "Ensure only approved APIs by Service Principals are permitted", + "profile": "E3 E5", + "level": "L1", + "status": "Manual", + "description": "Restricts API access to approved Service Principals.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "fabric.approvedServicePrincipalsOnly", + "remediation": "Limit API permissions to approved Service Principals in Fabric admin center.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "API", + "Governance" + ] +} diff --git a/rules/9.1.11.json b/rules/9.1.11.json new file mode 100644 index 00000000..f4137447 --- /dev/null +++ b/rules/9.1.11.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Fabric", + "id_level_1": 9.1, + "id_level_2": "9.1.11", + "title": "Ensure app permission grants are reviewed", + "profile": "E3 E5", + "level": "L1", + "status": "Manual", + "description": "Periodically reviews and revokes unnecessary app permissions.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "fabric.reviewAppPermissionGrants", + "remediation": "Schedule periodic review of app permissions in Fabric admin center.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Apps", + "Governance" + ] +} diff --git a/rules/9.1.2.json b/rules/9.1.2.json new file mode 100644 index 00000000..b5120ff1 --- /dev/null +++ b/rules/9.1.2.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Fabric", + "id_level_1": 9.1, + "id_level_2": "9.1.2", + "title": "Ensure external user invitations are restricted", + "profile": "E3 E5", + "level": "L1", + "status": "Manual", + "description": "Limits which users can send Fabric invitations to external accounts.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "fabric.restrictExternalInvitations", + "remediation": "Restrict external invitation privileges to specific users/groups.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Guests", + "Governance" + ] +} diff --git a/rules/9.1.3.json b/rules/9.1.3.json new file mode 100644 index 00000000..2078a7a4 --- /dev/null +++ b/rules/9.1.3.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Fabric", + "id_level_1": 9.1, + "id_level_2": "9.1.3", + "title": "Ensure guest access to content is restricted", + "profile": "E3 E5", + "level": "L1", + "status": "Manual", + "description": "Controls guest access level to Fabric content.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "fabric.restrictGuestContentAccess", + "remediation": "Configure Fabric guest access level settings to least privilege.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Guests", + "Governance" + ] +} diff --git a/rules/9.1.4.json b/rules/9.1.4.json new file mode 100644 index 00000000..994fe05d --- /dev/null +++ b/rules/9.1.4.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Fabric", + "id_level_1": 9.1, + "id_level_2": "9.1.4", + "title": "Ensure 'Publish to web' is restricted", + "profile": "E3 E5", + "level": "L1", + "status": "Automated", + "description": "Prevents unrestricted public sharing of Fabric content.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "fabric.publishToWebRestricted", + "remediation": "Disable “Publish to web” or restrict to approved users.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Sharing", + "External" + ] +} diff --git a/rules/9.1.5.json b/rules/9.1.5.json new file mode 100644 index 00000000..2b1e9010 --- /dev/null +++ b/rules/9.1.5.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Fabric", + "id_level_1": 9.1, + "id_level_2": "9.1.5", + "title": "Ensure 'Interact with and share R and Python' visuals is disabled", + "profile": "E3 E5", + "level": "L1", + "status": "Manual", + "description": "Prevents execution of R/Python scripts embedded in Fabric visuals.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "fabric.disableRpythonVisuals", + "remediation": "Disable R/Python visuals in Fabric admin settings.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Security", + "Scripts" + ] +} diff --git a/rules/9.1.6.json b/rules/9.1.6.json new file mode 100644 index 00000000..3916a5d3 --- /dev/null +++ b/rules/9.1.6.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Fabric", + "id_level_1": 9.1, + "id_level_2": "9.1.6", + "title": "Ensure 'Allow users to apply sensitivity labels for content' is enabled", + "profile": "E3 E5", + "level": "L1", + "status": "Manual", + "description": "Allows classification and labeling of content in Fabric.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "fabric.enableSensitivityLabels", + "remediation": "Enable Microsoft Purview sensitivity labeling integration in Fabric.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Labels", + "Compliance" + ] +} diff --git a/rules/9.1.7.json b/rules/9.1.7.json new file mode 100644 index 00000000..e0d60a70 --- /dev/null +++ b/rules/9.1.7.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Fabric", + "id_level_1": 9.1, + "id_level_2": "9.1.7", + "title": "Ensure shareable links are restricted", + "profile": "E3 E5", + "level": "L1", + "status": "Manual", + "description": "Restricts Fabric shareable links to approved scopes.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "fabric.restrictShareableLinks", + "remediation": "Configure shareable link policy to limit scope and duration.", + "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Sharing", + "External" + ] +} diff --git a/rules/9.1.8.json b/rules/9.1.8.json new file mode 100644 index 00000000..9ff6d252 --- /dev/null +++ b/rules/9.1.8.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Fabric", + "id_level_1": 9.1, + "id_level_2": "9.1.8", + "title": "Ensure enabling of external data sharing is restricted", + "profile": "E3 E5", + "level": "L1", + "status": "Manual", + "description": "Controls whether Fabric content can be shared externally.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "fabric.restrictExternalDataSharing", + "remediation": "Set external data sharing option to disabled or restricted in Fabric admin settings.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Sharing", + "External" + ] +} diff --git a/rules/9.1.9.json b/rules/9.1.9.json new file mode 100644 index 00000000..e4c0cd69 --- /dev/null +++ b/rules/9.1.9.json @@ -0,0 +1,22 @@ +{ + "product": "Microsoft Fabric", + "id_level_1": 9.1, + "id_level_2": "9.1.9", + "title": "Ensure 'Block Reshare/Copy Authentication' is enabled", + "profile": "E3 E5", + "level": "L1", + "status": "Manual", + "description": "Prevents recipients from resharing or copying authentication data.", + "expected_value": "TRUE", + "comparison": "equals", + "evaluation_path": "fabric.blockReshareCopyAuth", + "remediation": "Enable “Block Reshare/Copy Authentication” in Fabric settings.", + "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", + "tags": [ + "Sharing", + "Governance" + ] +} From 92c8beb3a6b4d66bb7c1100ac987d84159646ef5 Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Wed, 20 Aug 2025 17:08:40 +1000 Subject: [PATCH 28/63] Engine updated with risk assessment output and better print --- engine/main.py | 35 ++++++++++++++++------------------- rules/1.1.1.json | 3 +++ rules/1.1.2.json | 3 +++ rules/1.1.3.json | 3 +++ rules/1.1.4.json | 3 +++ rules/1.2.1.json | 3 +++ rules/1.2.2.json | 3 +++ rules/1.3.1.json | 3 +++ rules/1.3.2.json | 3 +++ rules/1.3.3.json | 3 +++ rules/1.3.4.json | 3 +++ rules/1.3.5.json | 3 +++ rules/1.3.6.json | 3 +++ rules/1.3.7.json | 3 +++ rules/1.3.8.json | 3 +++ 15 files changed, 58 insertions(+), 19 deletions(-) diff --git a/engine/main.py b/engine/main.py index dc32f450..f1d69cf9 100644 --- a/engine/main.py +++ b/engine/main.py @@ -1,7 +1,6 @@ import json import os -# Load a mock JSON config file def load_mock_config(path="test-configs/compliant.json"): try: with open(path) as f: @@ -13,7 +12,6 @@ def load_mock_config(path="test-configs/compliant.json"): print(f"Invalid JSON in config file: {path}") return {} -# Load all JSON rules from the rules directory def load_rules(directory="rules"): rules = [] for file in os.listdir(directory): @@ -26,7 +24,6 @@ def load_rules(directory="rules"): print(f"Invalid JSON in {file}") return rules -# Getting Nested values def get_value_from_path(config, path): placeholder_value = config for key in path.split("."): @@ -37,7 +34,6 @@ def get_value_from_path(config, path): return placeholder_value -# Evaluate one rule against the config def evaluate_rule(rule, config): expected = rule.get("expected_value") value = get_value_from_path(config, rule.get("evaluation_path")) @@ -46,31 +42,32 @@ def evaluate_rule(rule, config): return True, "Pass" return False, f"{rule['tags']} = {value}, expected {expected}" -# Main function to run all rules and show results def main(): - config = load_mock_config() # Load tenant configuration - rules = load_rules() # Load all CIS rules - - if not config or not rules: - print("No config or rules found. Exiting.") - return + config = load_mock_config() + rules = load_rules() passed, failed = 0, 0 for rule in rules: result, reason = evaluate_rule(rule, config) status = "PASS" if result else "FAIL" - print(f"[{status}] {rule['id_level_2']} - {rule['description']}") + print(f"[{status}] {rule['id_level_2']} - {rule['title']}") + if not result: - print(f" Reason: {reason}") + print(f" Description : {rule['description']}") + print(f" Reason : {reason}") + print(f" Remediation : {rule['remediation']}") + print(" --- Risk Assessment ---") + print(f" Risk Level : {rule.get('risk', 'N/A')}") + print(f" Impact : {rule.get('Impact', 'N/A')}") + print(f" Likelihood : {rule.get('Likelihood', 'N/A')}") + print(f" Overall : {rule.get('Risk level', 'N/A')}") + print("-------------------------------------------------------------------") + passed += result failed += not result - # Summary output - print("Summary:") - print(f" Total Rules: {len(rules)}") - print(f" Passed: {passed}") - print(f" Failed: {failed}") - + print(f"\nSummary: {passed} rules passed, {failed} rules failed") + if __name__ == "__main__": main() \ No newline at end of file diff --git a/rules/1.1.1.json b/rules/1.1.1.json index c01d00da..db6cf91f 100644 --- a/rules/1.1.1.json +++ b/rules/1.1.1.json @@ -12,6 +12,9 @@ "evaluation_path": "user.OnPremisesSyncEnabled", "remediation": "Migrate hybrid admin accounts to new cloud-only accounts and update roles accordingly.", "risk": "High", + "impact": "Moderate", + "likelihood": "2", + "risk_level": "Low", "tags": [ "MFA", "Identity", diff --git a/rules/1.1.2.json b/rules/1.1.2.json index 8b0cc05e..ddfdd791 100644 --- a/rules/1.1.2.json +++ b/rules/1.1.2.json @@ -12,6 +12,9 @@ "evaluation_path": "Microsoft 365 admin center > Users > Active Users and Entra admin center > Protection > Conditional Access", "remediation": "Create two cloud-only accounts with Global Admin role, no license, exclude from Conditional Access rules.", "risk": "High", + "impact": "Serious", + "likelihood": "2", + "risk_level": "Moderate", "tags": [ "Accounts", "EmergencyAccess", diff --git a/rules/1.1.3.json b/rules/1.1.3.json index 760c70f8..15ac3641 100644 --- a/rules/1.1.3.json +++ b/rules/1.1.3.json @@ -12,6 +12,9 @@ "evaluation_path": "Microsoft 365 admin center > Roles > Global Administrator", "remediation": "Add or remove users from Global Admin role to maintain 2\ufffd4 total.", "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", "tags": [ "AdminAccounts", "PrivilegeManagement" diff --git a/rules/1.1.4.json b/rules/1.1.4.json index f4613824..88d5d375 100644 --- a/rules/1.1.4.json +++ b/rules/1.1.4.json @@ -12,6 +12,9 @@ "evaluation_path": "Microsoft 365 admin center > Users > Active users > License column", "remediation": "Assign minimal license or Entra ID P1/P2 to admin accounts. Use PIM if applicable.", "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", "tags": [ "Licensing", "AdminAccounts", diff --git a/rules/1.2.1.json b/rules/1.2.1.json index 9a14c94b..2e319cc1 100644 --- a/rules/1.2.1.json +++ b/rules/1.2.1.json @@ -12,6 +12,9 @@ "evaluation_path": "Microsoft 365 admin center > Teams & groups > Active teams & groups", "remediation": "Change group privacy from Public to Private in group settings.", "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", "tags": [ "Groups", "Privacy", diff --git a/rules/1.2.2.json b/rules/1.2.2.json index edfeb44a..e059382b 100644 --- a/rules/1.2.2.json +++ b/rules/1.2.2.json @@ -12,6 +12,9 @@ "evaluation_path": "Microsoft 365 admin center > Users > Active users > Shared mailbox properties", "remediation": "Uncheck the 'Sign-in allowed' option under mailbox settings.", "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", "tags": [ "Mailbox", "AccountAccess", diff --git a/rules/1.3.1.json b/rules/1.3.1.json index 157dd7b8..e9905bfe 100644 --- a/rules/1.3.1.json +++ b/rules/1.3.1.json @@ -12,6 +12,9 @@ "evaluation_path": "Microsoft 365 admin center > Org Settings > Security & Privacy > Password expiration policy", "remediation": "Enable the 'Set passwords to never expire' option in org settings.", "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", "tags": [ "PasswordPolicy", "UserSettings", diff --git a/rules/1.3.2.json b/rules/1.3.2.json index 47303906..3b6b1554 100644 --- a/rules/1.3.2.json +++ b/rules/1.3.2.json @@ -12,6 +12,9 @@ "evaluation_path": "Microsoft 365 admin center > Org settings > Security & privacy > Idle session timeout", "remediation": "Configure timeout policy in settings for unmanaged device sessions.", "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", "tags": [ "SessionTimeout", "DeviceManagement", diff --git a/rules/1.3.3.json b/rules/1.3.3.json index 22e57b74..95562a3b 100644 --- a/rules/1.3.3.json +++ b/rules/1.3.3.json @@ -12,6 +12,9 @@ "evaluation_path": "Microsoft 365 admin center > Settings > Org settings > Calendar", "remediation": "Disable external calendar sharing in org settings.", "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", "tags": [ "Calendar", "ExternalSharing", diff --git a/rules/1.3.4.json b/rules/1.3.4.json index 46a887f0..512a302f 100644 --- a/rules/1.3.4.json +++ b/rules/1.3.4.json @@ -12,6 +12,9 @@ "evaluation_path": "Microsoft Entra admin center > User settings > App registrations", "remediation": "Disable 'Users can register applications' in user settings.", "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", "tags": [ "UserApps", "ThirdPartyAccess", diff --git a/rules/1.3.5.json b/rules/1.3.5.json index 2c3cff99..c737be71 100644 --- a/rules/1.3.5.json +++ b/rules/1.3.5.json @@ -12,6 +12,9 @@ "evaluation_path": "Microsoft 365 admin center > Settings > Org settings > Microsoft Forms", "remediation": "Enable internal phishing protection in Microsoft Forms settings.", "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", "tags": [ "Forms", "PhishingProtection", diff --git a/rules/1.3.6.json b/rules/1.3.6.json index 1c4af230..3cb51764 100644 --- a/rules/1.3.6.json +++ b/rules/1.3.6.json @@ -12,6 +12,9 @@ "evaluation_path": "Microsoft 365 compliance center > Solutions > Customer Lockbox", "remediation": "Enable Customer Lockbox via Microsoft 365 compliance center.", "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", "tags": [ "CustomerLockbox", "AccessControl", diff --git a/rules/1.3.7.json b/rules/1.3.7.json index f40c2808..c27618c5 100644 --- a/rules/1.3.7.json +++ b/rules/1.3.7.json @@ -12,6 +12,9 @@ "evaluation_path": "Microsoft 365 admin center > Org settings > Services > Office for the web", "remediation": "Disable integration with third-party storage services.", "risk": "High", + "impact": "", + "likelihood": "", + "risk_level": "", "tags": [ "Storage", "ExternalServices", diff --git a/rules/1.3.8.json b/rules/1.3.8.json index 2a65fc99..324b33e8 100644 --- a/rules/1.3.8.json +++ b/rules/1.3.8.json @@ -12,6 +12,9 @@ "evaluation_path": "Microsoft 365 admin center > Settings > Org settings > Sway", "remediation": "Manually disable external sharing for Sway presentations.", "risk": "Medium", + "impact": "", + "likelihood": "", + "risk_level": "", "tags": [ "Sway", "ContentSharing", From b807f6c9cfbe8b2c1beb33823c5fbf9a5d87faeb Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Wed, 20 Aug 2025 17:11:18 +1000 Subject: [PATCH 29/63] slight fix --- engine/main.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/engine/main.py b/engine/main.py index f1d69cf9..a942f7c1 100644 --- a/engine/main.py +++ b/engine/main.py @@ -59,9 +59,9 @@ def main(): print(f" Remediation : {rule['remediation']}") print(" --- Risk Assessment ---") print(f" Risk Level : {rule.get('risk', 'N/A')}") - print(f" Impact : {rule.get('Impact', 'N/A')}") - print(f" Likelihood : {rule.get('Likelihood', 'N/A')}") - print(f" Overall : {rule.get('Risk level', 'N/A')}") + print(f" Impact : {rule.get('impact', 'N/A')}") + print(f" Likelihood : {rule.get('likelihood', 'N/A')}") + print(f" Overall : {rule.get('risk_level', 'N/A')}") print("-------------------------------------------------------------------") passed += result From 810a8429354a8dfcc2fc897417cc4ff2c31d1cf3 Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Thu, 21 Aug 2025 15:40:52 +1000 Subject: [PATCH 30/63] Improve Engine code readability --- engine/main.py | 32 +++++++++++++------------------- test-configs/compliant.json | 21 +++++++++++++++++++++ 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/engine/main.py b/engine/main.py index a942f7c1..f885d004 100644 --- a/engine/main.py +++ b/engine/main.py @@ -2,26 +2,17 @@ import os def load_mock_config(path="test-configs/compliant.json"): - try: - with open(path) as f: - return json.load(f) - except FileNotFoundError: - print(f"Config file not found: {path}") - return {} - except json.JSONDecodeError: - print(f"Invalid JSON in config file: {path}") - return {} + with open(path) as f: + return json.load(f) + def load_rules(directory="rules"): rules = [] for file in os.listdir(directory): if file.endswith(".json"): - try: - with open(os.path.join(directory, file)) as f: - rule = json.load(f) - rules.append(rule) - except json.JSONDecodeError: - print(f"Invalid JSON in {file}") + with open(os.path.join(directory, file)) as f: + rule = json.load(f) + rules.append(rule) return rules def get_value_from_path(config, path): @@ -54,14 +45,17 @@ def main(): print(f"[{status}] {rule['id_level_2']} - {rule['title']}") if not result: + print("") + print(" --- Cause of Failure ---") print(f" Description : {rule['description']}") print(f" Reason : {reason}") print(f" Remediation : {rule['remediation']}") + print("") print(" --- Risk Assessment ---") - print(f" Risk Level : {rule.get('risk', 'N/A')}") - print(f" Impact : {rule.get('impact', 'N/A')}") - print(f" Likelihood : {rule.get('likelihood', 'N/A')}") - print(f" Overall : {rule.get('risk_level', 'N/A')}") + print(f" Risk Level : {rule['risk']}") + print(f" Impact : {rule['impact']}") + print(f" Likelihood : {rule['likelihood']}") + print(f" Overall : {rule['risk_level']}") print("-------------------------------------------------------------------") passed += result diff --git a/test-configs/compliant.json b/test-configs/compliant.json index 292a4a42..392070a4 100644 --- a/test-configs/compliant.json +++ b/test-configs/compliant.json @@ -13,6 +13,27 @@ "block_legacy_auth": "Legacy authentication blocked" } } + }, + "purview" : { + + }, + "entra" : { + + }, + "exchange" : { + + }, + "sharepoint" : { + + }, + "teams" : { + + }, + "defender" : { + + }, + "fabric" : { + } } \ No newline at end of file From f6a12db4076f6815061363ef233df1fa94550e72 Mon Sep 17 00:00:00 2001 From: aaawan9 Date: Fri, 22 Aug 2025 01:15:43 +1000 Subject: [PATCH 31/63] Update 1.1.2.json --- rules/1.1.2.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/1.1.2.json b/rules/1.1.2.json index ddfdd791..3d17f789 100644 --- a/rules/1.1.2.json +++ b/rules/1.1.2.json @@ -9,7 +9,7 @@ "description": "Emergency access or \ufffdbreak glass\ufffd accounts are limited for emergency scenarios where normal administrative accounts are unavailable.", "expected_value": "Two emergency access accounts defined", "comparison": "Manual validation", - "evaluation_path": "Microsoft 365 admin center > Users > Active Users and Entra admin center > Protection > Conditional Access", + "evaluation_path": "user.WithTwoEmergencyAccs", "remediation": "Create two cloud-only accounts with Global Admin role, no license, exclude from Conditional Access rules.", "risk": "High", "impact": "Serious", @@ -20,4 +20,4 @@ "EmergencyAccess", "GlobalAdmin" ] -} \ No newline at end of file +} From 15a0776b2b4c811972055679fd32ea3455e31683 Mon Sep 17 00:00:00 2001 From: aaawan9 Date: Fri, 22 Aug 2025 01:17:38 +1000 Subject: [PATCH 32/63] Update 1.1.3.json --- rules/1.1.3.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/1.1.3.json b/rules/1.1.3.json index 15ac3641..658b2fbd 100644 --- a/rules/1.1.3.json +++ b/rules/1.1.3.json @@ -9,7 +9,7 @@ "description": "Between two and four global administrators should be designated in the tenant to ensure redundancy and limit exposure.", "expected_value": "2\ufffd4 Global Administrators", "comparison": "Count and range check", - "evaluation_path": "Microsoft 365 admin center > Roles > Global Administrator", + "evaluation_path": "user.globalAdmins", "remediation": "Add or remove users from Global Admin role to maintain 2\ufffd4 total.", "risk": "High", "impact": "", @@ -19,4 +19,4 @@ "AdminAccounts", "PrivilegeManagement" ] -} \ No newline at end of file +} From e853bb5f9fde7f6759ceb9b4939945f20d2102f8 Mon Sep 17 00:00:00 2001 From: aaawan9 Date: Fri, 22 Aug 2025 01:18:53 +1000 Subject: [PATCH 33/63] Update 1.1.4.json --- rules/1.1.4.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/1.1.4.json b/rules/1.1.4.json index 88d5d375..24d7cbd1 100644 --- a/rules/1.1.4.json +++ b/rules/1.1.4.json @@ -9,7 +9,7 @@ "description": "Administrative accounts should not use licenses with applications to reduce attack surface.", "expected_value": "License with no user applications (e.g. Entra ID P1/P2)", "comparison": "License check", - "evaluation_path": "Microsoft 365 admin center > Users > Active users > License column", + "evaluation_path": "user.licenses", "remediation": "Assign minimal license or Entra ID P1/P2 to admin accounts. Use PIM if applicable.", "risk": "Medium", "impact": "", @@ -20,4 +20,4 @@ "AdminAccounts", "LeastPrivilege" ] -} \ No newline at end of file +} From c05ad3d36950fdd27d9731099122986e44ee47e3 Mon Sep 17 00:00:00 2001 From: aaawan9 Date: Fri, 22 Aug 2025 01:19:57 +1000 Subject: [PATCH 34/63] Update 1.2.1.json --- rules/1.2.1.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/1.2.1.json b/rules/1.2.1.json index 2e319cc1..3261eef5 100644 --- a/rules/1.2.1.json +++ b/rules/1.2.1.json @@ -9,7 +9,7 @@ "description": "Ensure that only organizationally managed and approved public groups exist to prevent unauthorized access to internal data.", "expected_value": "No groups with public visibility", "comparison": "Group.Visibility != Public", - "evaluation_path": "Microsoft 365 admin center > Teams & groups > Active teams & groups", + "evaluation_path": "groups.approved", "remediation": "Change group privacy from Public to Private in group settings.", "risk": "High", "impact": "", @@ -20,4 +20,4 @@ "Privacy", "AccessControl" ] -} \ No newline at end of file +} From ea62b758eabf114b8790a2f53b19fb5bd8dcdd1c Mon Sep 17 00:00:00 2001 From: aaawan9 Date: Fri, 22 Aug 2025 01:21:01 +1000 Subject: [PATCH 35/63] Update 1.2.2.json --- rules/1.2.2.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/1.2.2.json b/rules/1.2.2.json index e059382b..b3bc203f 100644 --- a/rules/1.2.2.json +++ b/rules/1.2.2.json @@ -9,7 +9,7 @@ "description": "Block sign-in access for shared mailboxes to reduce exposure to unauthorized access.", "expected_value": "Sign-in disabled for shared mailboxes", "comparison": "user.AccountEnabled == false", - "evaluation_path": "Microsoft 365 admin center > Users > Active users > Shared mailbox properties", + "evaluation_path": "mailboxes.shared", "remediation": "Uncheck the 'Sign-in allowed' option under mailbox settings.", "risk": "Medium", "impact": "", @@ -20,4 +20,4 @@ "AccountAccess", "Security" ] -} \ No newline at end of file +} From b8c443c6182801176a5e666a9b4ba781c6b21a06 Mon Sep 17 00:00:00 2001 From: aaawan9 Date: Fri, 22 Aug 2025 01:22:51 +1000 Subject: [PATCH 36/63] Update 1.3.1.json --- rules/1.3.1.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/1.3.1.json b/rules/1.3.1.json index e9905bfe..0c4b6748 100644 --- a/rules/1.3.1.json +++ b/rules/1.3.1.json @@ -9,7 +9,7 @@ "description": "Avoid enforcing periodic password changes unless a compromise is suspected.", "expected_value": "Set passwords to never expire", "comparison": "PasswordExpiration == Never", - "evaluation_path": "Microsoft 365 admin center > Org Settings > Security & Privacy > Password expiration policy", + "evaluation_path": "password.expiration", "remediation": "Enable the 'Set passwords to never expire' option in org settings.", "risk": "Medium", "impact": "", @@ -20,4 +20,4 @@ "UserSettings", "Authentication" ] -} \ No newline at end of file +} From 1f780eef9802d719516b55c7753b3a41f358eb16 Mon Sep 17 00:00:00 2001 From: aaawan9 Date: Fri, 22 Aug 2025 01:23:48 +1000 Subject: [PATCH 37/63] Update 1.3.2.json --- rules/1.3.2.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/1.3.2.json b/rules/1.3.2.json index 3b6b1554..8e8c6470 100644 --- a/rules/1.3.2.json +++ b/rules/1.3.2.json @@ -9,7 +9,7 @@ "description": "Limit idle session timeout for unmanaged devices to reduce session hijack risks.", "expected_value": "Idle timeout set to = 3 hours", "comparison": "IdleTimeout <= 3h", - "evaluation_path": "Microsoft 365 admin center > Org settings > Security & privacy > Idle session timeout", + "evaluation_path": "session.idleTimeout", "remediation": "Configure timeout policy in settings for unmanaged device sessions.", "risk": "High", "impact": "", @@ -20,4 +20,4 @@ "DeviceManagement", "UnmanagedAccess" ] -} \ No newline at end of file +} From 63d67273018b0c38f0cf0269f8393275f9991e2f Mon Sep 17 00:00:00 2001 From: aaawan9 Date: Fri, 22 Aug 2025 01:24:44 +1000 Subject: [PATCH 38/63] Update 1.3.3.json --- rules/1.3.3.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/1.3.3.json b/rules/1.3.3.json index 95562a3b..1713ad62 100644 --- a/rules/1.3.3.json +++ b/rules/1.3.3.json @@ -9,7 +9,7 @@ "description": "Prevent external calendar sharing to avoid data leakage and preserve internal privacy.", "expected_value": "External sharing disabled", "comparison": "CalendarSharing == InternalOnly", - "evaluation_path": "Microsoft 365 admin center > Settings > Org settings > Calendar", + "evaluation_path": "calendar.externalSharing", "remediation": "Disable external calendar sharing in org settings.", "risk": "High", "impact": "", @@ -20,4 +20,4 @@ "ExternalSharing", "Privacy" ] -} \ No newline at end of file +} From 7479d9c15384bcf67343b330f50845a66e3ee6a4 Mon Sep 17 00:00:00 2001 From: aaawan9 Date: Fri, 22 Aug 2025 01:25:50 +1000 Subject: [PATCH 39/63] Update 1.3.4.json --- rules/1.3.4.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/1.3.4.json b/rules/1.3.4.json index 512a302f..0c4118e8 100644 --- a/rules/1.3.4.json +++ b/rules/1.3.4.json @@ -9,7 +9,7 @@ "description": "Restrict user ability to register applications to control third-party integrations.", "expected_value": "App registration disabled for users", "comparison": "AppRegistration == Disabled", - "evaluation_path": "Microsoft Entra admin center > User settings > App registrations", + "evaluation_path": "apps.userOwned", "remediation": "Disable 'Users can register applications' in user settings.", "risk": "Medium", "impact": "", @@ -20,4 +20,4 @@ "ThirdPartyAccess", "AppRegistration" ] -} \ No newline at end of file +} From a64bb2b2058813126f1248364fee423963ebb9ee Mon Sep 17 00:00:00 2001 From: aaawan9 Date: Fri, 22 Aug 2025 01:26:46 +1000 Subject: [PATCH 40/63] Update 1.3.5.json --- rules/1.3.5.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/1.3.5.json b/rules/1.3.5.json index c737be71..958cdf76 100644 --- a/rules/1.3.5.json +++ b/rules/1.3.5.json @@ -9,7 +9,7 @@ "description": "Enable internal phishing detection for Microsoft Forms to prevent credential harvesting.", "expected_value": "Phishing protection enabled", "comparison": "FormsPhishingProtection == On", - "evaluation_path": "Microsoft 365 admin center > Settings > Org settings > Microsoft Forms", + "evaluation_path": "forms.phishingProtection", "remediation": "Enable internal phishing protection in Microsoft Forms settings.", "risk": "Medium", "impact": "", @@ -20,4 +20,4 @@ "PhishingProtection", "ThreatDetection" ] -} \ No newline at end of file +} From d81b3c553c3379a5b756ba63f180facd9369bcc0 Mon Sep 17 00:00:00 2001 From: aaawan9 Date: Fri, 22 Aug 2025 01:27:41 +1000 Subject: [PATCH 41/63] Update 1.3.6.json --- rules/1.3.6.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/1.3.6.json b/rules/1.3.6.json index 3cb51764..c76e4941 100644 --- a/rules/1.3.6.json +++ b/rules/1.3.6.json @@ -9,7 +9,7 @@ "description": "Require explicit customer approval before Microsoft can access customer content.", "expected_value": "Customer lockbox enabled", "comparison": "Lockbox == Enabled", - "evaluation_path": "Microsoft 365 compliance center > Solutions > Customer Lockbox", + "evaluation_path": "customer.lockbox", "remediation": "Enable Customer Lockbox via Microsoft 365 compliance center.", "risk": "High", "impact": "", @@ -20,4 +20,4 @@ "AccessControl", "DataProtection" ] -} \ No newline at end of file +} From b318a34f93293947cbaae0c528c97a1d5e6f9987 Mon Sep 17 00:00:00 2001 From: aaawan9 Date: Fri, 22 Aug 2025 01:28:27 +1000 Subject: [PATCH 42/63] Update 1.3.7.json --- rules/1.3.7.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/1.3.7.json b/rules/1.3.7.json index c27618c5..5e2e1d82 100644 --- a/rules/1.3.7.json +++ b/rules/1.3.7.json @@ -9,7 +9,7 @@ "description": "Restrict access to third-party storage services like Dropbox or Google Drive to protect data.", "expected_value": "Third-party storage access disabled", "comparison": "ThirdPartyStorage == Disabled", - "evaluation_path": "Microsoft 365 admin center > Org settings > Services > Office for the web", + "evaluation_path": "office.ThirdPartyStorage", "remediation": "Disable integration with third-party storage services.", "risk": "High", "impact": "", @@ -20,4 +20,4 @@ "ExternalServices", "DataControl" ] -} \ No newline at end of file +} From 3634e33b3e84b69b0073fcb4ce104f5bb119c0ab Mon Sep 17 00:00:00 2001 From: aaawan9 Date: Fri, 22 Aug 2025 01:29:27 +1000 Subject: [PATCH 43/63] Update 1.3.8.json --- rules/1.3.8.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/1.3.8.json b/rules/1.3.8.json index 324b33e8..2b34cf52 100644 --- a/rules/1.3.8.json +++ b/rules/1.3.8.json @@ -9,7 +9,7 @@ "description": "Prevent sharing of Microsoft Sway content outside the organization to maintain internal content privacy.", "expected_value": "External sharing disabled for Sways", "comparison": "SwaySharing == InternalOnly", - "evaluation_path": "Microsoft 365 admin center > Settings > Org settings > Sway", + "evaluation_path": "sway.externalSharing", "remediation": "Manually disable external sharing for Sway presentations.", "risk": "Medium", "impact": "", @@ -20,4 +20,4 @@ "ContentSharing", "ExternalAccess" ] -} \ No newline at end of file +} From 3043f27e3b54b8644ccc199fa23ec2278d3b6593 Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Thu, 28 Aug 2025 17:03:55 +1000 Subject: [PATCH 44/63] GCP Rego update --- engine/GCPAccess.py | 19 +++++++++++++++++++ engine/Helpers.rego | 32 ++++++++++++++++++++++++++++++++ iam_policy.json | 18 ++++++++++++++++++ rules/CIS_GCP_1_5.rego | 6 ++++++ 4 files changed, 75 insertions(+) create mode 100644 engine/GCPAccess.py create mode 100644 engine/Helpers.rego create mode 100644 iam_policy.json create mode 100644 rules/CIS_GCP_1_5.rego diff --git a/engine/GCPAccess.py b/engine/GCPAccess.py new file mode 100644 index 00000000..c5af1eea --- /dev/null +++ b/engine/GCPAccess.py @@ -0,0 +1,19 @@ +from googleapiclient.discovery import build +from google.auth import default +import json + +creds, _ = default(scopes=["https://www.googleapis.com/auth/cloud-platform"]) +crm = build("cloudresourcemanager", "v3", credentials=creds) + +project_id = "coastal-stone-470308-a0" +res_name = f"projects/{project_id}" + +policy = crm.projects().getIamPolicy( + resource=res_name, + body={"options": {"requestedPolicyVersion": 3}} +).execute() + +with open("iam_policy.json", "w") as f: + json.dump(policy, f, indent=2) + +print("IAM policy written to iam_policy.json") \ No newline at end of file diff --git a/engine/Helpers.rego b/engine/Helpers.rego new file mode 100644 index 00000000..219e9752 --- /dev/null +++ b/engine/Helpers.rego @@ -0,0 +1,32 @@ +package AutoAudit_tester.engine.Helpers + +import future.keywords.in + +get(path) = v if { + parts := split(path, ".") + some i + pv := walk(input)[i] + p := pv[0] + v := pv[1] + p == parts +} +equals(path, expected) if { + get(path) == expected +} + +in_whitelist(path, allowed) if { + val := get(path) + val in allowed +} +not_in_blacklist(path, blocked) if { + val := get(path) + not val in blocked +} +status(bool) = s if { + bool + s := "Compliant" +} +status(bool) = s if { + not bool + s := "NonCompliant" +} diff --git a/iam_policy.json b/iam_policy.json new file mode 100644 index 00000000..8afc21d2 --- /dev/null +++ b/iam_policy.json @@ -0,0 +1,18 @@ +{ + "version": 1, + "etag": "BwY9WRutdgg=", + "bindings": [ + { + "role": "roles/editor", + "members": [ + "serviceAccount:sa-noperms@coastal-stone-470308-a0.iam.gserviceaccount.com" + ] + }, + { + "role": "roles/owner", + "members": [ + "user:AdityaHindocha3@gmail.com" + ] + } + ] +} \ No newline at end of file diff --git a/rules/CIS_GCP_1_5.rego b/rules/CIS_GCP_1_5.rego new file mode 100644 index 00000000..2738921d --- /dev/null +++ b/rules/CIS_GCP_1_5.rego @@ -0,0 +1,6 @@ +package AutoAudit_tester.rules.CIS_GCP_1_5 +import data.AutoAudit_tester.engine.Helpers + +result.no_admin := Helpers.status( + Helpers.not_in_blacklist("bindings.role", {"roles/owner","roles/editor"}) +) From d9dcc585fcc7f2fc7fc4ebcff31ca5f7fb62a08b Mon Sep 17 00:00:00 2001 From: 223159756 <139199818+223159756@users.noreply.github.com> Date: Thu, 28 Aug 2025 18:33:16 +1000 Subject: [PATCH 45/63] Update GCPAccess.py --- engine/GCPAccess.py | 1 - 1 file changed, 1 deletion(-) diff --git a/engine/GCPAccess.py b/engine/GCPAccess.py index c5af1eea..b1025592 100644 --- a/engine/GCPAccess.py +++ b/engine/GCPAccess.py @@ -16,4 +16,3 @@ with open("iam_policy.json", "w") as f: json.dump(policy, f, indent=2) -print("IAM policy written to iam_policy.json") \ No newline at end of file From 557d884e570af1fb226300771d950c03bf5ce06c Mon Sep 17 00:00:00 2001 From: 223159756 <139199818+223159756@users.noreply.github.com> Date: Mon, 1 Sep 2025 16:41:54 +1000 Subject: [PATCH 46/63] Create Collecter.yml Testing automated policy collector with GitHub secrets --- .github/workflows/Collecter.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/Collecter.yml diff --git a/.github/workflows/Collecter.yml b/.github/workflows/Collecter.yml new file mode 100644 index 00000000..db093b75 --- /dev/null +++ b/.github/workflows/Collecter.yml @@ -0,0 +1,27 @@ +name: Run Collector + +on: + push: + branches: [Compliance-Engine] + +jobs: + run-collector: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install deps + run: pip install google-api-python-client google-auth google-auth-httplib2 google-auth-oauthlib + + - name: Configure GCP credentials + run: | + echo "${{ secrets.GCP_CREDENTIALS }}" > "${HOME}/gcp-key.json" + echo "GOOGLE_APPLICATION_CREDENTIALS=${HOME}/gcp-key.json" >> $GITHUB_ENV + + - name: Run GCP Access Collector + run: python3 engine/GCPAccess.py From feab9b455749af105b9403fdb560eb06bb8d659c Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Mon, 1 Sep 2025 16:45:05 +1000 Subject: [PATCH 47/63] updated collector code with secrets --- engine/GCPAccess.py | 5 +++++ iam_policy.json | 12 ++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/engine/GCPAccess.py b/engine/GCPAccess.py index b1025592..840961ba 100644 --- a/engine/GCPAccess.py +++ b/engine/GCPAccess.py @@ -1,3 +1,4 @@ +from google.oauth2 import service_account from googleapiclient.discovery import build from google.auth import default import json @@ -16,3 +17,7 @@ with open("iam_policy.json", "w") as f: json.dump(policy, f, indent=2) +<<<<<<< Updated upstream +======= +print("IAM policy written to iam_policy.json") +>>>>>>> Stashed changes diff --git a/iam_policy.json b/iam_policy.json index 8afc21d2..f29a225e 100644 --- a/iam_policy.json +++ b/iam_policy.json @@ -1,11 +1,19 @@ { "version": 1, - "etag": "BwY9WRutdgg=", + "etag": "BwY9aQGbYhE=", "bindings": [ + { + "role": "roles/compute.serviceAgent", + "members": [ + "serviceAccount:service-162922847862@compute-system.iam.gserviceaccount.com" + ] + }, { "role": "roles/editor", "members": [ - "serviceAccount:sa-noperms@coastal-stone-470308-a0.iam.gserviceaccount.com" + "serviceAccount:162922847862@cloudservices.gserviceaccount.com", + "serviceAccount:sa-noperms@coastal-stone-470308-a0.iam.gserviceaccount.com", + "serviceAccount:162922847862-compute@developer.gserviceaccount.com" ] }, { From 940c573e12c204828db233b0a6c2856cf7bedb17 Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Mon, 1 Sep 2025 16:46:14 +1000 Subject: [PATCH 48/63] minor change --- engine/GCPAccess.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/engine/GCPAccess.py b/engine/GCPAccess.py index 840961ba..c233d518 100644 --- a/engine/GCPAccess.py +++ b/engine/GCPAccess.py @@ -17,7 +17,3 @@ with open("iam_policy.json", "w") as f: json.dump(policy, f, indent=2) -<<<<<<< Updated upstream -======= -print("IAM policy written to iam_policy.json") ->>>>>>> Stashed changes From bb6076b88769a64220252369cbe59f9235dcd129 Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Mon, 1 Sep 2025 16:49:51 +1000 Subject: [PATCH 49/63] using env variable instaed of git secrets --- .github/workflows/Collecter.yml | 7 +++---- engine/GCPAccess.py | 10 ++++++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/workflows/Collecter.yml b/.github/workflows/Collecter.yml index db093b75..49de1e4a 100644 --- a/.github/workflows/Collecter.yml +++ b/.github/workflows/Collecter.yml @@ -18,10 +18,9 @@ jobs: - name: Install deps run: pip install google-api-python-client google-auth google-auth-httplib2 google-auth-oauthlib - - name: Configure GCP credentials - run: | - echo "${{ secrets.GCP_CREDENTIALS }}" > "${HOME}/gcp-key.json" - echo "GOOGLE_APPLICATION_CREDENTIALS=${HOME}/gcp-key.json" >> $GITHUB_ENV + - name: Run GCP Access Collector + env: + GCP_CREDENTIALS: ${{ secrets.GCP_CREDENTIALS }} - name: Run GCP Access Collector run: python3 engine/GCPAccess.py diff --git a/engine/GCPAccess.py b/engine/GCPAccess.py index c233d518..72b68d4c 100644 --- a/engine/GCPAccess.py +++ b/engine/GCPAccess.py @@ -1,9 +1,15 @@ from google.oauth2 import service_account from googleapiclient.discovery import build from google.auth import default -import json +import json +import os + +service_account_info = json.loads(os.environ["GCP_CREDENTIALS"]) +creds = service_account.Credentials.from_service_account_info( + service_account_info, + scopes=["https://www.googleapis.com/auth/cloud-platform"], +) -creds, _ = default(scopes=["https://www.googleapis.com/auth/cloud-platform"]) crm = build("cloudresourcemanager", "v3", credentials=creds) project_id = "coastal-stone-470308-a0" From 959f1931a9edc351f6d8a7cfe32263dca10f2e02 Mon Sep 17 00:00:00 2001 From: 223159756 <139199818+223159756@users.noreply.github.com> Date: Mon, 1 Sep 2025 16:52:35 +1000 Subject: [PATCH 50/63] Update Collecter.yml whatever --- .github/workflows/Collecter.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/Collecter.yml b/.github/workflows/Collecter.yml index 49de1e4a..1ed5c0cc 100644 --- a/.github/workflows/Collecter.yml +++ b/.github/workflows/Collecter.yml @@ -21,6 +21,5 @@ jobs: - name: Run GCP Access Collector env: GCP_CREDENTIALS: ${{ secrets.GCP_CREDENTIALS }} - - - name: Run GCP Access Collector run: python3 engine/GCPAccess.py + From 89b40ffc1ae989122b465c69f3a5497361014805 Mon Sep 17 00:00:00 2001 From: 223159756 <139199818+223159756@users.noreply.github.com> Date: Mon, 1 Sep 2025 16:54:01 +1000 Subject: [PATCH 51/63] Delete iam_policy.json Lets see if the collector works --- iam_policy.json | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 iam_policy.json diff --git a/iam_policy.json b/iam_policy.json deleted file mode 100644 index f29a225e..00000000 --- a/iam_policy.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "version": 1, - "etag": "BwY9aQGbYhE=", - "bindings": [ - { - "role": "roles/compute.serviceAgent", - "members": [ - "serviceAccount:service-162922847862@compute-system.iam.gserviceaccount.com" - ] - }, - { - "role": "roles/editor", - "members": [ - "serviceAccount:162922847862@cloudservices.gserviceaccount.com", - "serviceAccount:sa-noperms@coastal-stone-470308-a0.iam.gserviceaccount.com", - "serviceAccount:162922847862-compute@developer.gserviceaccount.com" - ] - }, - { - "role": "roles/owner", - "members": [ - "user:AdityaHindocha3@gmail.com" - ] - } - ] -} \ No newline at end of file From 0e24970b0e9aebd7ddfec8c3998340e8b01d27e5 Mon Sep 17 00:00:00 2001 From: 223159756 <139199818+223159756@users.noreply.github.com> Date: Mon, 1 Sep 2025 17:20:51 +1000 Subject: [PATCH 52/63] Update Collecter.yml Committing the policy json file outputted --- .github/workflows/Collecter.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/Collecter.yml b/.github/workflows/Collecter.yml index 1ed5c0cc..4585586a 100644 --- a/.github/workflows/Collecter.yml +++ b/.github/workflows/Collecter.yml @@ -7,8 +7,12 @@ on: jobs: run-collector: runs-on: ubuntu-latest + permissions: + contents: write steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Set up Python uses: actions/setup-python@v5 @@ -21,5 +25,15 @@ jobs: - name: Run GCP Access Collector env: GCP_CREDENTIALS: ${{ secrets.GCP_CREDENTIALS }} - run: python3 engine/GCPAccess.py + run: | + python3 engine/GCPAccess.py + mv iam_policy.json engine/test-configs/iam_policy.json + + - name: Commit and push IAM policy + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add engine/test-configs/iam_policy.json + git diff --cached --quiet && echo "No changes to commit" || git commit -m "Update iam_policy.json [skip ci]" + git push origin Compliance-Engine From 5c908923b1a45d8f63593a678a17fec02b03e69d Mon Sep 17 00:00:00 2001 From: 223159756 <139199818+223159756@users.noreply.github.com> Date: Mon, 1 Sep 2025 17:22:13 +1000 Subject: [PATCH 53/63] Update Collecter.yml Updated path --- .github/workflows/Collecter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Collecter.yml b/.github/workflows/Collecter.yml index 4585586a..e721f357 100644 --- a/.github/workflows/Collecter.yml +++ b/.github/workflows/Collecter.yml @@ -27,7 +27,7 @@ jobs: GCP_CREDENTIALS: ${{ secrets.GCP_CREDENTIALS }} run: | python3 engine/GCPAccess.py - mv iam_policy.json engine/test-configs/iam_policy.json + mv iam_policy.json test-configs/iam_policy.json - name: Commit and push IAM policy run: | From ef1fa1dffda7cfba6ddfaec0462dac0f265c2893 Mon Sep 17 00:00:00 2001 From: 223159756 <139199818+223159756@users.noreply.github.com> Date: Mon, 1 Sep 2025 17:23:08 +1000 Subject: [PATCH 54/63] Update Collecter.yml last one I promise --- .github/workflows/Collecter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Collecter.yml b/.github/workflows/Collecter.yml index e721f357..9fb07d66 100644 --- a/.github/workflows/Collecter.yml +++ b/.github/workflows/Collecter.yml @@ -33,7 +33,7 @@ jobs: run: | git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add engine/test-configs/iam_policy.json + git add test-configs/iam_policy.json git diff --cached --quiet && echo "No changes to commit" || git commit -m "Update iam_policy.json [skip ci]" git push origin Compliance-Engine From b3459faaeb9c0145436110f0cc8c00674f08fc4a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 1 Sep 2025 07:23:21 +0000 Subject: [PATCH 55/63] Update iam_policy.json [skip ci] --- test-configs/iam_policy.json | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 test-configs/iam_policy.json diff --git a/test-configs/iam_policy.json b/test-configs/iam_policy.json new file mode 100644 index 00000000..f29a225e --- /dev/null +++ b/test-configs/iam_policy.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "etag": "BwY9aQGbYhE=", + "bindings": [ + { + "role": "roles/compute.serviceAgent", + "members": [ + "serviceAccount:service-162922847862@compute-system.iam.gserviceaccount.com" + ] + }, + { + "role": "roles/editor", + "members": [ + "serviceAccount:162922847862@cloudservices.gserviceaccount.com", + "serviceAccount:sa-noperms@coastal-stone-470308-a0.iam.gserviceaccount.com", + "serviceAccount:162922847862-compute@developer.gserviceaccount.com" + ] + }, + { + "role": "roles/owner", + "members": [ + "user:AdityaHindocha3@gmail.com" + ] + } + ] +} \ No newline at end of file From aea16c7985e92211e1e46d4ada80bc6fc33d4eda Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Tue, 2 Sep 2025 13:30:47 +1000 Subject: [PATCH 56/63] a try --- .github/workflows/Collecter.yml | 2 +- engine/GCPAccess.py | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/Collecter.yml b/.github/workflows/Collecter.yml index 9fb07d66..c20e66bc 100644 --- a/.github/workflows/Collecter.yml +++ b/.github/workflows/Collecter.yml @@ -34,6 +34,6 @@ jobs: git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git add test-configs/iam_policy.json - git diff --cached --quiet && echo "No changes to commit" || git commit -m "Update iam_policy.json [skip ci]" + git diff --cached --quiet && echo "No changes to commit" || git commit -m "Update iam_policy.json" git push origin Compliance-Engine diff --git a/engine/GCPAccess.py b/engine/GCPAccess.py index 72b68d4c..3df698c9 100644 --- a/engine/GCPAccess.py +++ b/engine/GCPAccess.py @@ -10,16 +10,27 @@ scopes=["https://www.googleapis.com/auth/cloud-platform"], ) -crm = build("cloudresourcemanager", "v3", credentials=creds) +crm_policy = build("cloudresourcemanager", "v3", credentials=creds) +crm_compute = build("compute", "v1", credentials=creds) project_id = "coastal-stone-470308-a0" res_name = f"projects/{project_id}" -policy = crm.projects().getIamPolicy( +policy = crm_policy.projects().getIamPolicy( resource=res_name, body={"options": {"requestedPolicyVersion": 3}} ).execute() +networks = [] +req = crm_compute.networks().list(project=project_id) +while req is not None: + resp = req.execute() + networks.extend(resp.get("items", [])) + req = crm_compute.networks().list_next(previous_request=req, previous_response=resp) + with open("iam_policy.json", "w") as f: json.dump(policy, f, indent=2) +with open("networks.json", "w") as f: + json.dump(networks, f, indent=2) + From 4fe952c8849943e7b090e716c4639e6a84188496 Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Wed, 3 Sep 2025 19:32:02 +1000 Subject: [PATCH 57/63] added code in collecter to extract compute networks config --- .github/workflows/Collecter.yml | 6 ++-- engine/huh.py | 37 ++++++++++++++++++++ engine/test-sa-key.json | 13 +++++++ iam_policy.json | 26 ++++++++++++++ networks.json | 60 +++++++++++++++++++++++++++++++++ 5 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 engine/huh.py create mode 100644 engine/test-sa-key.json create mode 100644 iam_policy.json create mode 100644 networks.json diff --git a/.github/workflows/Collecter.yml b/.github/workflows/Collecter.yml index c20e66bc..b37531d2 100644 --- a/.github/workflows/Collecter.yml +++ b/.github/workflows/Collecter.yml @@ -28,12 +28,14 @@ jobs: run: | python3 engine/GCPAccess.py mv iam_policy.json test-configs/iam_policy.json + mv networks.json test-configs/networks.json - - name: Commit and push IAM policy + - name: Commit and push IAM policy & networks config run: | git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git add test-configs/iam_policy.json - git diff --cached --quiet && echo "No changes to commit" || git commit -m "Update iam_policy.json" + git add test-configs/networks.json + git diff --cached --quiet && echo "No changes to commit" || git commit -m "Update iam_policy.json & networks.json" git push origin Compliance-Engine diff --git a/engine/huh.py b/engine/huh.py new file mode 100644 index 00000000..4e41ff71 --- /dev/null +++ b/engine/huh.py @@ -0,0 +1,37 @@ +from google.oauth2 import service_account +from googleapiclient.discovery import build +from google.auth import default +import json +import os + +KEY_PATH = "engine/test-sa-key.json" + +creds = service_account.Credentials.from_service_account_file( + KEY_PATH, + scopes=["https://www.googleapis.com/auth/cloud-platform"], +) + +crm_policy = build("cloudresourcemanager", "v3", credentials=creds) +crm_compute = build("compute", "v1", credentials=creds) + +project_id = "coastal-stone-470308-a0" +res_name = f"projects/{project_id}" + +policy = crm_policy.projects().getIamPolicy( + resource=res_name, + body={"options": {"requestedPolicyVersion": 3}} +).execute() + +networks = [] +req = crm_compute.networks().list(project=project_id) +while req is not None: + resp = req.execute() + networks.extend(resp.get("items", [])) + req = crm_compute.networks().list_next(previous_request=req, previous_response=resp) + +with open("iam_policy.json", "w") as f: + json.dump(policy, f, indent=2) + +with open("networks.json", "w") as f: + json.dump(networks, f, indent=2) + diff --git a/engine/test-sa-key.json b/engine/test-sa-key.json new file mode 100644 index 00000000..09318c45 --- /dev/null +++ b/engine/test-sa-key.json @@ -0,0 +1,13 @@ +{ + "type": "service_account", + "project_id": "coastal-stone-470308-a0", + "private_key_id": "5476e8c2dee74f5e7eea55d98bcc2815b71e44ef", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDYPi619VGWmVcg\nPyDYxAM/kyfcZfwWGxy7JWPu7G/MlvTd+A/YdbBwPXzDDDEZ0rsuFfflgS8BYWoo\nwvU3D01fME/jfVHaMc63lI2yzi9HZ/Uchm6jEn/x/vtckz2lW2k1W4woEfhwxHQA\nPYbzH/PFna7rFPhPX3xBmFNT490rfsga08lGj4hRXZevLMiXZmG+YMfvkmojwQbc\n7SZYeGN1quvQrsUkFI77iciR0d6JiUQuboBJ5dEJcmYdwt/FSed1sCafi26zYF6+\nbPlnaqgtQbuodLBMSNxkfT/x+NqwTDq8AC5MumC5ohAlhl0BOapx3R3tbHCvsxdL\noMurT+49AgMBAAECggEAAKc/cOFK28+eycQnD0CYWerR5gKQ3mg6j/4u7Rvdwpp6\nJumG8rp4S/6Dj/tLcq6GTj9WvmTDhZeLwI/GOeJb83ur4h4Qzz3zR+609uNUlTyl\nKu7lCq0Vod+JVuBDAWrjSHv8Umqre3u8dfu5mqZwEBrH2oH3thWtxGz3Y3t+wZDh\nEe3FaAYB5Mn2wW8A2x8lJZJup4TQJ7OLf6lzsf47/UUycJYxd+jzkrw1CvfkwwUn\n3xpQ9k10xLupiI+pNsxSOVobCp5eDGSeENWh9MnfftSLClaQsn1N0VSm4fEIp259\nMRimLd+aqGvcSacWhnVLMps+auKAn6aWQeYNpzOXwQKBgQDsvBrc0av9EqNg+gA6\ngbiMuBZ+4GvYT95YzR2Wgy7WjY1h7XR0bp2VQaaTtTxnK04X+H49ITMAMehWYaxY\nBXYyXdCYrWZIpVHUPxmAQKj+kmALM8/HmtGRkKApByT8UxusLvZCYtEpuKzBPkuX\nmtVW+XxYq/N7kl1f0IaEJbLqiQKBgQDp1yuPoZs/Ob1jckDeFa18LZ9Td0YFhrKV\nOoqTIvQ9YrPkrBs2t4H8t5Xq8A9ZvgO3g0WDAV6u+y82O9YsppG9Rf4TeV/CzyKi\neotW/ZqB6GhSOa3p6lpzYXqNGXst7IUVjT6TUaAfsrZUtFHQVIZjHU1Ye8H/Qo65\ncFuBX8zpFQKBgQCEKDau03Y6H2+Jscby4nwOQq58Qfiyl1O/KzK7VZyONhOZeaAr\nZ50dN7swdlq0FZ7RDu4aXjBEiZf0sS4vLU1grLLIqPSS1Yeq/1bTHEW7aCep2VDD\nU5BuvNhMTyq8mgC2zLi5MsUlj20RrB8zEULL/RcHwWZ5s6ng1V5i41DQUQKBgQCB\npVE6dd/r4uhUrXC3cI9ZzLWMAhHpWG/Eest/nh6JtiKEwsLnyEAiS+qrceMg30+S\nPA6a/nRvUUYwrGYnJUaiCJ9ATse/6zWJnaWJWluCcMb954q7qLnzRHU8q4b2xC5Y\n75Fk/hln2Z5rQfomJebIJuPODfdVvaIBwACLrwCdrQKBgE/cfZ1EhAiXCKi2OrH+\nFJB9De9m2XeW4lY7geQkqQy3z29Rdc4yxEd4W0lmXX25eC2HjEnP11GmqhUK8Osr\n7N40734KPDnkFaQ/Cbxk+7fDSmXbmuOwLOYacw2Nk/DcCnxrSZ0GIUDiFpFSGhHE\ntCsjZmReOVFmI2ZPO8E1YnPS\n-----END PRIVATE KEY-----\n", + "client_email": "sa-noperms@coastal-stone-470308-a0.iam.gserviceaccount.com", + "client_id": "113627683228706962319", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/sa-noperms%40coastal-stone-470308-a0.iam.gserviceaccount.com", + "universe_domain": "googleapis.com" +} diff --git a/iam_policy.json b/iam_policy.json new file mode 100644 index 00000000..f29a225e --- /dev/null +++ b/iam_policy.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "etag": "BwY9aQGbYhE=", + "bindings": [ + { + "role": "roles/compute.serviceAgent", + "members": [ + "serviceAccount:service-162922847862@compute-system.iam.gserviceaccount.com" + ] + }, + { + "role": "roles/editor", + "members": [ + "serviceAccount:162922847862@cloudservices.gserviceaccount.com", + "serviceAccount:sa-noperms@coastal-stone-470308-a0.iam.gserviceaccount.com", + "serviceAccount:162922847862-compute@developer.gserviceaccount.com" + ] + }, + { + "role": "roles/owner", + "members": [ + "user:AdityaHindocha3@gmail.com" + ] + } + ] +} \ No newline at end of file diff --git a/networks.json b/networks.json new file mode 100644 index 00000000..5f430dcf --- /dev/null +++ b/networks.json @@ -0,0 +1,60 @@ +[ + { + "kind": "compute#network", + "id": "5399391690813187728", + "creationTimestamp": "2025-08-28T01:51:11.237-07:00", + "name": "default", + "description": "Default network for the project", + "selfLink": "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/global/networks/default", + "selfLinkWithId": "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/global/networks/5399391690813187728", + "autoCreateSubnetworks": true, + "subnetworks": [ + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-north2/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-southeast1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-central2/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/me-west1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west12/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west10/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-northeast3/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-east4/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-east1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-west4/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/africa-south1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/southamerica-east1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-west3/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-southwest1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-west2/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-southeast2/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-northeast1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/australia-southeast1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-northeast2/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/northamerica-northeast1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-north1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-south2/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-south1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west4/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/australia-southeast2/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-east2/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-east1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-south1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/me-central1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-west1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west9/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west8/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-central1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west6/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-east5/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/northamerica-south1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west3/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/northamerica-northeast2/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/southamerica-west1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west2/subnetworks/default" + ], + "routingConfig": { + "routingMode": "REGIONAL", + "bgpBestPathSelectionMode": "LEGACY" + }, + "networkFirewallPolicyEnforcementOrder": "AFTER_CLASSIC_FIREWALL" + } +] \ No newline at end of file From 0e15994b40033a58e5b0e4962d18b1e957768e9a Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Wed, 3 Sep 2025 19:32:43 +1000 Subject: [PATCH 58/63] deleted secrets file --- engine/test-sa-key.json | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 engine/test-sa-key.json diff --git a/engine/test-sa-key.json b/engine/test-sa-key.json deleted file mode 100644 index 09318c45..00000000 --- a/engine/test-sa-key.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "type": "service_account", - "project_id": "coastal-stone-470308-a0", - "private_key_id": "5476e8c2dee74f5e7eea55d98bcc2815b71e44ef", - "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDYPi619VGWmVcg\nPyDYxAM/kyfcZfwWGxy7JWPu7G/MlvTd+A/YdbBwPXzDDDEZ0rsuFfflgS8BYWoo\nwvU3D01fME/jfVHaMc63lI2yzi9HZ/Uchm6jEn/x/vtckz2lW2k1W4woEfhwxHQA\nPYbzH/PFna7rFPhPX3xBmFNT490rfsga08lGj4hRXZevLMiXZmG+YMfvkmojwQbc\n7SZYeGN1quvQrsUkFI77iciR0d6JiUQuboBJ5dEJcmYdwt/FSed1sCafi26zYF6+\nbPlnaqgtQbuodLBMSNxkfT/x+NqwTDq8AC5MumC5ohAlhl0BOapx3R3tbHCvsxdL\noMurT+49AgMBAAECggEAAKc/cOFK28+eycQnD0CYWerR5gKQ3mg6j/4u7Rvdwpp6\nJumG8rp4S/6Dj/tLcq6GTj9WvmTDhZeLwI/GOeJb83ur4h4Qzz3zR+609uNUlTyl\nKu7lCq0Vod+JVuBDAWrjSHv8Umqre3u8dfu5mqZwEBrH2oH3thWtxGz3Y3t+wZDh\nEe3FaAYB5Mn2wW8A2x8lJZJup4TQJ7OLf6lzsf47/UUycJYxd+jzkrw1CvfkwwUn\n3xpQ9k10xLupiI+pNsxSOVobCp5eDGSeENWh9MnfftSLClaQsn1N0VSm4fEIp259\nMRimLd+aqGvcSacWhnVLMps+auKAn6aWQeYNpzOXwQKBgQDsvBrc0av9EqNg+gA6\ngbiMuBZ+4GvYT95YzR2Wgy7WjY1h7XR0bp2VQaaTtTxnK04X+H49ITMAMehWYaxY\nBXYyXdCYrWZIpVHUPxmAQKj+kmALM8/HmtGRkKApByT8UxusLvZCYtEpuKzBPkuX\nmtVW+XxYq/N7kl1f0IaEJbLqiQKBgQDp1yuPoZs/Ob1jckDeFa18LZ9Td0YFhrKV\nOoqTIvQ9YrPkrBs2t4H8t5Xq8A9ZvgO3g0WDAV6u+y82O9YsppG9Rf4TeV/CzyKi\neotW/ZqB6GhSOa3p6lpzYXqNGXst7IUVjT6TUaAfsrZUtFHQVIZjHU1Ye8H/Qo65\ncFuBX8zpFQKBgQCEKDau03Y6H2+Jscby4nwOQq58Qfiyl1O/KzK7VZyONhOZeaAr\nZ50dN7swdlq0FZ7RDu4aXjBEiZf0sS4vLU1grLLIqPSS1Yeq/1bTHEW7aCep2VDD\nU5BuvNhMTyq8mgC2zLi5MsUlj20RrB8zEULL/RcHwWZ5s6ng1V5i41DQUQKBgQCB\npVE6dd/r4uhUrXC3cI9ZzLWMAhHpWG/Eest/nh6JtiKEwsLnyEAiS+qrceMg30+S\nPA6a/nRvUUYwrGYnJUaiCJ9ATse/6zWJnaWJWluCcMb954q7qLnzRHU8q4b2xC5Y\n75Fk/hln2Z5rQfomJebIJuPODfdVvaIBwACLrwCdrQKBgE/cfZ1EhAiXCKi2OrH+\nFJB9De9m2XeW4lY7geQkqQy3z29Rdc4yxEd4W0lmXX25eC2HjEnP11GmqhUK8Osr\n7N40734KPDnkFaQ/Cbxk+7fDSmXbmuOwLOYacw2Nk/DcCnxrSZ0GIUDiFpFSGhHE\ntCsjZmReOVFmI2ZPO8E1YnPS\n-----END PRIVATE KEY-----\n", - "client_email": "sa-noperms@coastal-stone-470308-a0.iam.gserviceaccount.com", - "client_id": "113627683228706962319", - "auth_uri": "https://accounts.google.com/o/oauth2/auth", - "token_uri": "https://oauth2.googleapis.com/token", - "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", - "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/sa-noperms%40coastal-stone-470308-a0.iam.gserviceaccount.com", - "universe_domain": "googleapis.com" -} From a06a0b82fa5764c4468e0a7e4ade9c5f1ece9077 Mon Sep 17 00:00:00 2001 From: Aditya Hindocha Date: Wed, 3 Sep 2025 19:33:54 +1000 Subject: [PATCH 59/63] testing collector --- engine/huh.py | 37 ------------------------------- networks.json | 60 --------------------------------------------------- 2 files changed, 97 deletions(-) delete mode 100644 engine/huh.py delete mode 100644 networks.json diff --git a/engine/huh.py b/engine/huh.py deleted file mode 100644 index 4e41ff71..00000000 --- a/engine/huh.py +++ /dev/null @@ -1,37 +0,0 @@ -from google.oauth2 import service_account -from googleapiclient.discovery import build -from google.auth import default -import json -import os - -KEY_PATH = "engine/test-sa-key.json" - -creds = service_account.Credentials.from_service_account_file( - KEY_PATH, - scopes=["https://www.googleapis.com/auth/cloud-platform"], -) - -crm_policy = build("cloudresourcemanager", "v3", credentials=creds) -crm_compute = build("compute", "v1", credentials=creds) - -project_id = "coastal-stone-470308-a0" -res_name = f"projects/{project_id}" - -policy = crm_policy.projects().getIamPolicy( - resource=res_name, - body={"options": {"requestedPolicyVersion": 3}} -).execute() - -networks = [] -req = crm_compute.networks().list(project=project_id) -while req is not None: - resp = req.execute() - networks.extend(resp.get("items", [])) - req = crm_compute.networks().list_next(previous_request=req, previous_response=resp) - -with open("iam_policy.json", "w") as f: - json.dump(policy, f, indent=2) - -with open("networks.json", "w") as f: - json.dump(networks, f, indent=2) - diff --git a/networks.json b/networks.json deleted file mode 100644 index 5f430dcf..00000000 --- a/networks.json +++ /dev/null @@ -1,60 +0,0 @@ -[ - { - "kind": "compute#network", - "id": "5399391690813187728", - "creationTimestamp": "2025-08-28T01:51:11.237-07:00", - "name": "default", - "description": "Default network for the project", - "selfLink": "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/global/networks/default", - "selfLinkWithId": "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/global/networks/5399391690813187728", - "autoCreateSubnetworks": true, - "subnetworks": [ - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-north2/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-southeast1/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-central2/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/me-west1/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west12/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west10/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-northeast3/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west1/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-east4/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-east1/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-west4/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/africa-south1/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/southamerica-east1/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-west3/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-southwest1/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-west2/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-southeast2/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-northeast1/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/australia-southeast1/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-northeast2/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/northamerica-northeast1/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-north1/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-south2/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-south1/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west4/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/australia-southeast2/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-east2/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-east1/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-south1/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/me-central1/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-west1/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west9/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west8/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-central1/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west6/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-east5/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/northamerica-south1/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west3/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/northamerica-northeast2/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/southamerica-west1/subnetworks/default", - "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west2/subnetworks/default" - ], - "routingConfig": { - "routingMode": "REGIONAL", - "bgpBestPathSelectionMode": "LEGACY" - }, - "networkFirewallPolicyEnforcementOrder": "AFTER_CLASSIC_FIREWALL" - } -] \ No newline at end of file From ea5264dad7d0650e7ea3b95a07c37a4c1f00c4c2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 3 Sep 2025 09:37:49 +0000 Subject: [PATCH 60/63] Update iam_policy.json & networks.json --- test-configs/networks.json | 60 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 test-configs/networks.json diff --git a/test-configs/networks.json b/test-configs/networks.json new file mode 100644 index 00000000..5f430dcf --- /dev/null +++ b/test-configs/networks.json @@ -0,0 +1,60 @@ +[ + { + "kind": "compute#network", + "id": "5399391690813187728", + "creationTimestamp": "2025-08-28T01:51:11.237-07:00", + "name": "default", + "description": "Default network for the project", + "selfLink": "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/global/networks/default", + "selfLinkWithId": "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/global/networks/5399391690813187728", + "autoCreateSubnetworks": true, + "subnetworks": [ + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-north2/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-southeast1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-central2/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/me-west1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west12/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west10/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-northeast3/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-east4/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-east1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-west4/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/africa-south1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/southamerica-east1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-west3/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-southwest1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-west2/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-southeast2/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-northeast1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/australia-southeast1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-northeast2/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/northamerica-northeast1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-north1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-south2/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-south1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west4/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/australia-southeast2/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-east2/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-east1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/asia-south1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/me-central1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-west1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west9/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west8/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-central1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west6/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/us-east5/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/northamerica-south1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west3/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/northamerica-northeast2/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/southamerica-west1/subnetworks/default", + "https://www.googleapis.com/compute/v1/projects/coastal-stone-470308-a0/regions/europe-west2/subnetworks/default" + ], + "routingConfig": { + "routingMode": "REGIONAL", + "bgpBestPathSelectionMode": "LEGACY" + }, + "networkFirewallPolicyEnforcementOrder": "AFTER_CLASSIC_FIREWALL" + } +] \ No newline at end of file From 19af3467e176f55e823a0d47297a7ba3d3c94357 Mon Sep 17 00:00:00 2001 From: 223159756 <139199818+223159756@users.noreply.github.com> Date: Wed, 3 Sep 2025 20:11:27 +1000 Subject: [PATCH 61/63] Replaced Service Account Key --- engine/.trigger | 1 + 1 file changed, 1 insertion(+) diff --git a/engine/.trigger b/engine/.trigger index 6183eec9..53526546 100644 --- a/engine/.trigger +++ b/engine/.trigger @@ -1 +1,2 @@ abcdaas +a From 5c9441585695cd4cd10eb104b2b4a3219e2658bb Mon Sep 17 00:00:00 2001 From: dig Date: Thu, 4 Sep 2025 12:58:50 +1000 Subject: [PATCH 62/63] monorepo merge (engine) 2 --- {engine => engine-preserve}/.DS_Store | Bin {engine => engine-preserve}/.gitignore | 0 {engine => engine-preserve}/README.md | 0 .../cloudbuild-engine-docker.yml | 0 .../docker/engine.Dockerfile | 0 {engine => engine-preserve}/engine/.trigger | 0 {engine => engine-preserve}/engine/.trigger2 | 0 {engine => engine-preserve}/engine/main.py | 0 {engine => engine-preserve}/py_test.py | 0 {engine => engine-preserve}/rules/1.1.1.json | 0 {engine => engine-preserve}/rules/1.1.2.json | 0 {engine => engine-preserve}/rules/1.1.3.json | 0 {engine => engine-preserve}/rules/1.1.4.json | 0 {engine => engine-preserve}/rules/1.2.1.json | 0 {engine => engine-preserve}/rules/1.2.2.json | 0 {engine => engine-preserve}/rules/1.3.1.json | 0 {engine => engine-preserve}/rules/1.3.2.json | 0 {engine => engine-preserve}/rules/1.3.3.json | 0 {engine => engine-preserve}/rules/1.3.4.json | 0 {engine => engine-preserve}/rules/1.3.5.json | 0 {engine => engine-preserve}/rules/1.3.6.json | 0 {engine => engine-preserve}/rules/1.3.7.json | 0 {engine => engine-preserve}/rules/1.3.8.json | 0 .../test-configs/compliant.json | 0 24 files changed, 0 insertions(+), 0 deletions(-) rename {engine => engine-preserve}/.DS_Store (100%) rename {engine => engine-preserve}/.gitignore (100%) rename {engine => engine-preserve}/README.md (100%) rename {engine => engine-preserve}/cloudbuild-engine-docker.yml (100%) rename {engine => engine-preserve}/docker/engine.Dockerfile (100%) rename {engine => engine-preserve}/engine/.trigger (100%) rename {engine => engine-preserve}/engine/.trigger2 (100%) rename {engine => engine-preserve}/engine/main.py (100%) rename {engine => engine-preserve}/py_test.py (100%) rename {engine => engine-preserve}/rules/1.1.1.json (100%) rename {engine => engine-preserve}/rules/1.1.2.json (100%) rename {engine => engine-preserve}/rules/1.1.3.json (100%) rename {engine => engine-preserve}/rules/1.1.4.json (100%) rename {engine => engine-preserve}/rules/1.2.1.json (100%) rename {engine => engine-preserve}/rules/1.2.2.json (100%) rename {engine => engine-preserve}/rules/1.3.1.json (100%) rename {engine => engine-preserve}/rules/1.3.2.json (100%) rename {engine => engine-preserve}/rules/1.3.3.json (100%) rename {engine => engine-preserve}/rules/1.3.4.json (100%) rename {engine => engine-preserve}/rules/1.3.5.json (100%) rename {engine => engine-preserve}/rules/1.3.6.json (100%) rename {engine => engine-preserve}/rules/1.3.7.json (100%) rename {engine => engine-preserve}/rules/1.3.8.json (100%) rename {engine => engine-preserve}/test-configs/compliant.json (100%) diff --git a/engine/.DS_Store b/engine-preserve/.DS_Store similarity index 100% rename from engine/.DS_Store rename to engine-preserve/.DS_Store diff --git a/engine/.gitignore b/engine-preserve/.gitignore similarity index 100% rename from engine/.gitignore rename to engine-preserve/.gitignore diff --git a/engine/README.md b/engine-preserve/README.md similarity index 100% rename from engine/README.md rename to engine-preserve/README.md diff --git a/engine/cloudbuild-engine-docker.yml b/engine-preserve/cloudbuild-engine-docker.yml similarity index 100% rename from engine/cloudbuild-engine-docker.yml rename to engine-preserve/cloudbuild-engine-docker.yml diff --git a/engine/docker/engine.Dockerfile b/engine-preserve/docker/engine.Dockerfile similarity index 100% rename from engine/docker/engine.Dockerfile rename to engine-preserve/docker/engine.Dockerfile diff --git a/engine/engine/.trigger b/engine-preserve/engine/.trigger similarity index 100% rename from engine/engine/.trigger rename to engine-preserve/engine/.trigger diff --git a/engine/engine/.trigger2 b/engine-preserve/engine/.trigger2 similarity index 100% rename from engine/engine/.trigger2 rename to engine-preserve/engine/.trigger2 diff --git a/engine/engine/main.py b/engine-preserve/engine/main.py similarity index 100% rename from engine/engine/main.py rename to engine-preserve/engine/main.py diff --git a/engine/py_test.py b/engine-preserve/py_test.py similarity index 100% rename from engine/py_test.py rename to engine-preserve/py_test.py diff --git a/engine/rules/1.1.1.json b/engine-preserve/rules/1.1.1.json similarity index 100% rename from engine/rules/1.1.1.json rename to engine-preserve/rules/1.1.1.json diff --git a/engine/rules/1.1.2.json b/engine-preserve/rules/1.1.2.json similarity index 100% rename from engine/rules/1.1.2.json rename to engine-preserve/rules/1.1.2.json diff --git a/engine/rules/1.1.3.json b/engine-preserve/rules/1.1.3.json similarity index 100% rename from engine/rules/1.1.3.json rename to engine-preserve/rules/1.1.3.json diff --git a/engine/rules/1.1.4.json b/engine-preserve/rules/1.1.4.json similarity index 100% rename from engine/rules/1.1.4.json rename to engine-preserve/rules/1.1.4.json diff --git a/engine/rules/1.2.1.json b/engine-preserve/rules/1.2.1.json similarity index 100% rename from engine/rules/1.2.1.json rename to engine-preserve/rules/1.2.1.json diff --git a/engine/rules/1.2.2.json b/engine-preserve/rules/1.2.2.json similarity index 100% rename from engine/rules/1.2.2.json rename to engine-preserve/rules/1.2.2.json diff --git a/engine/rules/1.3.1.json b/engine-preserve/rules/1.3.1.json similarity index 100% rename from engine/rules/1.3.1.json rename to engine-preserve/rules/1.3.1.json diff --git a/engine/rules/1.3.2.json b/engine-preserve/rules/1.3.2.json similarity index 100% rename from engine/rules/1.3.2.json rename to engine-preserve/rules/1.3.2.json diff --git a/engine/rules/1.3.3.json b/engine-preserve/rules/1.3.3.json similarity index 100% rename from engine/rules/1.3.3.json rename to engine-preserve/rules/1.3.3.json diff --git a/engine/rules/1.3.4.json b/engine-preserve/rules/1.3.4.json similarity index 100% rename from engine/rules/1.3.4.json rename to engine-preserve/rules/1.3.4.json diff --git a/engine/rules/1.3.5.json b/engine-preserve/rules/1.3.5.json similarity index 100% rename from engine/rules/1.3.5.json rename to engine-preserve/rules/1.3.5.json diff --git a/engine/rules/1.3.6.json b/engine-preserve/rules/1.3.6.json similarity index 100% rename from engine/rules/1.3.6.json rename to engine-preserve/rules/1.3.6.json diff --git a/engine/rules/1.3.7.json b/engine-preserve/rules/1.3.7.json similarity index 100% rename from engine/rules/1.3.7.json rename to engine-preserve/rules/1.3.7.json diff --git a/engine/rules/1.3.8.json b/engine-preserve/rules/1.3.8.json similarity index 100% rename from engine/rules/1.3.8.json rename to engine-preserve/rules/1.3.8.json diff --git a/engine/test-configs/compliant.json b/engine-preserve/test-configs/compliant.json similarity index 100% rename from engine/test-configs/compliant.json rename to engine-preserve/test-configs/compliant.json From ea0bff77ab62c728f768141e9bd086e71f029bd1 Mon Sep 17 00:00:00 2001 From: dig Date: Thu, 4 Sep 2025 13:04:24 +1000 Subject: [PATCH 63/63] monorepo merge (engine) 3 --- .github/workflows/engine-ci.yml | 27 ----- engine-preserve/.DS_Store | Bin 6148 -> 0 bytes engine-preserve/.gitignore | 0 engine-preserve/README.md | 1 - engine-preserve/cloudbuild-engine-docker.yml | 31 ------ engine-preserve/docker/engine.Dockerfile | 9 -- engine-preserve/engine/.trigger | 1 - engine-preserve/engine/main.py | 95 ------------------ engine-preserve/py_test.py | 9 -- engine-preserve/rules/1.1.1.json | 20 ---- engine-preserve/rules/1.1.2.json | 20 ---- engine-preserve/rules/1.1.3.json | 19 ---- engine-preserve/rules/1.1.4.json | 20 ---- engine-preserve/rules/1.2.1.json | 20 ---- engine-preserve/rules/1.2.2.json | 20 ---- engine-preserve/rules/1.3.1.json | 20 ---- engine-preserve/rules/1.3.2.json | 20 ---- engine-preserve/rules/1.3.3.json | 20 ---- engine-preserve/rules/1.3.4.json | 20 ---- engine-preserve/rules/1.3.5.json | 20 ---- engine-preserve/rules/1.3.6.json | 20 ---- engine-preserve/rules/1.3.7.json | 20 ---- engine-preserve/rules/1.3.8.json | 20 ---- engine-preserve/test-configs/compliant.json | 9 -- .DS_Store => engine/.DS_Store | Bin .gitignore => engine/.gitignore | 0 engine/.trigger2 | 1 - README.md => engine/README.md | 0 {docker => engine/docker}/engine.Dockerfile | 0 engine/{ => engine}/.trigger | 0 {engine-preserve => engine}/engine/.trigger2 | 0 engine/{ => engine}/GCPAccess.py | 0 engine/{ => engine}/Helpers.rego | 0 engine/{ => engine}/main.py | 0 iam_policy.json => engine/iam_policy.json | 0 {rules => engine/rules}/1.1.1.json | 0 {rules => engine/rules}/1.1.2.json | 0 {rules => engine/rules}/1.1.3.json | 0 {rules => engine/rules}/1.1.4.json | 0 {rules => engine/rules}/1.2.1.json | 0 {rules => engine/rules}/1.2.2.json | 0 {rules => engine/rules}/1.3.1.json | 0 {rules => engine/rules}/1.3.2.json | 0 {rules => engine/rules}/1.3.3.json | 0 {rules => engine/rules}/1.3.4.json | 0 {rules => engine/rules}/1.3.5.json | 0 {rules => engine/rules}/1.3.6.json | 0 {rules => engine/rules}/1.3.7.json | 0 {rules => engine/rules}/1.3.8.json | 0 {rules => engine/rules}/2.1.1.json | 0 {rules => engine/rules}/2.1.10.json | 0 {rules => engine/rules}/2.1.11.json | 0 {rules => engine/rules}/2.1.12.json | 0 {rules => engine/rules}/2.1.13.json | 0 {rules => engine/rules}/2.1.14.json | 0 {rules => engine/rules}/2.1.2.json | 0 {rules => engine/rules}/2.1.3.json | 0 {rules => engine/rules}/2.1.4.json | 0 {rules => engine/rules}/2.1.5.json | 0 {rules => engine/rules}/2.1.6.json | 0 {rules => engine/rules}/2.1.7.json | 0 {rules => engine/rules}/2.1.8.json | 0 {rules => engine/rules}/2.1.9.json | 0 {rules => engine/rules}/2.2.1.json | 0 {rules => engine/rules}/2.4.1.json | 0 {rules => engine/rules}/2.4.2.json | 0 {rules => engine/rules}/2.4.3.json | 0 {rules => engine/rules}/2.4.4.json | 0 {rules => engine/rules}/3.1.1.json | 0 {rules => engine/rules}/3.2.1.json | 0 {rules => engine/rules}/3.2.2.json | 0 {rules => engine/rules}/3.3.1.json | 0 {rules => engine/rules}/5.1.1.json | 0 {rules => engine/rules}/5.1.2.json | 0 {rules => engine/rules}/5.1.3.json | 0 {rules => engine/rules}/5.1.4.json | 0 {rules => engine/rules}/5.1.5.json | 0 {rules => engine/rules}/5.1.6.json | 0 {rules => engine/rules}/5.1.7.json | 0 {rules => engine/rules}/5.1.8.json | 0 {rules => engine/rules}/5.2.1.json | 0 {rules => engine/rules}/5.2.2.3.json | 0 {rules => engine/rules}/5.2.2.json | 0 {rules => engine/rules}/5.2.3.json | 0 {rules => engine/rules}/5.2.4.json | 0 {rules => engine/rules}/5.3.1.json | 0 {rules => engine/rules}/5.3.2.json | 0 {rules => engine/rules}/5.3.3.json | 0 {rules => engine/rules}/5.3.4.json | 0 {rules => engine/rules}/5.3.5.json | 0 {rules => engine/rules}/6.1.1.json | 0 {rules => engine/rules}/6.1.2.json | 0 {rules => engine/rules}/6.1.3.json | 0 {rules => engine/rules}/6.2.1.json | 0 {rules => engine/rules}/6.2.2.json | 0 {rules => engine/rules}/6.2.3.json | 0 {rules => engine/rules}/6.3.1.json | 0 {rules => engine/rules}/6.5.1.json | 0 {rules => engine/rules}/6.5.2.json | 0 {rules => engine/rules}/6.5.3.json | 0 {rules => engine/rules}/6.5.4.json | 0 {rules => engine/rules}/7.2.1.json | 0 {rules => engine/rules}/7.2.10.json | 0 {rules => engine/rules}/7.2.11.json | 0 {rules => engine/rules}/7.2.2.json | 0 {rules => engine/rules}/7.2.3.json | 0 {rules => engine/rules}/7.2.4.json | 0 {rules => engine/rules}/7.2.5.json | 0 {rules => engine/rules}/7.2.6.json | 0 {rules => engine/rules}/7.2.7.json | 0 {rules => engine/rules}/7.2.8.json | 0 {rules => engine/rules}/7.2.9.json | 0 {rules => engine/rules}/7.3.1.json | 0 {rules => engine/rules}/7.3.2.json | 0 {rules => engine/rules}/7.3.3.json | 0 {rules => engine/rules}/7.3.4.json | 0 {rules => engine/rules}/8.1.1.json | 0 {rules => engine/rules}/8.1.2.json | 0 {rules => engine/rules}/8.2.1.json | 0 {rules => engine/rules}/8.2.2.json | 0 {rules => engine/rules}/8.2.3.json | 0 {rules => engine/rules}/8.2.4.json | 0 {rules => engine/rules}/8.4.1.json | 0 {rules => engine/rules}/8.5.1.json | 0 {rules => engine/rules}/8.5.2.json | 0 {rules => engine/rules}/8.5.3.json | 0 {rules => engine/rules}/8.5.4.json | 0 {rules => engine/rules}/8.5.5.json | 0 {rules => engine/rules}/8.5.6.json | 0 {rules => engine/rules}/8.5.7.json | 0 {rules => engine/rules}/8.5.8.json | 0 {rules => engine/rules}/8.5.9.json | 0 {rules => engine/rules}/8.6.1.json | 0 {rules => engine/rules}/9.1.1.json | 0 {rules => engine/rules}/9.1.10.json | 0 {rules => engine/rules}/9.1.11.json | 0 {rules => engine/rules}/9.1.2.json | 0 {rules => engine/rules}/9.1.3.json | 0 {rules => engine/rules}/9.1.4.json | 0 {rules => engine/rules}/9.1.5.json | 0 {rules => engine/rules}/9.1.6.json | 0 {rules => engine/rules}/9.1.7.json | 0 {rules => engine/rules}/9.1.8.json | 0 {rules => engine/rules}/9.1.9.json | 0 {rules => engine/rules}/CIS_GCP_1_5.rego | 0 .../test-configs}/compliant.json | 0 .../test-configs}/iam_policy.json | 0 .../test-configs}/networks.json | 0 148 files changed, 462 deletions(-) delete mode 100644 .github/workflows/engine-ci.yml delete mode 100644 engine-preserve/.DS_Store delete mode 100644 engine-preserve/.gitignore delete mode 100644 engine-preserve/README.md delete mode 100644 engine-preserve/cloudbuild-engine-docker.yml delete mode 100644 engine-preserve/docker/engine.Dockerfile delete mode 100644 engine-preserve/engine/.trigger delete mode 100644 engine-preserve/engine/main.py delete mode 100644 engine-preserve/py_test.py delete mode 100644 engine-preserve/rules/1.1.1.json delete mode 100644 engine-preserve/rules/1.1.2.json delete mode 100644 engine-preserve/rules/1.1.3.json delete mode 100644 engine-preserve/rules/1.1.4.json delete mode 100644 engine-preserve/rules/1.2.1.json delete mode 100644 engine-preserve/rules/1.2.2.json delete mode 100644 engine-preserve/rules/1.3.1.json delete mode 100644 engine-preserve/rules/1.3.2.json delete mode 100644 engine-preserve/rules/1.3.3.json delete mode 100644 engine-preserve/rules/1.3.4.json delete mode 100644 engine-preserve/rules/1.3.5.json delete mode 100644 engine-preserve/rules/1.3.6.json delete mode 100644 engine-preserve/rules/1.3.7.json delete mode 100644 engine-preserve/rules/1.3.8.json delete mode 100644 engine-preserve/test-configs/compliant.json rename .DS_Store => engine/.DS_Store (100%) rename .gitignore => engine/.gitignore (100%) delete mode 100644 engine/.trigger2 rename README.md => engine/README.md (100%) rename {docker => engine/docker}/engine.Dockerfile (100%) rename engine/{ => engine}/.trigger (100%) rename {engine-preserve => engine}/engine/.trigger2 (100%) rename engine/{ => engine}/GCPAccess.py (100%) rename engine/{ => engine}/Helpers.rego (100%) rename engine/{ => engine}/main.py (100%) rename iam_policy.json => engine/iam_policy.json (100%) rename {rules => engine/rules}/1.1.1.json (100%) rename {rules => engine/rules}/1.1.2.json (100%) rename {rules => engine/rules}/1.1.3.json (100%) rename {rules => engine/rules}/1.1.4.json (100%) rename {rules => engine/rules}/1.2.1.json (100%) rename {rules => engine/rules}/1.2.2.json (100%) rename {rules => engine/rules}/1.3.1.json (100%) rename {rules => engine/rules}/1.3.2.json (100%) rename {rules => engine/rules}/1.3.3.json (100%) rename {rules => engine/rules}/1.3.4.json (100%) rename {rules => engine/rules}/1.3.5.json (100%) rename {rules => engine/rules}/1.3.6.json (100%) rename {rules => engine/rules}/1.3.7.json (100%) rename {rules => engine/rules}/1.3.8.json (100%) rename {rules => engine/rules}/2.1.1.json (100%) rename {rules => engine/rules}/2.1.10.json (100%) rename {rules => engine/rules}/2.1.11.json (100%) rename {rules => engine/rules}/2.1.12.json (100%) rename {rules => engine/rules}/2.1.13.json (100%) rename {rules => engine/rules}/2.1.14.json (100%) rename {rules => engine/rules}/2.1.2.json (100%) rename {rules => engine/rules}/2.1.3.json (100%) rename {rules => engine/rules}/2.1.4.json (100%) rename {rules => engine/rules}/2.1.5.json (100%) rename {rules => engine/rules}/2.1.6.json (100%) rename {rules => engine/rules}/2.1.7.json (100%) rename {rules => engine/rules}/2.1.8.json (100%) rename {rules => engine/rules}/2.1.9.json (100%) rename {rules => engine/rules}/2.2.1.json (100%) rename {rules => engine/rules}/2.4.1.json (100%) rename {rules => engine/rules}/2.4.2.json (100%) rename {rules => engine/rules}/2.4.3.json (100%) rename {rules => engine/rules}/2.4.4.json (100%) rename {rules => engine/rules}/3.1.1.json (100%) rename {rules => engine/rules}/3.2.1.json (100%) rename {rules => engine/rules}/3.2.2.json (100%) rename {rules => engine/rules}/3.3.1.json (100%) rename {rules => engine/rules}/5.1.1.json (100%) rename {rules => engine/rules}/5.1.2.json (100%) rename {rules => engine/rules}/5.1.3.json (100%) rename {rules => engine/rules}/5.1.4.json (100%) rename {rules => engine/rules}/5.1.5.json (100%) rename {rules => engine/rules}/5.1.6.json (100%) rename {rules => engine/rules}/5.1.7.json (100%) rename {rules => engine/rules}/5.1.8.json (100%) rename {rules => engine/rules}/5.2.1.json (100%) rename {rules => engine/rules}/5.2.2.3.json (100%) rename {rules => engine/rules}/5.2.2.json (100%) rename {rules => engine/rules}/5.2.3.json (100%) rename {rules => engine/rules}/5.2.4.json (100%) rename {rules => engine/rules}/5.3.1.json (100%) rename {rules => engine/rules}/5.3.2.json (100%) rename {rules => engine/rules}/5.3.3.json (100%) rename {rules => engine/rules}/5.3.4.json (100%) rename {rules => engine/rules}/5.3.5.json (100%) rename {rules => engine/rules}/6.1.1.json (100%) rename {rules => engine/rules}/6.1.2.json (100%) rename {rules => engine/rules}/6.1.3.json (100%) rename {rules => engine/rules}/6.2.1.json (100%) rename {rules => engine/rules}/6.2.2.json (100%) rename {rules => engine/rules}/6.2.3.json (100%) rename {rules => engine/rules}/6.3.1.json (100%) rename {rules => engine/rules}/6.5.1.json (100%) rename {rules => engine/rules}/6.5.2.json (100%) rename {rules => engine/rules}/6.5.3.json (100%) rename {rules => engine/rules}/6.5.4.json (100%) rename {rules => engine/rules}/7.2.1.json (100%) rename {rules => engine/rules}/7.2.10.json (100%) rename {rules => engine/rules}/7.2.11.json (100%) rename {rules => engine/rules}/7.2.2.json (100%) rename {rules => engine/rules}/7.2.3.json (100%) rename {rules => engine/rules}/7.2.4.json (100%) rename {rules => engine/rules}/7.2.5.json (100%) rename {rules => engine/rules}/7.2.6.json (100%) rename {rules => engine/rules}/7.2.7.json (100%) rename {rules => engine/rules}/7.2.8.json (100%) rename {rules => engine/rules}/7.2.9.json (100%) rename {rules => engine/rules}/7.3.1.json (100%) rename {rules => engine/rules}/7.3.2.json (100%) rename {rules => engine/rules}/7.3.3.json (100%) rename {rules => engine/rules}/7.3.4.json (100%) rename {rules => engine/rules}/8.1.1.json (100%) rename {rules => engine/rules}/8.1.2.json (100%) rename {rules => engine/rules}/8.2.1.json (100%) rename {rules => engine/rules}/8.2.2.json (100%) rename {rules => engine/rules}/8.2.3.json (100%) rename {rules => engine/rules}/8.2.4.json (100%) rename {rules => engine/rules}/8.4.1.json (100%) rename {rules => engine/rules}/8.5.1.json (100%) rename {rules => engine/rules}/8.5.2.json (100%) rename {rules => engine/rules}/8.5.3.json (100%) rename {rules => engine/rules}/8.5.4.json (100%) rename {rules => engine/rules}/8.5.5.json (100%) rename {rules => engine/rules}/8.5.6.json (100%) rename {rules => engine/rules}/8.5.7.json (100%) rename {rules => engine/rules}/8.5.8.json (100%) rename {rules => engine/rules}/8.5.9.json (100%) rename {rules => engine/rules}/8.6.1.json (100%) rename {rules => engine/rules}/9.1.1.json (100%) rename {rules => engine/rules}/9.1.10.json (100%) rename {rules => engine/rules}/9.1.11.json (100%) rename {rules => engine/rules}/9.1.2.json (100%) rename {rules => engine/rules}/9.1.3.json (100%) rename {rules => engine/rules}/9.1.4.json (100%) rename {rules => engine/rules}/9.1.5.json (100%) rename {rules => engine/rules}/9.1.6.json (100%) rename {rules => engine/rules}/9.1.7.json (100%) rename {rules => engine/rules}/9.1.8.json (100%) rename {rules => engine/rules}/9.1.9.json (100%) rename {rules => engine/rules}/CIS_GCP_1_5.rego (100%) rename {test-configs => engine/test-configs}/compliant.json (100%) rename {test-configs => engine/test-configs}/iam_policy.json (100%) rename {test-configs => engine/test-configs}/networks.json (100%) diff --git a/.github/workflows/engine-ci.yml b/.github/workflows/engine-ci.yml deleted file mode 100644 index f31ab4ec..00000000 --- a/.github/workflows/engine-ci.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Build Engine Branch - -on: - push: - branches: [Compliance-Engine] - -jobs: - build-engine-from-devops: - name: Build Engine Code - runs-on: ubuntu-latest - - steps: - - name: Checkout engine branch code - uses: actions/checkout@v3 - with: - ref: Compliance-Engine - - - name: Confirm branch - run: git branch - - - name: Build container - run: | - docker build -t autoaudit/engine -f docker/engine.Dockerfile . - - - name: Run engine container - run: | - docker run --rm autoaudit/engine diff --git a/engine-preserve/.DS_Store b/engine-preserve/.DS_Store deleted file mode 100644 index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 Users > Active Users and Entra admin center > Protection > Conditional Access", - "remediation": "Create two cloud-only accounts with Global Admin role, no license, exclude from Conditional Access rules.", - "risk": "High", - "tags": [ - "Accounts", - "EmergencyAccess", - "GlobalAdmin" - ] -} \ No newline at end of file diff --git a/engine-preserve/rules/1.1.3.json b/engine-preserve/rules/1.1.3.json deleted file mode 100644 index 760c70f8..00000000 --- a/engine-preserve/rules/1.1.3.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "product": "Microsoft 365 admin center", - "id_level_1": 1.1, - "id_level_2": "1.1.3", - "title": "Ensure that between two and four global admins are designated", - "profile": "E3 E5", - "level": "L1", - "status": "Automated", - "description": "Between two and four global administrators should be designated in the tenant to ensure redundancy and limit exposure.", - "expected_value": "2\ufffd4 Global Administrators", - "comparison": "Count and range check", - "evaluation_path": "Microsoft 365 admin center > Roles > Global Administrator", - "remediation": "Add or remove users from Global Admin role to maintain 2\ufffd4 total.", - "risk": "High", - "tags": [ - "AdminAccounts", - "PrivilegeManagement" - ] -} \ No newline at end of file diff --git a/engine-preserve/rules/1.1.4.json b/engine-preserve/rules/1.1.4.json deleted file mode 100644 index f4613824..00000000 --- a/engine-preserve/rules/1.1.4.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "product": "Microsoft 365 admin center", - "id_level_1": 1.1, - "id_level_2": "1.1.4", - "title": "Ensure administrative accounts use licenses with reduced application footprint", - "profile": "E3 E5", - "level": "L1", - "status": "Automated", - "description": "Administrative accounts should not use licenses with applications to reduce attack surface.", - "expected_value": "License with no user applications (e.g. Entra ID P1/P2)", - "comparison": "License check", - "evaluation_path": "Microsoft 365 admin center > Users > Active users > License column", - "remediation": "Assign minimal license or Entra ID P1/P2 to admin accounts. Use PIM if applicable.", - "risk": "Medium", - "tags": [ - "Licensing", - "AdminAccounts", - "LeastPrivilege" - ] -} \ No newline at end of file diff --git a/engine-preserve/rules/1.2.1.json b/engine-preserve/rules/1.2.1.json deleted file mode 100644 index 9a14c94b..00000000 --- a/engine-preserve/rules/1.2.1.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "product": "Microsoft 365 admin center", - "id_level_1": 1.2, - "id_level_2": "1.2.1", - "title": "Ensure that only organizationally managed/approved public groups exist", - "profile": "E3 E5", - "level": "L2", - "status": "Automated", - "description": "Ensure that only organizationally managed and approved public groups exist to prevent unauthorized access to internal data.", - "expected_value": "No groups with public visibility", - "comparison": "Group.Visibility != Public", - "evaluation_path": "Microsoft 365 admin center > Teams & groups > Active teams & groups", - "remediation": "Change group privacy from Public to Private in group settings.", - "risk": "High", - "tags": [ - "Groups", - "Privacy", - "AccessControl" - ] -} \ No newline at end of file diff --git a/engine-preserve/rules/1.2.2.json b/engine-preserve/rules/1.2.2.json deleted file mode 100644 index 1dd967fd..00000000 --- a/engine-preserve/rules/1.2.2.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "product": "Microsoft 365 admin center", - "id_level_1": 1.2, - "id_level_2": "1.2.2", - "title": "Ensure sign-in to shared mailboxes is blocked", - "profile": "E3 E5", - "level": "L1", - "status": "Automated", - "description": "Block sign-in access for shared mailboxes to reduce exposure to unauthorized access.", - "expected_value": "Sign-in disabled for shared mailboxes", - "comparison": "user.AccountEnabled == false", - "evaluation_path": "mailboxes.shared", - "remediation": "Uncheck the 'Sign-in allowed' option under mailbox settings.", - "risk": "Medium", - "tags": [ - "Mailbox", - "AccountAccess", - "Security" - ] -} diff --git a/engine-preserve/rules/1.3.1.json b/engine-preserve/rules/1.3.1.json deleted file mode 100644 index 157dd7b8..00000000 --- a/engine-preserve/rules/1.3.1.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "product": "Microsoft 365 admin center", - "id_level_1": 1.3, - "id_level_2": "1.3.1", - "title": "Ensure the 'Password expiration policy' is set to 'Set passwords to never expire (recommended)'", - "profile": "E3 E5", - "level": "L1", - "status": "Automated", - "description": "Avoid enforcing periodic password changes unless a compromise is suspected.", - "expected_value": "Set passwords to never expire", - "comparison": "PasswordExpiration == Never", - "evaluation_path": "Microsoft 365 admin center > Org Settings > Security & Privacy > Password expiration policy", - "remediation": "Enable the 'Set passwords to never expire' option in org settings.", - "risk": "Medium", - "tags": [ - "PasswordPolicy", - "UserSettings", - "Authentication" - ] -} \ No newline at end of file diff --git a/engine-preserve/rules/1.3.2.json b/engine-preserve/rules/1.3.2.json deleted file mode 100644 index 47303906..00000000 --- a/engine-preserve/rules/1.3.2.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "product": "Microsoft 365 admin center", - "id_level_1": 1.3, - "id_level_2": "1.3.2", - "title": "Ensure 'Idle session timeout' is set to '3 hours (or less)' for unmanaged devices", - "profile": "E3 E5", - "level": "L2", - "status": "Automated", - "description": "Limit idle session timeout for unmanaged devices to reduce session hijack risks.", - "expected_value": "Idle timeout set to = 3 hours", - "comparison": "IdleTimeout <= 3h", - "evaluation_path": "Microsoft 365 admin center > Org settings > Security & privacy > Idle session timeout", - "remediation": "Configure timeout policy in settings for unmanaged device sessions.", - "risk": "High", - "tags": [ - "SessionTimeout", - "DeviceManagement", - "UnmanagedAccess" - ] -} \ No newline at end of file diff --git a/engine-preserve/rules/1.3.3.json b/engine-preserve/rules/1.3.3.json deleted file mode 100644 index 22e57b74..00000000 --- a/engine-preserve/rules/1.3.3.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "product": "Microsoft 365 admin center", - "id_level_1": 1.3, - "id_level_2": "1.3.3", - "title": "Ensure 'External sharing' of calendars is not available", - "profile": "E3 E5", - "level": "L2", - "status": "Automated", - "description": "Prevent external calendar sharing to avoid data leakage and preserve internal privacy.", - "expected_value": "External sharing disabled", - "comparison": "CalendarSharing == InternalOnly", - "evaluation_path": "Microsoft 365 admin center > Settings > Org settings > Calendar", - "remediation": "Disable external calendar sharing in org settings.", - "risk": "High", - "tags": [ - "Calendar", - "ExternalSharing", - "Privacy" - ] -} \ No newline at end of file diff --git a/engine-preserve/rules/1.3.4.json b/engine-preserve/rules/1.3.4.json deleted file mode 100644 index 46a887f0..00000000 --- a/engine-preserve/rules/1.3.4.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "product": "Microsoft 365 admin center", - "id_level_1": 1.3, - "id_level_2": "1.3.4", - "title": "Ensure 'User owned apps and services' is restricted", - "profile": "E3 E5", - "level": "L1", - "status": "Automated", - "description": "Restrict user ability to register applications to control third-party integrations.", - "expected_value": "App registration disabled for users", - "comparison": "AppRegistration == Disabled", - "evaluation_path": "Microsoft Entra admin center > User settings > App registrations", - "remediation": "Disable 'Users can register applications' in user settings.", - "risk": "Medium", - "tags": [ - "UserApps", - "ThirdPartyAccess", - "AppRegistration" - ] -} \ No newline at end of file diff --git a/engine-preserve/rules/1.3.5.json b/engine-preserve/rules/1.3.5.json deleted file mode 100644 index 2c3cff99..00000000 --- a/engine-preserve/rules/1.3.5.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "product": "Microsoft 365 admin center", - "id_level_1": 1.3, - "id_level_2": "1.3.5", - "title": "Ensure internal phishing protection for Forms is enabled", - "profile": "E3 E5", - "level": "L1", - "status": "Automated", - "description": "Enable internal phishing detection for Microsoft Forms to prevent credential harvesting.", - "expected_value": "Phishing protection enabled", - "comparison": "FormsPhishingProtection == On", - "evaluation_path": "Microsoft 365 admin center > Settings > Org settings > Microsoft Forms", - "remediation": "Enable internal phishing protection in Microsoft Forms settings.", - "risk": "Medium", - "tags": [ - "Forms", - "PhishingProtection", - "ThreatDetection" - ] -} \ No newline at end of file diff --git a/engine-preserve/rules/1.3.6.json b/engine-preserve/rules/1.3.6.json deleted file mode 100644 index 1c4af230..00000000 --- a/engine-preserve/rules/1.3.6.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "product": "Microsoft 365 admin center", - "id_level_1": 1.3, - "id_level_2": "1.3.6", - "title": "Ensure the customer lockbox feature is enabled", - "profile": "E5", - "level": "L2", - "status": "Automated", - "description": "Require explicit customer approval before Microsoft can access customer content.", - "expected_value": "Customer lockbox enabled", - "comparison": "Lockbox == Enabled", - "evaluation_path": "Microsoft 365 compliance center > Solutions > Customer Lockbox", - "remediation": "Enable Customer Lockbox via Microsoft 365 compliance center.", - "risk": "High", - "tags": [ - "CustomerLockbox", - "AccessControl", - "DataProtection" - ] -} \ No newline at end of file diff --git a/engine-preserve/rules/1.3.7.json b/engine-preserve/rules/1.3.7.json deleted file mode 100644 index 21657916..00000000 --- a/engine-preserve/rules/1.3.7.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "product": "Microsoft 365 admin center", - "id_level_1": 1.3, - "id_level_2": "1.3.7", - "title": "Ensure 'third-party storage services' are restricted in 'Microsoft 365 on the web'", - "profile": "E3 E5", - "level": "L2", - "status": "Automated", - "description": "Restrict access to third-party storage services like Dropbox or Google Drive to protect data.", - "expected_value": "Third-party storage access disabled", - "comparison": "ThirdPartyStorage == Disabled", - "evaluation_path": "office.ThirdPartyStorage", - "remediation": "Disable integration with third-party storage services.", - "risk": "High", - "tags": [ - "Storage", - "ExternalServices", - "DataControl" - ] -} diff --git a/engine-preserve/rules/1.3.8.json b/engine-preserve/rules/1.3.8.json deleted file mode 100644 index 5553c9f6..00000000 --- a/engine-preserve/rules/1.3.8.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "product": "Microsoft 365 admin center", - "id_level_1": 1.3, - "id_level_2": "1.3.8", - "title": "Ensure that Sways cannot be shared with people outside of your organization", - "profile": "E3 E5", - "level": "L2", - "status": "Manual", - "description": "Prevent sharing of Microsoft Sway content outside the organization to maintain internal content privacy.", - "expected_value": "External sharing disabled for Sways", - "comparison": "SwaySharing == InternalOnly", - "evaluation_path": "sway.externalSharing", - "remediation": "Manually disable external sharing for Sway presentations.", - "risk": "Medium", - "tags": [ - "Sway", - "ContentSharing", - "ExternalAccess" - ] -} diff --git a/engine-preserve/test-configs/compliant.json b/engine-preserve/test-configs/compliant.json deleted file mode 100644 index b4d27026..00000000 --- a/engine-preserve/test-configs/compliant.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "azure_ad": { - "mfa_status": "enabled", - "legacy_authentication": "disabled" - }, - "microsoft_forms": { - "phishing_protection": "enabled" - } -} \ No newline at end of file diff --git a/.DS_Store b/engine/.DS_Store similarity index 100% rename from .DS_Store rename to engine/.DS_Store diff --git a/.gitignore b/engine/.gitignore similarity index 100% rename from .gitignore rename to engine/.gitignore diff --git a/engine/.trigger2 b/engine/.trigger2 deleted file mode 100644 index 7c4a013e..00000000 --- a/engine/.trigger2 +++ /dev/null @@ -1 +0,0 @@ -aaa \ No newline at end of file diff --git a/README.md b/engine/README.md similarity index 100% rename from README.md rename to engine/README.md diff --git a/docker/engine.Dockerfile b/engine/docker/engine.Dockerfile similarity index 100% rename from docker/engine.Dockerfile rename to engine/docker/engine.Dockerfile diff --git a/engine/.trigger b/engine/engine/.trigger similarity index 100% rename from engine/.trigger rename to engine/engine/.trigger diff --git a/engine-preserve/engine/.trigger2 b/engine/engine/.trigger2 similarity index 100% rename from engine-preserve/engine/.trigger2 rename to engine/engine/.trigger2 diff --git a/engine/GCPAccess.py b/engine/engine/GCPAccess.py similarity index 100% rename from engine/GCPAccess.py rename to engine/engine/GCPAccess.py diff --git a/engine/Helpers.rego b/engine/engine/Helpers.rego similarity index 100% rename from engine/Helpers.rego rename to engine/engine/Helpers.rego diff --git a/engine/main.py b/engine/engine/main.py similarity index 100% rename from engine/main.py rename to engine/engine/main.py diff --git a/iam_policy.json b/engine/iam_policy.json similarity index 100% rename from iam_policy.json rename to engine/iam_policy.json diff --git a/rules/1.1.1.json b/engine/rules/1.1.1.json similarity index 100% rename from rules/1.1.1.json rename to engine/rules/1.1.1.json diff --git a/rules/1.1.2.json b/engine/rules/1.1.2.json similarity index 100% rename from rules/1.1.2.json rename to engine/rules/1.1.2.json diff --git a/rules/1.1.3.json b/engine/rules/1.1.3.json similarity index 100% rename from rules/1.1.3.json rename to engine/rules/1.1.3.json diff --git a/rules/1.1.4.json b/engine/rules/1.1.4.json similarity index 100% rename from rules/1.1.4.json rename to engine/rules/1.1.4.json diff --git a/rules/1.2.1.json b/engine/rules/1.2.1.json similarity index 100% rename from rules/1.2.1.json rename to engine/rules/1.2.1.json diff --git a/rules/1.2.2.json b/engine/rules/1.2.2.json similarity index 100% rename from rules/1.2.2.json rename to engine/rules/1.2.2.json diff --git a/rules/1.3.1.json b/engine/rules/1.3.1.json similarity index 100% rename from rules/1.3.1.json rename to engine/rules/1.3.1.json diff --git a/rules/1.3.2.json b/engine/rules/1.3.2.json similarity index 100% rename from rules/1.3.2.json rename to engine/rules/1.3.2.json diff --git a/rules/1.3.3.json b/engine/rules/1.3.3.json similarity index 100% rename from rules/1.3.3.json rename to engine/rules/1.3.3.json diff --git a/rules/1.3.4.json b/engine/rules/1.3.4.json similarity index 100% rename from rules/1.3.4.json rename to engine/rules/1.3.4.json diff --git a/rules/1.3.5.json b/engine/rules/1.3.5.json similarity index 100% rename from rules/1.3.5.json rename to engine/rules/1.3.5.json diff --git a/rules/1.3.6.json b/engine/rules/1.3.6.json similarity index 100% rename from rules/1.3.6.json rename to engine/rules/1.3.6.json diff --git a/rules/1.3.7.json b/engine/rules/1.3.7.json similarity index 100% rename from rules/1.3.7.json rename to engine/rules/1.3.7.json diff --git a/rules/1.3.8.json b/engine/rules/1.3.8.json similarity index 100% rename from rules/1.3.8.json rename to engine/rules/1.3.8.json diff --git a/rules/2.1.1.json b/engine/rules/2.1.1.json similarity index 100% rename from rules/2.1.1.json rename to engine/rules/2.1.1.json diff --git a/rules/2.1.10.json b/engine/rules/2.1.10.json similarity index 100% rename from rules/2.1.10.json rename to engine/rules/2.1.10.json diff --git a/rules/2.1.11.json b/engine/rules/2.1.11.json similarity index 100% rename from rules/2.1.11.json rename to engine/rules/2.1.11.json diff --git a/rules/2.1.12.json b/engine/rules/2.1.12.json similarity index 100% rename from rules/2.1.12.json rename to engine/rules/2.1.12.json diff --git a/rules/2.1.13.json b/engine/rules/2.1.13.json similarity index 100% rename from rules/2.1.13.json rename to engine/rules/2.1.13.json diff --git a/rules/2.1.14.json b/engine/rules/2.1.14.json similarity index 100% rename from rules/2.1.14.json rename to engine/rules/2.1.14.json diff --git a/rules/2.1.2.json b/engine/rules/2.1.2.json similarity index 100% rename from rules/2.1.2.json rename to engine/rules/2.1.2.json diff --git a/rules/2.1.3.json b/engine/rules/2.1.3.json similarity index 100% rename from rules/2.1.3.json rename to engine/rules/2.1.3.json diff --git a/rules/2.1.4.json b/engine/rules/2.1.4.json similarity index 100% rename from rules/2.1.4.json rename to engine/rules/2.1.4.json diff --git a/rules/2.1.5.json b/engine/rules/2.1.5.json similarity index 100% rename from rules/2.1.5.json rename to engine/rules/2.1.5.json diff --git a/rules/2.1.6.json b/engine/rules/2.1.6.json similarity index 100% rename from rules/2.1.6.json rename to engine/rules/2.1.6.json diff --git a/rules/2.1.7.json b/engine/rules/2.1.7.json similarity index 100% rename from rules/2.1.7.json rename to engine/rules/2.1.7.json diff --git a/rules/2.1.8.json b/engine/rules/2.1.8.json similarity index 100% rename from rules/2.1.8.json rename to engine/rules/2.1.8.json diff --git a/rules/2.1.9.json b/engine/rules/2.1.9.json similarity index 100% rename from rules/2.1.9.json rename to engine/rules/2.1.9.json diff --git a/rules/2.2.1.json b/engine/rules/2.2.1.json similarity index 100% rename from rules/2.2.1.json rename to engine/rules/2.2.1.json diff --git a/rules/2.4.1.json b/engine/rules/2.4.1.json similarity index 100% rename from rules/2.4.1.json rename to engine/rules/2.4.1.json diff --git a/rules/2.4.2.json b/engine/rules/2.4.2.json similarity index 100% rename from rules/2.4.2.json rename to engine/rules/2.4.2.json diff --git a/rules/2.4.3.json b/engine/rules/2.4.3.json similarity index 100% rename from rules/2.4.3.json rename to engine/rules/2.4.3.json diff --git a/rules/2.4.4.json b/engine/rules/2.4.4.json similarity index 100% rename from rules/2.4.4.json rename to engine/rules/2.4.4.json diff --git a/rules/3.1.1.json b/engine/rules/3.1.1.json similarity index 100% rename from rules/3.1.1.json rename to engine/rules/3.1.1.json diff --git a/rules/3.2.1.json b/engine/rules/3.2.1.json similarity index 100% rename from rules/3.2.1.json rename to engine/rules/3.2.1.json diff --git a/rules/3.2.2.json b/engine/rules/3.2.2.json similarity index 100% rename from rules/3.2.2.json rename to engine/rules/3.2.2.json diff --git a/rules/3.3.1.json b/engine/rules/3.3.1.json similarity index 100% rename from rules/3.3.1.json rename to engine/rules/3.3.1.json diff --git a/rules/5.1.1.json b/engine/rules/5.1.1.json similarity index 100% rename from rules/5.1.1.json rename to engine/rules/5.1.1.json diff --git a/rules/5.1.2.json b/engine/rules/5.1.2.json similarity index 100% rename from rules/5.1.2.json rename to engine/rules/5.1.2.json diff --git a/rules/5.1.3.json b/engine/rules/5.1.3.json similarity index 100% rename from rules/5.1.3.json rename to engine/rules/5.1.3.json diff --git a/rules/5.1.4.json b/engine/rules/5.1.4.json similarity index 100% rename from rules/5.1.4.json rename to engine/rules/5.1.4.json diff --git a/rules/5.1.5.json b/engine/rules/5.1.5.json similarity index 100% rename from rules/5.1.5.json rename to engine/rules/5.1.5.json diff --git a/rules/5.1.6.json b/engine/rules/5.1.6.json similarity index 100% rename from rules/5.1.6.json rename to engine/rules/5.1.6.json diff --git a/rules/5.1.7.json b/engine/rules/5.1.7.json similarity index 100% rename from rules/5.1.7.json rename to engine/rules/5.1.7.json diff --git a/rules/5.1.8.json b/engine/rules/5.1.8.json similarity index 100% rename from rules/5.1.8.json rename to engine/rules/5.1.8.json diff --git a/rules/5.2.1.json b/engine/rules/5.2.1.json similarity index 100% rename from rules/5.2.1.json rename to engine/rules/5.2.1.json diff --git a/rules/5.2.2.3.json b/engine/rules/5.2.2.3.json similarity index 100% rename from rules/5.2.2.3.json rename to engine/rules/5.2.2.3.json diff --git a/rules/5.2.2.json b/engine/rules/5.2.2.json similarity index 100% rename from rules/5.2.2.json rename to engine/rules/5.2.2.json diff --git a/rules/5.2.3.json b/engine/rules/5.2.3.json similarity index 100% rename from rules/5.2.3.json rename to engine/rules/5.2.3.json diff --git a/rules/5.2.4.json b/engine/rules/5.2.4.json similarity index 100% rename from rules/5.2.4.json rename to engine/rules/5.2.4.json diff --git a/rules/5.3.1.json b/engine/rules/5.3.1.json similarity index 100% rename from rules/5.3.1.json rename to engine/rules/5.3.1.json diff --git a/rules/5.3.2.json b/engine/rules/5.3.2.json similarity index 100% rename from rules/5.3.2.json rename to engine/rules/5.3.2.json diff --git a/rules/5.3.3.json b/engine/rules/5.3.3.json similarity index 100% rename from rules/5.3.3.json rename to engine/rules/5.3.3.json diff --git a/rules/5.3.4.json b/engine/rules/5.3.4.json similarity index 100% rename from rules/5.3.4.json rename to engine/rules/5.3.4.json diff --git a/rules/5.3.5.json b/engine/rules/5.3.5.json similarity index 100% rename from rules/5.3.5.json rename to engine/rules/5.3.5.json diff --git a/rules/6.1.1.json b/engine/rules/6.1.1.json similarity index 100% rename from rules/6.1.1.json rename to engine/rules/6.1.1.json diff --git a/rules/6.1.2.json b/engine/rules/6.1.2.json similarity index 100% rename from rules/6.1.2.json rename to engine/rules/6.1.2.json diff --git a/rules/6.1.3.json b/engine/rules/6.1.3.json similarity index 100% rename from rules/6.1.3.json rename to engine/rules/6.1.3.json diff --git a/rules/6.2.1.json b/engine/rules/6.2.1.json similarity index 100% rename from rules/6.2.1.json rename to engine/rules/6.2.1.json diff --git a/rules/6.2.2.json b/engine/rules/6.2.2.json similarity index 100% rename from rules/6.2.2.json rename to engine/rules/6.2.2.json diff --git a/rules/6.2.3.json b/engine/rules/6.2.3.json similarity index 100% rename from rules/6.2.3.json rename to engine/rules/6.2.3.json diff --git a/rules/6.3.1.json b/engine/rules/6.3.1.json similarity index 100% rename from rules/6.3.1.json rename to engine/rules/6.3.1.json diff --git a/rules/6.5.1.json b/engine/rules/6.5.1.json similarity index 100% rename from rules/6.5.1.json rename to engine/rules/6.5.1.json diff --git a/rules/6.5.2.json b/engine/rules/6.5.2.json similarity index 100% rename from rules/6.5.2.json rename to engine/rules/6.5.2.json diff --git a/rules/6.5.3.json b/engine/rules/6.5.3.json similarity index 100% rename from rules/6.5.3.json rename to engine/rules/6.5.3.json diff --git a/rules/6.5.4.json b/engine/rules/6.5.4.json similarity index 100% rename from rules/6.5.4.json rename to engine/rules/6.5.4.json diff --git a/rules/7.2.1.json b/engine/rules/7.2.1.json similarity index 100% rename from rules/7.2.1.json rename to engine/rules/7.2.1.json diff --git a/rules/7.2.10.json b/engine/rules/7.2.10.json similarity index 100% rename from rules/7.2.10.json rename to engine/rules/7.2.10.json diff --git a/rules/7.2.11.json b/engine/rules/7.2.11.json similarity index 100% rename from rules/7.2.11.json rename to engine/rules/7.2.11.json diff --git a/rules/7.2.2.json b/engine/rules/7.2.2.json similarity index 100% rename from rules/7.2.2.json rename to engine/rules/7.2.2.json diff --git a/rules/7.2.3.json b/engine/rules/7.2.3.json similarity index 100% rename from rules/7.2.3.json rename to engine/rules/7.2.3.json diff --git a/rules/7.2.4.json b/engine/rules/7.2.4.json similarity index 100% rename from rules/7.2.4.json rename to engine/rules/7.2.4.json diff --git a/rules/7.2.5.json b/engine/rules/7.2.5.json similarity index 100% rename from rules/7.2.5.json rename to engine/rules/7.2.5.json diff --git a/rules/7.2.6.json b/engine/rules/7.2.6.json similarity index 100% rename from rules/7.2.6.json rename to engine/rules/7.2.6.json diff --git a/rules/7.2.7.json b/engine/rules/7.2.7.json similarity index 100% rename from rules/7.2.7.json rename to engine/rules/7.2.7.json diff --git a/rules/7.2.8.json b/engine/rules/7.2.8.json similarity index 100% rename from rules/7.2.8.json rename to engine/rules/7.2.8.json diff --git a/rules/7.2.9.json b/engine/rules/7.2.9.json similarity index 100% rename from rules/7.2.9.json rename to engine/rules/7.2.9.json diff --git a/rules/7.3.1.json b/engine/rules/7.3.1.json similarity index 100% rename from rules/7.3.1.json rename to engine/rules/7.3.1.json diff --git a/rules/7.3.2.json b/engine/rules/7.3.2.json similarity index 100% rename from rules/7.3.2.json rename to engine/rules/7.3.2.json diff --git a/rules/7.3.3.json b/engine/rules/7.3.3.json similarity index 100% rename from rules/7.3.3.json rename to engine/rules/7.3.3.json diff --git a/rules/7.3.4.json b/engine/rules/7.3.4.json similarity index 100% rename from rules/7.3.4.json rename to engine/rules/7.3.4.json diff --git a/rules/8.1.1.json b/engine/rules/8.1.1.json similarity index 100% rename from rules/8.1.1.json rename to engine/rules/8.1.1.json diff --git a/rules/8.1.2.json b/engine/rules/8.1.2.json similarity index 100% rename from rules/8.1.2.json rename to engine/rules/8.1.2.json diff --git a/rules/8.2.1.json b/engine/rules/8.2.1.json similarity index 100% rename from rules/8.2.1.json rename to engine/rules/8.2.1.json diff --git a/rules/8.2.2.json b/engine/rules/8.2.2.json similarity index 100% rename from rules/8.2.2.json rename to engine/rules/8.2.2.json diff --git a/rules/8.2.3.json b/engine/rules/8.2.3.json similarity index 100% rename from rules/8.2.3.json rename to engine/rules/8.2.3.json diff --git a/rules/8.2.4.json b/engine/rules/8.2.4.json similarity index 100% rename from rules/8.2.4.json rename to engine/rules/8.2.4.json diff --git a/rules/8.4.1.json b/engine/rules/8.4.1.json similarity index 100% rename from rules/8.4.1.json rename to engine/rules/8.4.1.json diff --git a/rules/8.5.1.json b/engine/rules/8.5.1.json similarity index 100% rename from rules/8.5.1.json rename to engine/rules/8.5.1.json diff --git a/rules/8.5.2.json b/engine/rules/8.5.2.json similarity index 100% rename from rules/8.5.2.json rename to engine/rules/8.5.2.json diff --git a/rules/8.5.3.json b/engine/rules/8.5.3.json similarity index 100% rename from rules/8.5.3.json rename to engine/rules/8.5.3.json diff --git a/rules/8.5.4.json b/engine/rules/8.5.4.json similarity index 100% rename from rules/8.5.4.json rename to engine/rules/8.5.4.json diff --git a/rules/8.5.5.json b/engine/rules/8.5.5.json similarity index 100% rename from rules/8.5.5.json rename to engine/rules/8.5.5.json diff --git a/rules/8.5.6.json b/engine/rules/8.5.6.json similarity index 100% rename from rules/8.5.6.json rename to engine/rules/8.5.6.json diff --git a/rules/8.5.7.json b/engine/rules/8.5.7.json similarity index 100% rename from rules/8.5.7.json rename to engine/rules/8.5.7.json diff --git a/rules/8.5.8.json b/engine/rules/8.5.8.json similarity index 100% rename from rules/8.5.8.json rename to engine/rules/8.5.8.json diff --git a/rules/8.5.9.json b/engine/rules/8.5.9.json similarity index 100% rename from rules/8.5.9.json rename to engine/rules/8.5.9.json diff --git a/rules/8.6.1.json b/engine/rules/8.6.1.json similarity index 100% rename from rules/8.6.1.json rename to engine/rules/8.6.1.json diff --git a/rules/9.1.1.json b/engine/rules/9.1.1.json similarity index 100% rename from rules/9.1.1.json rename to engine/rules/9.1.1.json diff --git a/rules/9.1.10.json b/engine/rules/9.1.10.json similarity index 100% rename from rules/9.1.10.json rename to engine/rules/9.1.10.json diff --git a/rules/9.1.11.json b/engine/rules/9.1.11.json similarity index 100% rename from rules/9.1.11.json rename to engine/rules/9.1.11.json diff --git a/rules/9.1.2.json b/engine/rules/9.1.2.json similarity index 100% rename from rules/9.1.2.json rename to engine/rules/9.1.2.json diff --git a/rules/9.1.3.json b/engine/rules/9.1.3.json similarity index 100% rename from rules/9.1.3.json rename to engine/rules/9.1.3.json diff --git a/rules/9.1.4.json b/engine/rules/9.1.4.json similarity index 100% rename from rules/9.1.4.json rename to engine/rules/9.1.4.json diff --git a/rules/9.1.5.json b/engine/rules/9.1.5.json similarity index 100% rename from rules/9.1.5.json rename to engine/rules/9.1.5.json diff --git a/rules/9.1.6.json b/engine/rules/9.1.6.json similarity index 100% rename from rules/9.1.6.json rename to engine/rules/9.1.6.json diff --git a/rules/9.1.7.json b/engine/rules/9.1.7.json similarity index 100% rename from rules/9.1.7.json rename to engine/rules/9.1.7.json diff --git a/rules/9.1.8.json b/engine/rules/9.1.8.json similarity index 100% rename from rules/9.1.8.json rename to engine/rules/9.1.8.json diff --git a/rules/9.1.9.json b/engine/rules/9.1.9.json similarity index 100% rename from rules/9.1.9.json rename to engine/rules/9.1.9.json diff --git a/rules/CIS_GCP_1_5.rego b/engine/rules/CIS_GCP_1_5.rego similarity index 100% rename from rules/CIS_GCP_1_5.rego rename to engine/rules/CIS_GCP_1_5.rego diff --git a/test-configs/compliant.json b/engine/test-configs/compliant.json similarity index 100% rename from test-configs/compliant.json rename to engine/test-configs/compliant.json diff --git a/test-configs/iam_policy.json b/engine/test-configs/iam_policy.json similarity index 100% rename from test-configs/iam_policy.json rename to engine/test-configs/iam_policy.json diff --git a/test-configs/networks.json b/engine/test-configs/networks.json similarity index 100% rename from test-configs/networks.json rename to engine/test-configs/networks.json