Policy API Integration (#499)

* move certain top-level directories into "scubagoggles"

* implementation with policy API

* correct anchor to setup utility

* first step in fixing smoke test workflow

* improve setup for smoke test; accommodate AMD64 OPA on ARM64 macOS

* implemented initial feedback from pull request

* argument parser: ensure credentials is a Path

* Complete implementation of service account credentials for policy API

* fix GwsAuth for service accounts - they have no token file
getopa: tolerate missing "v" in specified version

* documentation: moved from with "scubagoggles" subdirectory to top-level directory

* build: create output directory if non-existent

* documentation: minor changes

* setup: download OPA; resolve other PR issues

* smoke_test: remove default value for "subjectemail" in test_scubagoggles_output()

* groups 4.1, 5.1: correct for probable Google changes in enumeration values
drive 1.3, 1.4, 1.5, 1.7: correct misunderstanding of sharing option flags

* drive rego: remove unused import

* commoncontrols 3.1: remove policy API check for employee ID challenge (see 11/6 change)
commoncontrols 4.1: use "friendly" value in non-compliance message

* commoncontrols: remove 9.1, 9.2 policy API implementation

* commoncontrols: check "takeout_service_status" in 12.1

* policy_api: implement policy reduction and apply default values
scuba_argument_parser: fix bug in converting argument value data types
drive rego: fix 6.1 for subOUs/groups
policy_api: add ability to dump Google's raw policy response
installation & OPA instructions: add more detail about setup downloading OPA
This commit is contained in:
Roy Lane
2024-12-19 19:23:24 -05:00
committed by GitHub
parent c842e699ed
commit 2219d49692
229 changed files with 279122 additions and 271906 deletions

23
.gitattributes vendored Normal file
View File

@@ -0,0 +1,23 @@
# If you know it's a text file, don't use "=auto" because with that you're
# letting Git decide whether it's text (and YOU already know it IS).
*.css text
*.csv text
*.html text
*.jpg binary
*.js text
*.json text
*.md text
*.pdf binary
*.png binary
*.py text
*.rego text
*.sh text eol=lf
*.svg text
*.txt text
*.yaml text
*.yml text
.gitattributes text
.gitignore text
LICENSE text
MANIFEST.in text

View File

@@ -5,7 +5,7 @@ inputs:
default: "macos"
opa-version:
required: true
default: "0.60.0"
default: "v0.60.0"
python-version:
required: true
@@ -15,10 +15,9 @@ runs:
- name: Setup virtualenv
shell: bash
run: |
pip install virtualenv
virtualenv -p python .venv
python -m venv .venv
source .venv/bin/activate
- name: Install dependencies
shell: bash
run: |
@@ -30,5 +29,5 @@ runs:
- name: Download OPA executable
shell: bash
run: |
python download_opa.py -v ${{ inputs.opa-version }} -os ${{ inputs.operating-system }}
chmod +x opa_darwin_amd64
scubagoggles setup -m -nc -nd -d ~/scubagoggles -r ~/scubagoggles -c credentials.json
scubagoggles getopa -v ${{ inputs.opa-version }}

View File

@@ -5,7 +5,7 @@ inputs:
default: "windows"
opa-version:
required: true
default: "0.60.0"
default: "v0.60.0"
python-version:
required: true
@@ -15,9 +15,8 @@ runs:
- name: Setup virtualenv
shell: powershell
run: |
pip install virtualenv
python -m venv .venv
.venv\Scripts\activate
.venv\Scripts\activate.ps1
- name: Install dependencies
shell: powershell
@@ -29,4 +28,6 @@ runs:
- name: Download OPA executable
shell: powershell
run: python download_opa.py -v ${{ inputs.opa-version }} -os ${{ inputs.operating-system }}
run: |
scubagoggles setup -m -nc -nd -d ~/scubagoggles -r ~/scubagoggles -c credentials.json
scubagoggles getopa -v ${{ inputs.opa-version }}

View File

@@ -13,6 +13,6 @@ jobs:
ref: main
- name: Get OPA Hash
run: |
cd ./repo/utils
cd ./repo/scubagoggles/utils
chmod +x checkOPAHash.sh
./checkOPAHash.sh

View File

@@ -20,18 +20,18 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
python-version: ["3.9.2"]
python-version: ["3.9.19"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pylint==3.2.7 pytest selenium
pip install pylint pytest selenium
- name: Analysing the code with pylint
run: |
pylint -d R0913,R0914,R0915,R1702,W0718,W0719,R0801 $(git ls-files '*.py')

View File

@@ -28,15 +28,15 @@ jobs:
version: latest
- name: Run OPA Check
run: opa check rego Testing/RegoTests --strict
run: opa check scubagoggles/rego scubagoggles/Testing/RegoTests --strict
- name: Run OPA Tests
run: opa test rego/*.rego Testing/RegoTests/**/*.rego -v
run: opa test scubagoggles/rego/*.rego scubagoggles/Testing/RegoTests/**/*.rego -v
- name: Setup Regal
uses: StyraInc/setup-regal@v0.2.0
uses: StyraInc/setup-regal@v1
with:
version: v0.15.0
version: 0.27.0
- name: Run Regal Lint
run: regal lint --format github rego Testing
run: regal lint --format github scubagoggles/rego scubagoggles/Testing/RegoTests

View File

@@ -1,4 +1,4 @@
on:
on:
workflow_dispatch:
inputs:
releaseName:
@@ -14,33 +14,42 @@ name: Build Release
jobs:
build-and-deploy:
runs-on: windows-latest
runs-on: ubuntu-latest
env:
PYTHON_VERSION: "3.12"
RELEASE_VERSION: ${{ inputs.version }}
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
path: repo
ref: main
- name: Package Repo for release
shell: pwsh
run: |
$PackageName = "scubagoggles"
Remove-Item -Recurse -Force repo -Include .git*
Move-Item -Path repo -Destination "${PackageName}-${env:RELEASE_VERSION}" -Force
Compress-Archive -Path "${PackageName}-${env:RELEASE_VERSION}" -DestinationPath "${PackageName}-${env:RELEASE_VERSION}.zip"
Get-ChildItem -Path . | Write-Output
- name: release
uses: softprops/action-gh-release@v1
id: create_release
with:
draft: true
prerelease: false
name: v${{ inputs.releaseName }}
tag_name: v${{ inputs.version }}
files: scubagoggles-${{ inputs.version }}.zip
generate_release_notes: true
fail_on_unmatched_files: true
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Install Python dependencies
run: pip install -r requirements.txt
- name: Package Repo for release
shell: bash
run: |
reqv="${{ inputs.version }}"
reqv="${reqv//[[:space:]]/}"
[[ ! "$reqv" =~ ^[0-9]{1,2}(\.[0-9]{1,2}){2}$ ]] \
&& echo "invalid request version: $reqv" && exit 1
sgv=$(grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' scubagoggles/__init__.py)
[[ "$reqv" == "$sgv" ]] \
|| (echo "version mismatch - current: $sgv" && exit 1)
./scubagoggles/utils/build.sh -r "$PWD" -t "$GITHUB_REF_NAME"
- name: release
uses: softprops/action-gh-release@v1
id: create_release
with:
draft: true
prerelease: false
name: v${{ inputs.releaseName }}
tag_name: v${{ inputs.version }}
files: |
scubagoggles-*-py3-none-any.whl
scubagoggles-*.tar.gz
generate_release_notes: true
fail_on_unmatched_files: true

View File

@@ -1,5 +1,5 @@
name: Run Smoke Test
on:
name: Run Smoke Test
on:
pull_request:
types: [opened, reopened]
branches:
@@ -32,7 +32,7 @@ on:
description: "Choose OPA version"
required: true
type: string
default: "0.60.0"
default: "v0.60.0"
jobs:
configuration:
@@ -77,11 +77,11 @@ jobs:
- name: Setup Python v${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
with:
python-version: ${{ matrix.python-version }}
cache: "pip"
cache-dependency-path: "requirements.txt"
- name: Setup Dependencies (Windows)
if: ${{ matrix.operating-system == 'windows-latest' }}
uses: ./.github/actions/setup-dependencies-windows
@@ -89,7 +89,7 @@ jobs:
operating-system: "windows"
opa-version: ${{ needs.configuration.outputs.opa-version }}
python-version: ${{ matrix.python-version }}
- name: Setup Dependencies (macOS)
if: ${{ matrix.operating-system == 'macos-latest' }}
uses: ./.github/actions/setup-dependencies-macos
@@ -97,13 +97,13 @@ jobs:
operating-system: "macos"
opa-version: ${{ needs.configuration.outputs.opa-version }}
python-version: ${{ matrix.python-version }}
- name: Setup credentials for service account
id: create-json
uses: jsdaniell/create-json@v1.2.3
with:
with:
name: "credentials.json"
json: ${{ secrets.GWS_GITHUB_AUTOMATION_CREDS }}
- name: Run ScubaGoggles and check for correct output
run: pytest ./Testing/Functional/SmokeTests/ -vvv --subjectemail="${{ secrets.GWS_SUBJECT_EMAIL }}" --customerdomain="${{ secrets.GWS_DOMAIN }}"
run: pytest ./scubagoggles/Testing/Functional/SmokeTests/ -vvv --subjectemail="${{ secrets.GWS_SUBJECT_EMAIL }}" --customerdomain="${{ secrets.GWS_DOMAIN }}"

View File

@@ -1,60 +1,91 @@
# Regal linter configuration
# All rules documented here:
# https://docs.styra.com/regal/category/rules
rules:
custom:
naming-convention:
# Codifying the conventions used in this project.
# By all means, change this to be less restrictive
# if you wish.
level: error
conventions:
- pattern: '^[A-Z]+[a-zA-Z0-9_]+$|^tests$|^test_|^check_'
targets:
- rule
- pattern: '^[A-Z]+[a-zA-Z0-9_]+$'
targets:
- function
- pattern: '^[a-z]+$'
targets:
- package
idiomatic:
no-defined-entrypoint:
# This is a good practice for documentation, and
# compilation to Wasm/IR, but not a requirement.
# Safe to ignore.
level: ignore
imports:
implicit-future-keywords:
# This rule is on it's way out anyway, as future
# versions of OPA will make these keywords standard.
level: ignore
style:
external-reference:
# This rule is quite opinionated / style preference
# safe to ignore.
level: ignore
file-length:
level: ignore
no-whitespace-comment:
# This repo is actually good about this, but frequently
# uses '#--' as a delimeter of sorts. That should be OK,
# and the next version of Regal will allow for exceptions
# like this: https://github.com/StyraInc/regal/issues/379
level: ignore
opa-fmt:
level: ignore
prefer-snake-case:
# This is the default style preference for Rego, but since
# the style of this project better matches the domain it is
# modeling, we'll ignore this rule in favor of the custom
# naming-convention rule defined above.
level: ignore
rule-length:
level: ignore
todo-comment:
level: ignore
testing:
test-outside-test-package:
# This is just a style preference
level: ignore
# Regal linter configuration
# All rules documented here:
# https://docs.styra.com/regal/category/rules
rules:
custom:
naming-convention:
# Codifying the conventions used in this project.
# By all means, change this to be less restrictive
# if you wish.
level: error
conventions:
- pattern: '^[A-Z]+[a-zA-Z0-9_]+$|^tests$|^test_|^check_'
targets:
- rule
- pattern: '^[A-Z]+[a-zA-Z0-9_]+$'
targets:
- function
- pattern: '^[a-z]+$'
targets:
- package
idiomatic:
no-defined-entrypoint:
# This is a good practice for documentation, and
# compilation to Wasm/IR, but not a requirement.
# Safe to ignore.
level: ignore
directory-package-mismatch:
# Will prefixing the packages with "scubagoggles.rego" really
# be an improvement?
level: ignore
imports:
implicit-future-keywords:
# This rule is on it's way out anyway, as future
# versions of OPA will make these keywords standard.
level: ignore
prefer-package-imports:
# The following are used so often that there's no need
# for the "utils." prefix every single time they're used.
ignore-import-paths:
- data.utils.GetFriendlyEnabledValue
- data.utils.PolicyApiInUse
- data.utils.FailTestBothNonCompliant
- data.utils.FailTestGroupNonCompliant
- data.utils.FailTestOUNonCompliant
- data.utils.FailTestNonCompliant
- data.utils.FailTestNoEvent
- data.utils.PassTestResult
- data.utils.PassTestResultWithMessage
use-rego-v1:
# For now, anyway...
level: ignore
performance:
with-outside-test-context:
level: ignore
style:
external-reference:
# This rule is quite opinionated / style preference
# safe to ignore.
level: ignore
file-length:
level: ignore
messy-rule:
# This is all over the place with "tests", and the way we've
# done it (by baseline) makes sense.
level: ignore
no-whitespace-comment:
# This repo is actually good about this, but frequently
# uses '#--' as a delimeter of sorts. That should be OK,
# and the next version of Regal will allow for exceptions
# like this: https://github.com/StyraInc/regal/issues/379
level: ignore
opa-fmt:
level: ignore
pointless-reassignment:
# If this prevents duplicate strings all over the place,
# then it's worth it.
level: ignore
prefer-snake-case:
# This is the default style preference for Rego, but since
# the style of this project better matches the domain it is
# modeling, we'll ignore this rule in favor of the custom
# naming-convention rule defined above.
level: ignore
rule-length:
level: ignore
todo-comment:
level: ignore
testing:
test-outside-test-package:
# This is just a style preference
level: ignore

View File

@@ -1,4 +1,5 @@
# Branching Structure
The Branching Structure flow diagram describes the branching strategy implemented in the ScubaGoggles project.
The Branching Structure flow diagram describes the branching strategy
implemented in the ScubaGoggles project.
![image](/docs/images/scubagoggles_branching_structure.svg)
![image](images/scubagoggles_branching_structure.svg)

View File

@@ -8,7 +8,7 @@ We adhere to [GitHub flow](https://docs.github.com/en/get-started/using-github/g
There are exceptions to this, necessitated by the extensive review process the baseline documents themselves undergo, during which no baseline changes can be made.
To accommodate this, the development lifecycle on ScubaGoggles is as follows:
![image](/docs/images/scubagoggles_lifecycle.svg)
![image](images/scubagoggles_lifecycle.svg)
Baseline submission triggers a baseline freeze, at which point the following actions need to be performed:

10
MANIFEST.in Normal file
View File

@@ -0,0 +1,10 @@
# This manifest is used to ensure that certain non-Python files are included
# in the ScubaGoggles distribution. The following subdirectories (and their
# contents) are included:
graft scubagoggles/baselines
graft scubagoggles/rego
graft scubagoggles/reporter
graft scubagoggles/sample-report
graft scubagoggles/Testing
graft scubagoggles/utils

View File

@@ -1,21 +1,25 @@
![CISA Logo](/docs/images/cisa.png)
![CISA Logo](docs/images/cisa.png)
<div align='center' style="margin:0;" id="user-content-toc">
<ul>
<summary><h1 style="display: inline-block;">ScubaGoggles</h1></summary>
<h1 style="display: inline-block;">ScubaGoggles</h1>
</ul>
<ul>
<a href="https://github.com/cisagov/ScubaGoggles/releases" alt="ScubaGoggles version #">
<img src="https://img.shields.io/badge/ScubaGoggles-v0.3.0-%2385B065?labelColor=%23005288" /></a>
<a href="https://github.com/cisagov/ScubaGoggles/tree/main/baselines" alt="GWS SCB version #">
<img src="https://img.shields.io/badge/GWS_SCB-v0.3-%2385B065?labelColor=%23005288" /></a>
<a href="" alt="Downloads">
<img src="https://img.shields.io/github/downloads/cisagov/ScubaGoggles/total.svg" /></a>
<a href="https://github.com/cisagov/ScubaGoggles/releases">
<img src="https://img.shields.io/badge/ScubaGoggles-v0.3.0-%2385B065?labelColor=%23005288" alt="ScubaGoggles version #"></a>
<a href="https://github.com/cisagov/ScubaGoggles/tree/main/baselines">
<img src="https://img.shields.io/badge/GWS_SCB-v0.3-%2385B065?labelColor=%23005288" alt="GWS SCB version #"></a>
<a href="">
<img src="https://img.shields.io/github/downloads/cisagov/ScubaGoggles/total.svg" alt="Downloads"></a>
</ul>
</div>
<h2 align='center' stye="margin:0;">GWS Secure Configuration Baseline Assessment Tool </h2>
<h2 align='center' style="margin:0;">GWS Secure Configuration Baseline Assessment Tool </h2>
Developed by CISA, ScubaGoggles is an assessment tool that verifies a Google Workspace (GWS) organization's configuration conforms to the policies described in the Secure Cloud Business Applications ([SCuBA](https://cisa.gov/scuba)) Secure Configuration Baseline [documents](/baselines/README.md).
Developed by CISA, ScubaGoggles is an assessment tool that verifies a Google
Workspace (GWS) organization's configuration conforms to the policies
described in the Secure Cloud Business Applications
([SCuBA](https://cisa.gov/scuba)) Secure Configuration
Baseline [documents](scubagoggles/baselines/README.md).
For the Microsoft 365 (M365) rendition of this tool, see [ScubaGear](https://github.com/cisagov/ScubaGear).
@@ -28,43 +32,39 @@ We use a three-step process:
2. **Verify**. Compare the exported settings from the previous step with the configuration prescribed in the baselines. We do this using [OPA Rego](https://www.openpolicyagent.org/docs/latest/policy-language/#what-is-rego), a declarative query language for defining policy.
3. **Report**. Package the results as HTML and JSON.
## Limitations of the tool
The majority of the conformance checks done by ScubaGoggles rely on [GWS Admin log events](https://support.google.com/a/answer/4579579?hl=en). If there is no log event corresponding to a SCuBA baseline policy, ScubaGoggles will indicate that the setting currently can not be checked on its HTML report output. In this situation, we recommend you manually review your GWS security configurations with the SCuBA security baselines. See [Limitations](/docs/usage/Limitations.md) for more details.
## Table of Contents
### Installation
- [Download and Python Install](/docs/installation/DownloadAndInstall.md)
- [Download the OPA Executable](/docs/installation/OPA.md)
- [Download and Python Install](docs/installation/DownloadAndInstall.md)
- [Download the OPA Executable](docs/installation/OPA.md)
### Prerequisites
- [Permissions](/docs/prerequisites/Prerequisites.md#permissions)
- [Create a Project](/docs/prerequisites/Prerequisites.md#create-a-project)
- [Permissions](docs/prerequisites/Prerequisites.md#permissions)
- [Create a Project](docs/prerequisites/Prerequisites.md#create-a-project)
### Authentication
- [Authentication Methods](/docs/authentication/AuthenticationMethods.md)
- [Using OAuth](/docs/authentication/OAuth.md)
- [Using a Service Account](/docs/authentication/ServiceAccount.md)
- [Authentication Methods](docs/authentication/AuthenticationMethods.md)
- [Using OAuth](docs/authentication/OAuth.md)
- [Using a Service Account](docs/authentication/ServiceAccount.md)
### Usage
- [Usage: Parameters](/docs/usage/Parameters.md)
- [Usage: Config File](/docs/usage/Config.md)
- [Usage: Examples](/docs/usage/Examples.md)
- [Reviewing Output](/docs/usage/ReviewOutput.md)
- [Limitations](/docs/usage/Limitations.md)
### Upgrading and Maintenance
- [Upgrading ScubaGoggles](/docs/upgrading/Upgrading.md#upgrading-scubagoggles)
- [Upgrading OPA](/docs/upgrading/Upgrading.md#upgrading-opa)
- [Usage: Parameters](docs/usage/Parameters.md)
- [Usage: Config File](docs/usage/Config.md)
- [Usage: Examples](docs/usage/Examples.md)
- [Reviewing Output](docs/usage/ReviewOutput.md)
- [Limitations](docs/usage/Limitations.md)
### Troubleshooting
- [Lots of Manual Checks](/docs/troubleshooting/Troubleshooting.md#lots-of-manual-checks)
- [Not Authorized to Access This Resource](/docs/troubleshooting/Troubleshooting.md#not-authorized-to-access-this-resource)
- [scubagoggles Not Found](/docs/troubleshooting/Troubleshooting.md#scubagoggles-not-found)
- [Unable to view HTML report due to environment limitations](/docs/troubleshooting/Troubleshooting.md#unable-to-view-html-report-due-to-environment-limitations)
- [Lots of Manual Checks](docs/troubleshooting/Troubleshooting.md#lots-of-manual-checks)
- [Not Authorized to Access This Resource](docs/troubleshooting/Troubleshooting.md#not-authorized-to-access-this-resource)
- [scubagoggles Not Found](docs/troubleshooting/Troubleshooting.md#scubagoggles-not-found)
- [Unable to view HTML report due to environment limitations](docs/troubleshooting/Troubleshooting.md#unable-to-view-html-report-due-to-environment-limitations)
## Project License
Unless otherwise noted, this project is distributed under the Creative Commons Zero license. With developer approval, contributions may be submitted with an alternate compatible license. If accepted, those contributions will be listed herein with the appropriate license.
Unless otherwise noted, this project is distributed under the Creative
Commons Zero license. With developer approval, contributions may be
submitted with an alternate compatible license. If accepted, those
contributions will be listed herein with the appropriate license.

View File

@@ -1,72 +0,0 @@
"""
smoke_test.py declares a SmokeTest class for ScubaGoggles automation testing.
"""
import subprocess
import os
import pytest
from smoke_test_utils import (
get_output_path,
prepend_file_protocol,
get_required_entries,
verify_all_outputs_exist,
verify_output_type,
run_selenium,
verify_scubaresults,
)
SAMPLE_REPORT = "sample-report"
SCUBA_RESULTS = "ScubaResults.json"
BASELINE_REPORTS = "BaselineReports.html"
class SmokeTest:
"""
Pytest class to encapsulate the following test cases:
- Generate the correct output files (BaselineReports.html, ScubaResults.json, etc)
- Check the content of html files, verify href attributes are correct, etc
- Check if ScubaResults.json contains errors in the summary. If errors exist, then
either API calls or functions produced exceptions which need to be handled
"""
def test_scubagoggles_output(self, subjectemail):
"""
Test if the `scubagoggles gws` command generates correct output for all baselines.
Args:
subjectemail: The email address of a user for the service account
"""
try:
command: str = f"scubagoggles gws --subjectemail {subjectemail} --quiet"
subprocess.run(command, shell=True, check=True)
output_path: str = get_output_path()
output: list = verify_output_type(output_path, [])
required_entries = get_required_entries(os.path.join(os.getcwd(), SAMPLE_REPORT), [])
verify_all_outputs_exist(output, required_entries)
except (OSError, ValueError, Exception) as e:
pytest.fail(f"An error occurred, {e}")
def test_scubaresults(self):
"""
Determine if ScubaResults.json contains API errors or exceptions.
"""
try:
output_path: str = get_output_path()
scubaresults_path: str = os.path.join(output_path, SCUBA_RESULTS)
with open(scubaresults_path, encoding="utf-8") as jsonfile:
verify_scubaresults(jsonfile)
except (ValueError, Exception) as e:
pytest.fail(f"An error occurred, {e}")
def test_scubagoggles_report(self, browser, customerdomain):
"""
Test if the generated baseline reports are correct,
i.e. BaselineReports.html, CalendarReport.html, ChatReport.html
"""
try:
output_path: str = get_output_path()
report_path: str = prepend_file_protocol(os.path.join(output_path, BASELINE_REPORTS))
browser.get(report_path)
run_selenium(browser, customerdomain)
except (ValueError, AssertionError, Exception) as e:
browser.quit()
pytest.fail(f"An error occurred, {e}")

View File

@@ -1,11 +0,0 @@
Individual baselines can be visited directly at the links below:
- [Common Controls](/baselines/commoncontrols.md)
- [Gmail](/baselines/gmail.md)
- [Google Calendar](/baselines/calendar.md)
- [Google Chat](/baselines/chat.md)
- [Google Classroom](/baselines/classroom.md)
- [Google Drive and Docs](/baselines/drive.md)
- [Google Meet](/baselines/meet.md)
- [Google Sites](/baselines/sites.md)
- [Groups for Business](/baselines/groups.md)

View File

@@ -1,15 +1,15 @@
# Authentication Methods
ScubaGoggles supports both OAuth and Service Accounts for authorization/authentication. See the following table for the tradeoffs between the two methods.
| OAuth | Service Account |
| -------- | ------- |
| + Allows user consent to specific scopes | - Requires domain-wide delegation |
| - Requires a browser for authentication | + Does not require a browser for authentication, allowing for more automation. |
After determining which method is most appropriate for your organization, follow the instructions in either [Using OAuth](/docs/authentication/OAuth.md) or [Using a Service Account](/docs/authentication/ServiceAccount.md).
## Navigation
- Continue to [Using OAuth](/docs/authentication/OAuth.md)
- Continue to [Using a Service Account](/docs/authentication/ServiceAccount.md)
- Return to [Documentation Home](/README.md)
# Authentication Methods
ScubaGoggles supports both OAuth and Service Accounts for authorization/authentication. See the following table for the tradeoffs between the two methods.
| OAuth | Service Account |
| -------- | ------- |
| + Allows user consent to specific scopes | - Requires domain-wide delegation |
| - Requires a browser for authentication | + Does not require a browser for authentication, allowing for more automation. |
After determining which method is most appropriate for your organization, follow the instructions in either [Using OAuth](OAuth.md) or [Using a Service Account](ServiceAccount.md).
## Navigation
- Continue to [Using OAuth](OAuth.md)
- Continue to [Using a Service Account](ServiceAccount.md)
- Return to [Documentation Home](/README.md)

View File

@@ -1,50 +1,62 @@
# Using OAuth
Only complete this section if not authenticating via [Service Account](/docs/authentication/ServiceAccount.md). See [Authentication Methods](/docs/authentication/AuthenticationMethods.md) for more details.
## Create an OAuth credential
1. Be signed into http://console.cloud.google.com/.
1. From the hamburger menu on the left, select **APIs & Services** -> **OAuth consent screen**
1. Select **Internal** for **User Type**
1. Click **Create**
1. Fill in your **App name** and **User support email**
1. Scroll down to the **Authorized Domains** section
1. Under **Authorized domains**, add the primary domain of your GWS organization.
1. Add another email address for **Developer contact information**
1. Click **SAVE AND CONTINUE**
1. Do nothing on the **Scopes** screen, just click **SAVE AND CONTINUE**
1. Review summary, then click **BACK TO DASHBOARD**
1. Click **Credentials** from the menu on the left
1. Click **CREATE CREDENTIALS**
1. Select **Oauth client ID**
1. Select **Web application** for **Application type**
1. Give name as appropriate
1. Under **Authorized redirect URIs**, click "ADD URI." Add `http://localhost` and `http://localhost:8080/`
1. Click **CREATE**
1. Click **DOWNLOAD JSON** from the resulting **OAuth client created** page
1. Click **OK**
1. Move the downloaded file (begins with `client_secret*.json`) to the root directory folder of this repo, rename to `credentials.json`
1. Go back the menu on the left and click **Enabled API Services**
1. In the center screen click **Enable APIS AND Services**
1. Search for and enable the **Admin SDK API**
1. Search for and enable the **Groups Settings API**
1. During the first run of this tool your default web browser will open up a page to consent to the API scopes needed to run this tool. Sign in
with an account with the necessary privileges and click allow.
## Add the Oauth App to the allowlist
If you've limited application access to Google's APIs in your organization, the [Common Controls: App Access to Google APIs](/baselines/commoncontrols.md#10-app-access-to-google-apis) baseline covers this topic, follow the directions below to allowlist the OAuth app.
1. Login to https://console.cloud.google.com
2. Navigate to the appropriate project
3. Select **API's & Services** from the top left hamburger icon
4. Select **Credentials**
5. Copy your client ID under **OAuth 2.0 Client IDs**
6. Now login to [admin.google.com](https://admin.google.com/) and navigate to **Security** -> **Access and Data Control** -> **API Controls** -> **Manage Third-Party App Access**
7. Select **Add App** -> **Oauth App Name** or **Client ID**
8. Search by your **OAuth client ID**
9. Select the App
10. Select your root organization as the domain
11. Select **Trusted**
## Navigation
- Continue to [Usage: Parameters](/docs/usage/Parameters.md)
- Return to [Documentation Home](/README.md)
# Using OAuth
Only complete this section if not authenticating via [Service Account](ServiceAccount.md). See [Authentication Methods](AuthenticationMethods.md) for more details.
## Create an OAuth credential
1. Sign in to your account at http://console.cloud.google.com/.
1. Click the "hamburger" menu on the left (three horizontal
bars on top of each other), and select **APIs & Services** -> **OAuth consent screen**
1. Select **Internal** for **User Type**
1. Click **Create**
1. Fill in your **App name** and **User support email**
1. Scroll down to the **Authorized Domains** section
1. Under **Authorized domains**, add the primary domain of your GWS organization.
1. Add another email address for **Developer contact information**
1. Click **SAVE AND CONTINUE**
1. Do nothing on the **Scopes** screen, just click **SAVE AND CONTINUE**
1. Review summary, then click **BACK TO DASHBOARD**
1. Click **Credentials** from the menu on the left
1. Click **CREATE CREDENTIALS**
1. Select **Oauth client ID**
1. Select **Web application** for **Application type**
1. Give name as appropriate
1. Under **Authorized redirect URIs**, click "ADD URI." Add `http://localhost`
and `http://localhost:8080/`. **NOTE** the ending slash (`/`) in the *second*
URL is **necessary**. If the slash is missing, you will eventually get an
error when running ScubaGoggles (It will be an "access blocked" error on the
Google authentication webpage. You'll also see `Error 400:
redirect_uri_mismatch`).
1. Click **CREATE**
1. Click **DOWNLOAD JSON** from the resulting **OAuth client created** page
1. Click **OK**
1. Move the downloaded file (begins with `client_secret*.json`) to the
location and name you specified when you ran the
[ScubaGoggles setup utility](../installation/DownloadAndInstall.md#ScubaGoggles-Setup-Utility).
If you have not yet run the setup utility, you will specify this file as the
credentials file when prompted by the setup utility. You'll make it easier
on yourself if you rename the file to something simple, like
`credentials.json`.
1. Go back the menu on the left and click **Enabled API Services**
1. In the center screen click **Enabled APIs & Services**
1. Search for and enable the **Admin SDK API**
1. Search for and enable the **Groups Settings API**
1. During the first run of this tool your default web browser will open up a page to consent to the API scopes needed to run this tool. Sign in
with an account with the necessary privileges and click allow.
## Add the Oauth App to the allowlist
If you've limited application access to Google's APIs in your organization, the [Common Controls: App Access to Google APIs](../../scubagoggles/baselines/commoncontrols.md#10-app-access-to-google-apis) baseline covers this topic, follow the directions below to allowlist the OAuth app.
1. Login to https://console.cloud.google.com
2. Navigate to the appropriate project
3. Select **API's & Services** from the top left hamburger icon
4. Select **Credentials**
5. Copy your client ID under **OAuth 2.0 Client IDs**
6. Now login to [admin.google.com](https://admin.google.com/) and navigate to **Security** -> **Access and Data Control** -> **API Controls** -> **Manage Third-Party App Access**
7. Select **Add App** -> **Oauth App Name** or **Client ID**
8. Search by your **OAuth client ID**
9. Select the App
10. Select your root organization as the domain
11. Select **Trusted**
## Navigation
- Continue to [Usage: Parameters](../usage/Parameters.md)
- Return to [Documentation Home](/README.md)

View File

@@ -1,26 +1,26 @@
# Using a Service Account
Only complete this section if not authenticating via [OAuth](/docs/authentication/OAuth.md). See [Authentication Methods](/docs/authentication/AuthenticationMethods.md) for more details.
> [!Important]
> ScubaGoggles requires the service account to have [domain-wide delegation of authority](https://support.google.com/a/answer/162106?hl=en) to function.
1. Login to https://console.cloud.google.com and navigate to your GCP project.
1. From the hamburger menu, select **IAM & Admin** -> **Service Accounts**
1. Select **CREATE SERVICE ACCOUNT**. Fill out the id field and then select **DONE**
1. Click on the newly created service account then click **KEYS** -> **ADD KEY** -> **Create new key** -> **JSON** -> **CREATE**
1. Move the downloaded file (begins with `<service account>*.json`) to the root directory folder of this repo, rename to `credentials.json`
1. Now login to [admin.google.com](https://admin.google.com/) and navigate to **Security** -> **Access and data control** -> **API controls**
1. Select **MANAGE DOMAIN WIDE DELEGATION**
1. Select **Add new**
1. Enter the `client_id` from the downloaded credentials (also visible after clicking on the created Service account under Details -> Unique ID)
1. Enter each OAuth scope as listed in [Permissions](/docs/prerequisites/Prerequisites.md#permissions)
1. Select **AUTHORIZE**
1. Finally, run ScubaGoggles with the `--subjectemail` option set to the email of an admin with necessary permissions to run ScubaGoggles.
> [!NOTE]
> ScubaGoggles can be run using a service account in a different organization.
> To do so, specify the `--customerid` argument with the customer ID of the target organization (found in [admin.google.com](https://admin.google.com/) under **Account** -> **Account settings**)
## Navigation
- Continue to [Usage: Parameters](/docs/usage/Parameters.md)
- Return to [Documentation Home](/README.md)
# Using a Service Account
Only complete this section if not authenticating via [OAuth](OAuth.md). See [Authentication Methods](AuthenticationMethods.md) for more details.
> [!Important]
> ScubaGoggles requires the service account to have [domain-wide delegation of authority](https://support.google.com/a/answer/162106?hl=en) to function.
1. Login to https://console.cloud.google.com and navigate to your GCP project.
1. From the hamburger menu, select **IAM & Admin** -> **Service Accounts**
1. Select **CREATE SERVICE ACCOUNT**. Fill out the id field and then select **DONE**
1. Click on the newly created service account then click **KEYS** -> **ADD KEY** -> **Create new key** -> **JSON** -> **CREATE**
1. Move the downloaded file (begins with `<service account>*.json`) to the root directory folder of this repo, rename to `credentials.json`
1. Now login to [admin.google.com](https://admin.google.com/) and navigate to **Security** -> **Access and data control** -> **API controls**
1. Select **MANAGE DOMAIN WIDE DELEGATION**
1. Select **Add new**
1. Enter the `client_id` from the downloaded credentials (also visible after clicking on the created Service account under Details -> Unique ID)
1. Enter each OAuth scope as listed in [Permissions](../prerequisites/Prerequisites.md#permissions)
1. Select **AUTHORIZE**
1. Finally, run ScubaGoggles with the `--subjectemail` option set to the email of an admin with necessary permissions to run ScubaGoggles.
> [!NOTE]
> ScubaGoggles can be run using a service account in a different organization.
> To do so, specify the `--customerid` argument with the customer ID of the target organization (found in [admin.google.com](https://admin.google.com/) under **Account** -> **Account settings**)
## Navigation
- Continue to [Usage: Parameters](../usage/Parameters.md)
- Return to [Documentation Home](/README.md)

101
docs/development/release.md Normal file
View File

@@ -0,0 +1,101 @@
**NOTE** The following documentation is for ScubaGoggles
developers.
# ScubaGoggles Release Procedure
## Setting the Version
Update the version in the code that matches the release version number, if this
hasn't been done already. Use the `scubagoggles version --upgrade` command
to set the version.
Once changes in the repository have been frozen for the release, the release
branch (`main`) is tagged with the version. Use an annotated tag to mark the
release:
```
git tag -a v1.0.0 -m 'ScubaGoggles version 1.0.0'
git push origin v1.0.0
```
## Building the Release
ScubaGoggles uses the Python packaging process as described in the
[Python Packaging User Guide](https://packaging.python.org/en/latest/). The
`build` package is required, and is included in the `requirements.txt` file.
If `pip list` doesn't show that the `build` package is installed in your
environment, run `pip install -r requirements.txt` when your current working
directory is at the top-level directory of the ScubaGoggles repository (where
`requirements.txt` resides).
The `setuptools` backend is used to build the ScubaGoggles packages. The
configuration (which was originally in `setup.py`) is in `pyproject.toml`.
Because there are files other than Python code, such as Markdown and Rego files,
the `MANIFEST.in` file is needed to ensure these other files are included with
the ScubaGoggles package. These two configuration files, along with the
LICENSE file, are located at the repository top-level directory.
### Pre-release Review
Before building the release packages, review the `classifiers`, `dependencies`,
and `requires-python` configuration parameters in `pyproject.toml`. If any of
the package dependencies change, the same changes must be reflected both in
both the `pyproject.toml` and `requirements.txt` files.
### Building ScubaGoggles Packages
ScubaGoggles is distributed using a binary "wheel" format, and a source code
version in a gzip-compressed "tar" format. General users will install the
binary wheel package.
To build the packages, use the `scubagoggles/utils/build.sh` Bash script.
As it is written in Bash, it will require either Git or Cygwin on Windows.
Since Git is required for development, Git Bash should already be available
on a Windows system used for ScubaGoggles development. Because this script
is written in Bash, it will work correctly on linux and macOS systems.
The following is the script usage:
```shell
$ scubagoggles/utils/build.sh -h
script usage: build.sh [options]
-h: display usage and exit
-o <dir>: create package files in this directory
-r <git-repo>: ScubaGoggles Git repository specification
-t <git-tag-or-branch>: checkout tag or branch for build
defaults to top of main branch
```
The script creates a clean environment for building the packages. A Python
virtual environment is created in your temporary directory and the ScubaGoggles
Git repository is cloned into a subdirectory of your temporary directory. These
temporary directories are cleaned up when the script exits.
The `-t` option allows you to provide a branch or tag that the repository will
be set to for the build. For normal releases, this tag should be the release
tag (e.g., 'v1.0.0'). By default, the build is based on the HEAD of the main
branch.
When the build process completes, the binary and source package files are
copied to the current working directory when the script was run, or the
directory specified by the `-o` option.
This is an abbreviated example of running the build with its output to the
console:
```shell
$ scubagoggles/utils/build.sh
{build>>>} Creating new Python virtual environment for build...
{build>>>} Cloning Git repository...
<messages...>
{build>>>} Activate Python virtual environment...
{build>>>} Install requirements and editable ScubaGoggles...
<messages...>
{build>>>} Build distribution files...
<messages...>
Successfully built scubagoggles-x.x.x.tar.gz and scubagoggles-x.x.x-py3-none-any.whl
{build>>>} Copying <temp-dir>/scubagoggles-x.x.x-py3-none-any.whl to ./
{build>>>} Copying <temp-dir>/scubagoggles-x.x.x.tar.gz to ./
{build>>>} Performing build cleanup...
```

View File

@@ -0,0 +1,177 @@
**NOTE** The following documentation is for ScubaGoggles
developers.
# ScubaGoggles Version
There is only **one** location for the "official" version
number for ScubaGoggles. The version number resides in the
`scubagoggles/__init__.py`, defined in the `__version__`
variable.
The format of the version number is `<major>.<minor>.<build>`,
where `<major>` is the major version number, `<minor>` is the
minor version number, and `<build>` is the build number.
Each component is an integer.
## The Version class
The version number should be accessed in Python code
by using the `Version` class implemented in
`scubagoggles/version.py`.
These `Version` class attributes are available for accessing the version number:
| Attribute Name | Type | Description | Example |
|----------------|---------|----------------------|-------------------------|
| current | string | 'v' prefixed version | `'v1.0.0' ` |
| number | string | version | `'1.0.0' ` |
| with_name | string | product and version | `'ScubaGoggles v1.0.0'` |
| major | integer | major version | `1` |
| minor | integer | minor version | `0` |
| build | integer | build number | `0` |
| suffix | string | baseline version | `'v1.0'` |
## Baseline Versioning
Baseline policies in ScubaGoggles are identified by a policy
identifier. The format of the policy ID is:
`GWS.<app-name>.<policy-number>.v<baseline-version>`. The
`<app-name>` identifies the Google Workspace application
as shown in the following table:
| <app-name> | Description |
|----------------|---------------------|
| CALENDAR | Calendar |
| CHAT | Chat |
| CLASSROOM | Classroom |
| COMMONCONTROLS | Common Controls |
| DRIVEDOCS | Drive and Docs |
| GMAIL | Gmail |
| GROUPS | Groups for Business |
| MEET | Meet |
| SITES | Sites |
The `<policy-number>` has the format `<section>.<item>`,
where `<section>` is the number of the section in the
baseline for the application and `<item>` is the number of
the specific requirement in the section.
The `<baseline-version>` is derived from the ScubaGoggles
version number: `<major>.<minor>`.
### Policy Identifiers in Markdown
Policy identifiers are used throughout the baseline
Markdown documents. Because the identifiers contain
the baseline version, the identifiers must be changed
when the ScubaGoggles version number changes (except
for the build number component).
Changes to the policy identifiers due to the ScubaGoggles
version number changing is handled by the
`scubagoggles version` command (the functionality is
implemented in the `Version` class). There is no
manual editing necessary in the Markdown files when the
ScubaGoggles version number changes.
### Policy Identifiers in Rego Code
Policy identifiers are also used in the Rego code as
string values in variables. The `PolicyIdWithSuffix`
function, defined in `utils.rego`, is used to avoid the
necessity of making changes to all Rego files when the
ScubaGoggles version number changes.
The `PolicyIdWithSuffix` function takes a single string
argument, which is the policy identifier without the
baseline version. The function adds the current baseline
version to the end of the string to form the complete
policy identifier.
This is an example of specifying a policy identifier in
the Rego code:
```
PolicyId := utils.PolicyIdWithSuffix("GWS.CALENDAR.1.1")
```
Don't specify the complete policy identifier in comments.
There is no need to include the baseline version in the
identifier if it's necessary to reference a policy in the
comments. Including the baseline version requires a manual change
if the ScubaGoggles version changes and opens the possibility of
forgetting to make the changes.
```
# No version suffix in the policy identifier comment:
# Baseline GWS.CHAT.1.2
#--
```
The `scubagoggles version` command updates the single hard-coded
baseline version number in the `PolicyIdWithSuffix` function definition
in `utils.rego`.
## Upgrading ScubaGoggles Version
Upgrading the ScubaGoggles version is done entirely by running the
`scubagoggles version` command with the `--upgrade` option. This sets the
new version number and modifies all Markdown files and the `utils.rego` file
to replace the baseline version numbers.
The following example shows a version upgrade to 1.0.0 with debug
logging enabled. The debug output shows the files read and indicates
any changes by showing the line number and the new content of
the line.
```shell
> scubagoggles -log debug version --upgrade 1.0.0
ScubaGoggles version upgrade (1.0.0)
(INFO): changing ScubaGoggles version to 1.0.0
(DEBUG): C:\scubaDev\scubagoggles\rego\Utils.rego
(DEBUG): C:\scubaDev\scubagoggles\rego\Utils.rego:
(DEBUG): 9) BaseVersionSuffix = "v1.0"
(DEBUG): C:\scubaDev\scubagoggles\baselines\calendar.md
...
```
After the version upgrade, the ScubaGoggles Git repository will indicate
the modified files. To permanently include the version changes, the
files must be committed to the repository.
```
> git status
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: scubagoggles/__init__.py
modified: scubagoggles/baselines/calendar.md
modified: scubagoggles/baselines/chat.md
modified: scubagoggles/baselines/classroom.md
modified: scubagoggles/baselines/commoncontrols.md
modified: scubagoggles/baselines/drive.md
modified: scubagoggles/baselines/gmail.md
modified: scubagoggles/baselines/groups.md
modified: scubagoggles/baselines/meet.md
modified: scubagoggles/baselines/sites.md
modified: scubagoggles/rego/Utils.rego
...
> git add --update
> git commit -m 'version upgrade to 1.0.0'
```
## Checking Version Number Consistency
When the `scubagoggles version` command is invoked with the `--check`
option, all Markdown files and the `utils.rego` file are checked for
version numbers consistent with the current ScubaGoggles version number
defined in `scubagoggles/__init__.py`. If any inconsistencies are found,
the file name and line(s) (with line number(s)) are displayed.
```
> scubagoggles version --check
ScubaGoggles version check
```

View File

@@ -1,56 +1,208 @@
# Download and Python Install
> [!NOTE]
> Previously installed a different version of ScubaGoggles? See [Upgrading ScubaGoggles](/docs/upgrading/Upgrading.md#upgrading-scubagoggles).
## Downloading the Latest Release
To download ScubaGoggles:
1. Click [here](https://github.com/cisagov/ScubaGoggles/releases) to see the latest release.
2. Click scubagoggles-[latest-version].zip to download the release.
3. Extract the folder in the zip file.
## Installing Python Dependencies
As of ScubaGoggles v0.3.0, the minimum required Python version to run the tool is `3.10.x`. While it's possible that ScubaGoggles may work with different versions of Python, 3.10 is the version we've tested and ensured works with the versions of the modules listed in ScubaGoggles' [dependencies](../../requirements.txt).
### Installing in a Virtual Environment
The following commands are used to set up a python virtual environment (venv) to install the needed python dependencies.
Inside the release or repo folder, open up a terminal and run the following commands based on your OS.
> [!NOTE]
> Depending on the Python installation and operating system, it might be necessary to use `pip3` and `python3` instead of `pip` and `python`.
#### Windows
```
pip install virtualenv
python -m venv .venv
.venv\Scripts\activate
```
#### macOS
```
pip install virtualenv
virtualenv -p python .venv
source .venv/bin/activate
```
Users can run the tool via the `scuba.py` script as a developer or by installing the `scubagoggles` package in a python venv.
Choose either of these next steps to install the needed python dependencies in the `venv`.
#### Installing dependencies for running scubagoggles directly
In the root directory of the release/repo, install the `scubagoggles` package and dependencies with the following command.
```
python -m pip install .
```
#### Installing dependencies for running via scuba.py script
In the root directory of the release/repo, install the the required dependencies with the following command.
```
pip install -r requirements.txt
```
> [!IMPORTANT]
> Users will need to rerun the `activate` script from the OS specific directions above in each new terminal session to reactivate the `venv` containing the dependencies.
## Navigation
- Continue to [Download the OPA executable](/docs/installation/OPA.md)
- Return to [Documentation Home](/README.md)
# Getting started
> [!IMPORTANT]
> Use of this tool requires access to an internet browser for initial setup
> and to view the html report output.
Setting up to run ScubaGoggles for the first time involves the following steps:
1. Install [Python 3](https://www.python.org/) on your system.
2. (Optional) Create and activate a Python virtual environment.
3. Install ScubaGoggles and dependencies into the Python environment.
4. Run `scubagoggles setup` to specify the output directory, the location of the
OPA executable, and the credentials file. By default, the setup will
download the Open Policy Agent (OPA)
executable.
5. Create a Google OAuth credential file, unless you'll be using a Google
service account.
## Install Python 3
Running ScubaGoggles requires Python 3.9 or higher. If Python is not installed
in your environment, please visit the [Python website](https://www.python.org/)
for instructions on how to download and install Python.
A 64-bit operating system is required. While Python will run in a 32-bit
environment, the Open Policy Agent (OPA) required for ScubaGoggles is only
available on 64-bit platforms.
Depending on the operating system, the command to invoke Python from the command
line is either `python` (Windows) or `python3` (linux & macOS, for backward
compatibilty with Python version 2). You will need access to a command line,
via the command window or a PowerShell window for Windows, or a terminal window
in linux & macOS.
## Installing in a Python Virtual Environment
A Python virtual environment dedicated to ScubaGoggles isn't strictly
necessary, but it is recommended because it will allow you to isolate
ScubaGoggles and its dependencies from other Python tools you may have running
on your system. With a virtual environment, you create it only once, but you
will need to "activate" it in a new window (i.e., process) prior to running
ScubaGoggles. A virtual environment remains activated until the window is
closed (unless you explicitly deactivate the virtual environment).
The following commands are used to set up a python virtual environment using
the `venv` Python module. Create a window where you may enter commands on your
system.
Use the `cd` (change directory) command to set the current working directory to
the location where you want to create the virtual environment directory. In
this example, the directory that will be created is called `scuba-env`, but
you may use a different name.
The following examples show both the command to create the virtual environment,
followed by the command that activates the virtual environment in your current
session. The commands differ slightly depending on the operating system and
type of command window.
**Note** the command that activates the virtual environment. You will need this
command whenever you create a new session (i.e., terminal) where you will be
running ScubaGoggles.
### Windows
#### Windows Command
```
python -m venv scuba-env
scuba-env\Scripts\activate.bat
```
#### Windows PowerShell
```
python -m venv scuba-env
scuba-env\Scripts\activate.ps1
```
#### Windows Git Bash
```
python -m venv scuba-env
source scuba-env/Scripts/activate
```
### linux and macOS
```
python3 -m venv scuba-env
source scuba-env/bin/activate
```
## Downloading the Latest ScubaGoggles Release
To download ScubaGoggles, click [here](https://github.com/cisagov/ScubaGoggles/releases)
to display the download site in a browser. For installing ScubaGoggles as a
user (and not a developer), you should download the file with the name ending
in `.whl` (known as a Python "wheel" file), for example
`scubagoggles-1.0.0-py3-none-any.whl`.
If you are a developer, you may alternatively download the "gzipped tar" file
(file ending with `.tar.gz`), or zip file (file ending with `.zip`). You may
also clone the GitHub repository. The instructions that follow focus on the
installation for the general user.
### Installing ScubaGoggles
ScubaGoggles is installed as a Python package, whether you are using a virtual
environment or the system's Python environment (if you have write access to it).
Install ScubaGoggles using Python's `pip` utility. If you are using a virtual
environment, make sure your current session has activated the virtual
environment. Normally, the command you use is `pip` or `pip3`.
```
pip install scubagoggles-1.0.0-py3-none-any.whl
```
where you will replace `scubagoggles-1.0.0-py3-none-any.whl` in the above
command with the location and/or name of the ScubaGoggles wheel file you
downloaded.
This command will install ScubaGoggles and all its dependencies. The system on
which ScubaGoggles is installed must be able to access the internet so the
dependencies may be downloaded.
## Creating the ScubaGoggles Output Directory
ScubaGoggles produces "Secure Baseline Conformance Reports", which are written
to a directory on your system. In addition, ScubaGoggles requires the OPA
executable and the Google credentials file. It is recommended that you create
a directory that will contain these required files and serve as a location
for the reports. You will run the ScubaGoggles setup utility to indicate the
location of the output directory.
## ScubaGoggles Setup Utility
The ScubaGoggles setup utility lets you configure the data directory location,
as well as the locations of the OPA executable and the Google credentials file.
It is perfectly fine to locate the OPA executable and credentials files in the
output directory you create. Unless you specify otherwise, the OPA executable
will be downloaded to the location you specify.
When you run the setup utility, it will create a configuration file in your
top-level user directory called `.scubagoggles` (**Note** the leading dot (.)
in the file name, which indicates a "hidden" file on linux and macOS operating
systems).
The configuration file contains the following values used by ScubaGoggles when
running the conformance assessments:
| Name | Description |
|-------------|---------------------------------------------------|
| credentials | Location and name of the Google credentials file. |
| opa_dir | Location of the OPA executable. |
| output_dir | Location of the ScubaGoggles output directory. |
Run the setup utility with this command:
```shell
scubagoggles setup
```
You will be prompted to enter the output directory, location of the OPA
executable, and the location and name of the Google credentials file. By
default, the OPA executable will be downloaded into the directory you specify.
You do not have to create the Google credentials file before running setup. If
the credentials file doesn't exist, you will see a warning indicating that it is
missing. You will need to have the credentials file before running the
conformance assessment. See the [instructions for creating a credentials
file](../authentication/AuthenticationMethods.md).
These are sample outputs from running the setup utility before the required
files are available. Warnings are shown, but the `.scubagoggles` configuration
file is still created.
### Windows Example
```
> scubagoggles setup
Setup: output directory
Scubagoggles output directory [C:\Users\userID\scubagoggles]?
Create directory C:\Users\userID\scubagoggles [Yes/no]?
creating: C:\Users\userID\scubagoggles
C:\Users\userID\scubagoggles
Setup: OPA executable directory
(WARNING): OPA executable not found in PATH
Location of OPA executable [C:\Users\userID\scubagoggles]?
downloading: opa_windows_amd64.exe
OPA executable: C:\Users\userID\scubagoggles\opa_windows_amd64.exe
Setup: Google API credentials file
Google credentials (JSON) file [C:\Users\userID\scubagoggles\credentials.json]?
(WARNING): Google credentials file not found in C:\Users\userID\scubagoggles\credentials.json
```
### Linux Example
```
$ scubagoggles setup
Setup: output directory
Scubagoggles output directory [/home/userID/scubagoggles]?
Create directory /home/userID/scubagoggles [Yes/no]?
creating: /home/userID/scubagoggles
/home/userID/scubagoggles
Setup: OPA executable directory
(WARNING): OPA executable not found in PATH
Location of OPA executable [/home/userID/scubagoggles]?
downloading: opa_linux_amd64_static
OPA executable: /home/userID/scubagoggles/opa_linux_amd64_static
Setup: Google API credentials file
Google credentials (JSON) file [/home/userID/scubagoggles/credentials.json]?
(WARNING): Google credentials file not found in /home/userID/scubagoggles/credentials.json
```
## Navigation
- Continue to [Download the OPA executable](OPA.md)
- Return to [Documentation Home](/README.md)

View File

@@ -1,43 +1,66 @@
# Download the OPA executable
The tool makes use of [Open Policy Agent's Rego Policy language](https://www.openpolicyagent.org/docs/latest/policy-language/).
An OPA executable is required to execute this tool and can be downloaded using our `download_opa.py` script.
```
python download_opa.py --help
usage: download_opa.py [-h] [-v] [-os]
Download executable the OPA executable file required to run this SCuBA tool.
options:
-h, --help show this help message and exit
-v {0.45.0,0.46.3,0.47.4,0.48.0,0.49.2,0.50.2,0.51.0,0.52.0,0.53.1,0.54.0,0.55.0,0.56.0,0.57.1,0.58.0,0.59.0,0.60.0}
What version of OPA to download: Default version: 0.59.0
-os {windows,macos,linux}
Operating system version of OPA to download. Default os: windows
--disablessl If there are proxy errors, try adding this switch to disable ssl verification
```
```
# example
python download_opa.py -v 0.60.0 -os macos
```
1. If the above script can not execute for any reason or you would prefer to download OPA manually, go to the [Open Policy Agent website](https://www.openpolicyagent.org/docs/latest/#running-opa)
2. Check the website for a compatible OPA version (Currently v0.45.0 and above) for ScubaGoggles and select the corresponding version on top left of the website
3. Navigate to the menu on left side of the screen: `Introduction -> Running OPA -> Download OPA`
4. Follow the instructions for downloading the respective OPA executable for your OS.
> [!NOTE]
> The following notes apply only for MAC and Linux users.
- By default on MAC and Linux systems the OPA executable will be run with `sudo`.
- Use the `scubagoggles gws --omitsudo` flag to omit running the executable with `sudo`.
- MAC and Linux OS users should have their OPA executables named `opa_darwin_amd64` or `opa_linux_amd64_static` respectively for scubagoggles execution.
- The OPA executable must also be given execute permissions
- Run the following command to give the opa executable execute permissions:
```bash
chmod +x opa_darwin_amd64
```
## Navigation
- Continue to [Prerequisites](/docs/prerequisites/Prerequisites.md)
- Return to [Documentation Home](/README.md)
# Download the OPA executable
The tool makes use of [Open Policy Agent's Rego Policy language]
(https://www.openpolicyagent.org/docs/latest/policy-language/). By default,
the `scubagoggles setup` command downloads the OPA executable. You will only
need to download the OPA executable separately if you need a **specific**
version. Otherwise, you may skip this step and continue to
[Prerequisites](../prerequisites/Prerequisites.md).
You may download the OPA executable, to either upgrade the version you
currently have or use a specific version, using the `scubagoggles getopa`
command:
```
scubagoggles getopa --help
usage: scubagoggles getopa [-h] [--nocheck] [--force] [--version <OPA-version>] [--opa_directory <directory>]
Download OPA executable
options:
-h, --help show this help message and exit
--nocheck, -nc Do not check hash code after download
--force, -f Overwrite existing OPA executable
--version <OPA-version>, -v <OPA-version>
Version of OPA to download (default: latest version)
--opa_directory <directory>, -r <directory>
Directory containing OPA executable (default: location established by setup)
```
```bash
# example
scubagoggles getopa -v v0.60.0
```
If you have run the [ScubaGoggles setup utility](DownloadAndInstall.md#ScubaGoggles-Setup-Utility),
you will have specified the location of the OPA executable. This location is
used by `getopa` when downloading the OPA executable. Optionally, you may
download the executable to a location that is in the PATH environment variable.
## Downloading the OPA Executable from the OPA Website
1. If the above script can not execute for any reason or you would prefer to
download OPA manually, go to the [Open Policy Agent website]
(https://www.openpolicyagent.org/docs/latest/#running-opa)
2. Check the website for a compatible OPA version (Currently v0.45.0 and above)
for ScubaGoggles and select the corresponding version on top left of the
website.
3. Navigate to the menu on left side of the screen:
`Introduction -> Running OPA -> Download OPA`
4. Follow the instructions for downloading the respective OPA executable for
your OS.
> [!NOTE]
> For linux and macOS, you must make sure the OPA executable has execute
> permission. If you downloaded the OPA executable either during the setup
> process or using the `getopa`subcommand, the permission has already been set
> correctly.
```bash
# give the opa executable execute permissions
chmod u+x opa
```
## Navigation
- Continue to [Prerequisites](../prerequisites/Prerequisites.md)
- Return to [Documentation Home](/README.md)

View File

@@ -1,25 +1,29 @@
# Prerequisites
## Permissions
The tool uses the following OAUTH API scopes:
```
https://www.googleapis.com/auth/admin.reports.audit.readonly,
https://www.googleapis.com/auth/admin.directory.domain.readonly,
https://www.googleapis.com/auth/admin.directory.group.readonly,
https://www.googleapis.com/auth/admin.directory.orgunit.readonly,
https://www.googleapis.com/auth/admin.directory.user.readonly,
https://www.googleapis.com/auth/apps.groups.settings
```
When running ScubaGoggles for the first time you will be prompted to consent to these API scopes. Users with the Super Admin role automatically have the privilege to consent to these scopes. A custom admin role can also be made with the minimum permissions to consent to these scopes. See this [Google Admin SDK Prerequisites guide](https://developers.google.com/admin-sdk/reports/v1/guides/prerequisites) for more information.
## Create a Project
1. If you already have a Google Cloud Project that you want to utilize skip to [Authentication Methods](/docs/authentication/AuthenticationMethods.md)
2. Otherwise start by signing into http://console.cloud.google.com/.
3. Follow the [directions outlined in this guide to create a project](https://developers.google.com/workspace/guides/create-project)
## Navigation
- Continue to [Authentication Methods](/docs/authentication/AuthenticationMethods.md)
- Return to [Documentation Home](/README.md)
# Prerequisites
## Permissions
The tool uses the following OAUTH API scopes:
```
https://www.googleapis.com/auth/admin.reports.audit.readonly,
https://www.googleapis.com/auth/admin.directory.domain.readonly,
https://www.googleapis.com/auth/admin.directory.group.readonly,
https://www.googleapis.com/auth/admin.directory.orgunit.readonly,
https://www.googleapis.com/auth/admin.directory.user.readonly,
https://www.googleapis.com/auth/apps.groups.settings,
https://www.googleapis.com/auth/cloud-identity.policies.readonly
```
When running ScubaGoggles for the first time you will be prompted to consent to
these API scopes. Users with the Super Admin role automatically have the
privilege to consent to these scopes. When running ScubaGoggles for the first
time you will be prompted to consent to these API scopes.
## Create a Project
1. If you already have a Google Cloud Project that you want to utilize skip to [Authentication Methods](../authentication/AuthenticationMethods.md)
2. Otherwise start by signing into http://console.cloud.google.com/.
3. Follow the [directions outlined in this guide to create a project](https://developers.google.com/workspace/guides/create-project)
## Navigation
- Continue to [Authentication Methods](../authentication/AuthenticationMethods.md)
- Return to [Documentation Home](/README.md)

View File

@@ -1,74 +1,85 @@
# Troubleshooting
## Lots of Manual Checks
The report output by ScubaGoggles may indicate that many manual checks are needed (e.g., https://github.com/cisagov/ScubaGoggles/issues/260). This is a symptom of ScubaGoggles' primary limitation. As the API calls to check most of the settings relevant to ScubaGoggles are have not been made public by Google, ScubaGoggles relies on [GWS Admin log events](https://support.google.com/a/answer/4579579?hl=en) to determine the current state. If there are no log events corresponding to a SCuBA baseline policy (e.g., because the setting hasn't been changed within the past 6 months), ScubaGoggles will indicate that the setting needs to be checked manually. See [Limitations](/docs/usage/Limitations.md) for more details.
## Not Authorized to Access This Resource
If an authorization error similar to the one below appears:
```
/Users/scubagoggles/provider.py:463: RuntimeWarning: An exception was thrown trying to get the tenant info:
<HttpError 403 when requesting https://admin.googleapis.com/admin/directory/v1/customers/my_customer?alt=json returned "Not Authorized to access this resource/api">
```
Ensure that you consented to the following API scopes as a user with the proper [permissions to consent](/docs/prerequisites/Prerequisites.md#permissions) and have enabled the required [APIs and Services](/docs/authentication/OAuth.md).
## Scubagoggles Not Found
If an error similar to the one below appears:
```
command not found: scubagoggles
```
Ensure that you have properly [configured the virtual environment](/docs/installation/DownloadAndInstall.md#installing-in-a-virtual-environment) and have activated the virtual environment using the OS appropriate commands.
Alternatively, to run scubagoggles without installing it as a package, you can replace the `scubagoggles` command with `python scuba.py`.
## Unable to view HTML report due to environment limitations
If you are unable to view the HTML report in a browser window, the results of the conformance scan can be viewed in their raw JSON format.
We recommend running the conformance report in quiet mode to stop the web browser from being opened automatically. This can be done with the `--quiet` parameter:
```scubagoggles gws --quiet```
Once the scan is complete, navigate to the output folder. Within the output folder, we can access the generated HTML reports, or view the results in JSON format.
To view the results as JSON, open the `ScubaResults.json` file.
The output will resemble the following:
```
{
"Summary": {
"Gmail": {
"Manual": 26,
"Passes": 9,
"Errors": 0,
"Failures": 6,
"Warnings": 2
},
"Groups for Business": {
"Manual": 0,
"Passes": 6,
"Errors": 0,
"Failures": 0,
"Warnings": 1
}
},
"Results": {
"Gmail": [
{
"GroupName": "Mail Delegation",
"GroupNumber": "1",
"Controls": [
{
"Control ID": "GWS.GMAIL.1.1v0.2",
"Requirement": "Mail Delegation SHOULD be disabled.",
"Result": "Pass",
"Criticality": "Should",
"Details": "Requirement met in all OUs and groups."
}
...
```
## Navigation
- Return to [Documentation Home](/README.md)
# Troubleshooting
## Not Authorized to Access This Resource
If an authorization error similar to the one below appears:
```
RuntimeWarning: An exception was thrown trying to get the tenant data:
<HttpError 403 ... returned "Not Authorized to access this resource/api">
```
Ensure that you consented to the following API scopes as a user with the proper
[permissions to consent](../prerequisites/Prerequisites.md#permissions) and have
enabled the required [APIs and Services](../authentication/OAuth.md).
## Windows: WinError 10013: Permission Error
When ScubaGoggles is run and it needs to re-authorize you using your Google
credentials, it makes a connection using port 8080. If you receive a permission
error with the text `An attempt was made to access a socket in a way forbidden
by its access permissions`, it is likely that another process on your system is
using that port.
The following PowerShell command, when run as an Adminstrator, may help to
locate the process using the port. Once you've determined how the port is
being used, you can evaluate whether something may be done to temporarily
relinquish the port for ScubaGoggles use or whether you might need to try
running ScubaGoggles on a system where the port is available.
```
Get-Process -Id (Get-NetTCPConnection -LocalPort 8080).OwningProcess
```
## Unable to view HTML report due to environment limitations
If you are unable to view the HTML report in a browser window, the results of
the conformance scan can be viewed in their raw JSON format.
We recommend running the conformance report in quiet mode to stop the web
browser from being opened automatically. This can be done with the `--quiet`
parameter:
```scubagoggles gws --quiet```
Once the scan is complete, navigate to the output folder. Within the output
folder, you can access the generated HTML reports, or view the results in JSON
format.
To view the results as JSON, open the `ScubaResults.json` file.
The output will resemble the following:
```json
{
"Summary": {
"sites": {
"Manual": 0,
"Passes": 1,
"Errors": 0,
"Failures": 0,
"Warnings": 0,
"Omit": 0
}
},
"Results": {
"sites": [
{
"GroupName": "Sites Service Status",
"GroupNumber": "1",
"GroupReferenceURL": "https://github.com/cisagov...",
"Controls": [
{
"Control ID": "GWS.SITES.1.1",
"Requirement": "Sites Service SHOULD be disabled for all users.",
"Result": "Pass",
"Criticality": "Should",
"Details": "Requirement met in all OUs and groups."
}
]
}
]
},...
```
## Navigation
- Return to [Documentation Home](/README.md)

View File

@@ -1,22 +1,20 @@
# Upgrading and Maintenance
## Upgrading ScubaGoggles
Assuming you installed ScubaGoggles as described in [Download and Install](/docs/installation/DownloadAndInstall.md), upgrading to the lastest version of ScubaGoggles should be as simple as:
- Repeating the steps described in [Download and Install](/docs/installation/DownloadAndInstall.md) with the new release.
- Making the OPA executable available, by either:
- downloading the executable again as described in [Download the OPA executable](/docs/installation/OPA.md),
- copying the executable from the old release folder to the new release folder, or
- using the `--opapath` parameter to tell ScubaGoggles where to look for the executable.
- Making your credentials available, by either:
- copying your `credentials.json` file to the new release folder or
- using the `--credentials` parameter to tell ScubaGoggles where to look for your credentials.
If instead you cloned the ScubaGoggles repo and wish to run ScubaGoggles on the latest code from main (only recommended for development purposes), be sure to run `python -m pip install .` inside the ScubaGoggles directory after pulling the latest code.
## Upgrading OPA
While new versions of OPA are periodically released, it is only necessary to upgrade OPA if the version you have locally is unsupported. Running `python download_opa.py --help` lists the supported OPA versions.
Upgrading OPA is as simple as downloading the desired executable, which can be done by running the `download_opa.py` script again. See [Download the OPA executable](/docs/installation/OPA.md) for detailed instructions.
## Navigation
- Return to [Documentation Home](/README.md)
# Upgrading and Maintenance
## Upgrading ScubaGoggles
To upgrade ScubaGoggles to a newer version, you simply download the latest
[release package](../installation/DownloadAndInstall.md#downloading-the-latest-scubagoggles-release),
and [install](../installation/DownloadAndInstall.md#installing-scubagoggles)
it using Python's `pip` utility. If you are using a Python virtual environment, make sure you have activated the virtual
environment before upgrading.
## Upgrading OPA
To upgrade the OPA executable, re-run the `scubagoggles getopa`
command, which will download the latest version to the directory
specified with `scubagoggles setup`. You may also download a
particular version of OPA using the `--version` option. See
[here](../installation/OPA.md) for details.
## Navigation
- Return to [Documentation Home](/README.md)

View File

@@ -1,39 +1,51 @@
# Usage: Config File
All ScubaGoggles [parameters](/docs/usage/Parameters.md) can be placed into a configuration file in order to made execution easier. The path of the file is specified by the `--config` parameter, and its contents are expected as YAML.
> [!NOTE]
> If a parameter is specified both on the command-line and in a configuration file, the command-line parameter has precedence over the config file.
## Sample Configuration Files
[Sample config files](/sample-config-files) are available in the repo and are discussed below. When executing ScubaGoggles, only a single config file can be read in; we recommend looking through the following examples and constructing a config file that best suits your use case.
### Basic Usage
The [basic use](/sample-config-files/basic_config.yaml) example config file specifies the `outpath`, `baselines`, and `quiet` parameters.
ScubaGoggles can be invoked with this config file:
```
scubagoggles gws --config basic_config.yaml
```
It can also be invoked while overriding the `baselines` parameter.
```
scubagoggles gws --config basic_config.yaml -b gmail chat
```
### Omit Policies
In some cases, it may be appropriate to omit specific policies from ScubaGoggles evaluation. For example:
- When a policy is implemented by a third-party service that ScubaGoggles does not audit.
- When a policy is not applicable to your organization (e.g., policy GWS.GMAIL.4.3v0.3, which is only applicable to federal, executive branch, departments and agencies).
The `omitpolicy` top-level key, shown in this [example ScubaGoggles configuration file](/sample-config-files/omit_policies.yaml), allows the user to specify the policies that should be omitted from the ScubaGoggles report. Omitted policies will show up as "Omitted" in the HTML report and will be colored gray. Omitting policies must only be done if the omissions are approved within an organization's security risk management process. **Exercise care when omitting policies because this can inadvertently introduce blind spots when assessing your system.**
For each omitted policy, the config file allows you to indicate the following:
- `rationale`: The reason the policy should be omitted from the report. This value will be displayed in the "Details" column of the report. ScubaGoggles will output a warning if no rationale is provided.
- `expiration`: Optional. A date after which the policy should no longer be omitted from the report. The expected format is yyyy-mm-dd.
## Navigation
- Continue to [Usage: Examples](/docs/usage/Examples.md)
- Return to [Documentation Home](/README.md)
# Usage: Config File
All ScubaGoggles [parameters](Parameters.md) can be placed into a configuration file in order to made execution easier. The path of the file is specified by the `--config` parameter, and its contents are expected as YAML.
> [!NOTE]
> If a parameter is specified both on the command-line and in a configuration file, the command-line parameter has precedence over the config file.
## Sample Configuration Files
[Sample config files](../../scubagoggles/sample-config-files) are available in the
repo and are discussed below. When executing ScubaGoggles, only a single config
file can be read in; we recommend looking through the following examples and
constructing a config file that best suits your use case.
### Basic Usage
The [basic use](../../scubagoggles/sample-config-files/basic_config.yaml) example
config file specifies the `outpath`, `baselines`, and `quiet` parameters.
ScubaGoggles can be invoked with this config file:
```
scubagoggles gws --config basic_config.yaml
```
It can also be invoked while overriding the `baselines` parameter.
```
scubagoggles gws --config basic_config.yaml -b gmail chat
```
### Omit Policies
In some cases, it may be appropriate to omit specific policies from ScubaGoggles evaluation. For example:
- When a policy is implemented by a third-party service that ScubaGoggles does not audit.
- When a policy is not applicable to your organization (e.g., policy GWS.GMAIL.4.3, which is only applicable to federal, executive branch, departments and agencies).
The `omitpolicy` top-level key, shown in this [example ScubaGoggles
configuration file](../../scubagoggles/sample-config-files/omit_policies.yaml),
allows the user to specify the policies that should be omitted from the
ScubaGoggles report. Omitted policies will show up as "Omitted" in the HTML
report and will be colored gray. Omitting policies must only be done if the
omissions are approved within an organization's security risk management
process. **Exercise care when omitting policies because this can inadvertently
introduce blind spots when assessing your system.**
For each omitted policy, the config file allows you to indicate the following:
- `rationale`: The reason the policy should be omitted from the report. This value will be displayed in the "Details" column of the report. ScubaGoggles will output a warning if no rationale is provided.
- `expiration`: Optional. A date after which the policy should no longer be omitted from the report. The expected format is yyyy-mm-dd.
## Navigation
- Continue to [Usage: Examples](Examples.md)
- Return to [Documentation Home](/README.md)

View File

@@ -1,49 +1,54 @@
# Usage: Examples
> [!Note]
> If you chose not install the `scubagoggles` package in a venv but do have the dependencies installed from `requirements.txt`, you may execute the tool using the `scuba.py` script located in the root directory of this repository. Replace any `scubagoggles` directions with `python scuba.py`
## Example 1: Run an assessment against all GWS products
```
scubagoggles gws
```
## Example 2: Run an assessment against just Gmail and Google Calendar
```
scubagoggles gws -b gmail calendar
```
## Example 3: Run an assessment and store the results under a folder called output
```
scubagoggles gws -b calendar gmail groups chat meet sites -o ./output
```
## Example 4: Do a run cached assessment
```
# skip authentication and provider export stage
# used for running against a cached provider json
scubagoggles gws --runcached --skipexport
```
## Example 5: Run with a service account on a different tenant
```
scubagoggles gws --customerid <customer_id> --subjectemail admin@example.com
```
See the `help` options yourself
```
scubagoggles gws -h
```
## Example 6: Run with a config file
```
scubagoggles gws --config sample-config-files/basic_config.yaml
```
> [!NOTE]
> In all the above examples, the html report should open automatically. If not, navigate to the output folder and open the `*.html` file using a browser of your choice. The json output will also be located in this folder.
## Navigation
- Continue to [Reviewing Output](/docs/usage/ReviewOutput.md)
- Return to [Documentation Home](/README.md)
# Usage: Examples
## Example 1: Run an assessment against all GWS products
```
scubagoggles gws
```
## Example 2: Run an assessment against just Gmail and Google Calendar
```
scubagoggles gws -b gmail calendar
```
## Example 3: Run an assessment and store the results under a folder called output
```
scubagoggles gws -b calendar gmail groups chat meet sites -o ./output
```
## Example 4: Do a run cached assessment
```
# skip authentication and provider export stage
# used for running against a cached provider json
scubagoggles gws --runcached --skipexport
```
## Example 5: Run with a service account on a different tenant
```
scubagoggles gws --customerid <customer_id> --subjectemail admin@example.com
```
See the `help` options yourself
```
scubagoggles gws -h
```
## Example 6: Run with a config file
```
scubagoggles gws --config sample-config-files/basic_config.yaml
```
> [!NOTE]
> In all the above examples, the html report should open automatically. If not, navigate to the output folder and open the `*.html` file using a browser of your choice. The json output will also be located in this folder.
> [!NOTE]
> The following is intended for developers **ONLY**:
> If you chose not install the `scubagoggles` package in a venv but do have the
> dependencies installed from `requirements.txt`, you may execute the tool using
> the `scuba.py` script located in the root directory of this repository.
> Replace any `scubagoggles` directions with `python scuba.py`
## Navigation
- Continue to [Reviewing Output](ReviewOutput.md)
- Return to [Documentation Home](/README.md)

View File

@@ -1,11 +1,35 @@
# Limitations
The majority of the conformance checks done by ScubaGoggles rely on [GWS Admin log events](https://support.google.com/a/answer/4579579?hl=en). If there is no log event corresponding to a SCuBA baseline policy, ScubaGoggles will indicate that the setting currently can not be checked on its HTML report output. In this situation, we recommend you manually review your GWS security configurations with the SCuBA security baselines.
Additionally, some events will not be visible due to data retention time limits, as the admin logs are only retained for 6 months (see [Data retention and lag times](https://support.google.com/a/answer/7061566)). However, if you wish to generate a log event for testing ScubaGoggles' capabilities, follow the implementation instructions in the [SCuBA GWS baseline documents](/baselines/README.md) to change your GWS configuration settings. Toggling certain settings, off and on will be enough to generate a log event. Other settings will require implementing more substantive configuration changes.
Many controls can be scoped down to the organizaitonal unit (OU) or group level. ScubaGoggles is capable of checking settings applied at these levels. However, for any setting that can be scoped to specific OUs or groups, ScubaGoggles asserts that at least one event is present for the organization's top-level OU. If no event can be found for the top-level OU, ScubaGoggles will not display any results for that control and instead display a warning, such as the following:
![image](https://github.com/cisagov/ScubaGoggles/assets/106177711/e3bf7925-8c00-489d-8e79-262e861bd1a8)
## Navigation
- Return to [Documentation Home](/README.md)
# Limitations
While most of the conformance checks done by ScubaGoggles rely on Google's Policy
API that provides direct access to your GWS settings, some settings are not
available from this API. For a few comformance checks where the corresponding
settings are not provided by the Policy API, we try to determine the settings
using [GWS Admin log events](https://support.google.com/a/answer/4579579?hl=en).
## Log Event Limitations
For these cases, if there is no log event corresponding to a SCuBA baseline
policy, ScubaGoggles will indicate that the setting currently can not be checked
on its HTML report output. In this situation, we recommend you manually review
your GWS security configurations with the SCuBA secure baselines.
Additionally, some events will not be visible due to data retention time limits,
as the admin logs are only retained for 6 months
(see [Data retention and lag times](https://support.google.com/a/answer/7061566)).
However, if you wish to generate a log event for testing ScubaGoggles'
capabilities, follow the implementation instructions in the
[SCuBA GWS baseline documents](../../scubagoggles/baselines/README.md) to change your GWS
configuration settings. Toggling certain settings, off and on will be enough to
generate a log event. Other settings will require implementing more substantive
configuration changes.
Many controls can be scoped down to the organizational unit (OU) or group level.
ScubaGoggles is capable of checking settings applied at these levels. However,
for any setting that can be scoped to specific OUs or groups, ScubaGoggles
asserts that at least one event is present for the organization's top-level OU.
If no event can be found for the top-level OU, ScubaGoggles will not display
any results for that control and instead display a warning, such as the following:
![image](https://github.com/cisagov/ScubaGoggles/assets/106177711/e3bf7925-8c00-489d-8e79-262e861bd1a8)
## Navigation
- Return to [Documentation Home](/README.md)

View File

@@ -1,58 +1,75 @@
# Usage: Parameters
Execute the ScubaGoggles tool using the `scubagoggles` command. For GWS, all commands will be under the `gws` subparser.
```
scubagoggles gws -h
usage: scubagoggles gws [-h] [-b [...]] [-o] [-c] [--subjectemail] [--customerid] [--opapath] [--regopath] [--documentpath]
[--runcached] [--skipexport] [--outputfoldername] [--outputproviderfilename]
[--outputregofilename] [--outputreportfilename] [--omitsudo] [--quiet] [--debug]
optional arguments:
-h, --help show this help message and exit
-b [ ...], --baselines [ ...]
A list of one or more abbreviated GWS baseline names that the tool will assess. Defaults to
all baselines. Choices: gmail, calendar, groups, chat, drive, meet, sites, commoncontrols,
rules, classroom
-o , --outputpath The folder path where both the output JSON & HTML report will be created. Defaults to "./" The
current directory.
-c , --credentials The relative path and name of the OAuth / service account credentials json file. Defaults to
"./credentials.json" which means the tool will look for the file named credentials.json in the
current directory.
--config Local file path to a YAML formatted configuration file. Configuration file parameters can be
used in place of command-line parameters. Additional parameters and variables not available
on the command line can also be included in the file that will be provided to the tool for
use in specific tests.
--outjsonfilename The name of the file that encapsulates all assessment output. Defaults to ScubaResults.
--subjectemail Only applicable when using a service account. The email address of a user the service account
should act on behalf of. This user must have the necessary privileges to run scubagoggles.
--customerid The customer ID the tool should run on. Defaults to "my_customer" which will be the domain of
the user / service account authenticating.
--opapath The relative path to the directory containing the OPA executable. Defaults to "./" the current
executing directory.
--regopath The relative path to the directory contain the folder containing the rego files. Defaults to
"./rego" the "rego" folder inside the current executing directory.
--documentpath The relative path to the directory containing the SCuBA baseline documents. Defaults to
"./baselines" the "baselines" folder inside the current executing directory.
--runcached This switch when added will run in the tool in "RunCached mode". When combined with -sa allows
to the user to skip authentication and provider export.
--skipexport This switch when added will skip the provider export.To be used in conjunction with
--runcached.
--outputfoldername The name of the folder created in --outputpath where both the output JSON and the HTML report
will be created. Defaults to GWSBaselineConformance. The client's local timestamp will be
appended to this name.
--outputproviderfilename
The name of the Provider output json in --outputpath. Defaults to ProviderSettingsExport.
--outputregofilename
The name of the Rego output json in --outputpath. Defaults to TestResults.
--outputreportfilename
The name of the main html file homepage created in --outputpath. Defaults to BaselineReports.
--omitsudo This switch prevents running the OPA executable with sudo.
--quiet This switch suppresses automatically launching a web browser to open the html report output
and the loading bar output.
--debug This switch is used to print debugging information for OPA.
```
## Navigation
- Continue to [Usage: Config File](/docs/usage/Config.md)
- Return to [Documentation Home](/README.md)
# Usage: Parameters
Execute the ScubaGoggles tool using the `scubagoggles` command. For GWS,
all commands will be under the `gws` "subcommand".
```
usage: scubagoggles gws [-h]
[--baselines <baseline> [<baseline> ...]]
[--outputpath <directory>]
[--outjsonfilename <output-JSON-file>]
[--credentials <credentials-JSON-file>]
[--config <YAML-config-file>]
[--subjectemail <email-address>]
[--customerid <customer-id>]
[--opapath <opa-directory>]
[--regopath <directory>]
[--documentpath <directory>]
[--outputfoldername <name>]
[--outputproviderfilename <name>]
[--outputregofilename <name>]
[--outputreportfilename]
[--quiet]
[--debug]
[--runcached]
[--skipexport]
SCuBA automated conformance check for Google Workspace (GWS) products
options:
-h, --help show this help message and exit
--baselines <baseline> [<baseline> ...], -b <baseline> [<baseline> ...]
A list of one or more abbreviated GWS baseline names that the tool will assess. Defaults to all baselines. Choices: calendar, chat,
classroom, commoncontrols, drive, gmail, groups, meet, rules, sites
--outputpath <directory>, -o <directory>
The folder path where both the output JSON & HTML report will be created.
--outjsonfilename <output-JSON-file>
The name of the file that encapsulates all assessment output. Defaults to ScubaResults.
--credentials <credentials-JSON-file>, -c <credentials-JSON-file>
The location and name of the OAuth / service account credentials json file.
--config <YAML-config-file>
Local file path to a YAML formatted configuration file. Configuration file parameters can be used in place of command-line
parameters. Additional parameters and variables not available on the command line can also be included in the file that will be
provided to the tool for use in specific tests.
--subjectemail <email-address>
Only applicable when using a service account. The email address of a user the service account should act on behalf of. This user
must have the necessary privileges to run scubagoggles.
--customerid <customer-id>
The customer ID the tool should run on. Defaults to "my_customer" which will be the domain of the user / service account
authenticating.
--opapath <opa-directory>
The directory containing the OPA executable.
--regopath <directory>
The relative path to the directory contain the folder containing the rego files.
--documentpath <directory>
The relative path to the directory containing the SCuBA baseline documents.
--outputfoldername <name>
The name of the folder created in --outputpath where both the output JSON and the HTML report will be created. Defaults to GWSBaselineConformance. The client's local timestamp will be appended to this name.
--outputproviderfilename <name>
The name of the Provider output json in --outputpath. Defaults to ProviderSettingsExport.
--outputregofilename <name>
The name of the Rego output json in --outputpath. Defaults to TestResults.
--outputreportfilename
The name of the main html file homepage created in --outputpath. Defaults to BaselineReports.
--quiet This switch suppresses automatically launching a web browser to open the html report output and the loading bar output.
--debug This switch is used to print debugging information for OPA.
Cached Mode options:
--runcached This switch when added will run in the tool in "RunCached mode". When combined with --skipexport allows the user to skip
authentication and provider export.
--skipexport This switch when added will skip the provider export. To be used in conjunction with --runcached.
```
## Navigation
- Continue to [Usage: Examples](Examples.md)
- Return to [Documentation Home](/README.md)

View File

@@ -1,14 +1,43 @@
# Review Output
## Locating the Output
By default, ScubaGoggles output will be saved in a folder within the current working directory named GWSBaselineConformance_[yyyy_mm_dd_hh_mm_ss], though both the location of the output and name of the folder can be configured via the `--outputpath` and `--outputfoldername` parameters, respectively.
Unless run with the `--quiet` parameter, the HTML report will open automatically using the system's default browser.
See [Usage: Parameters](/docs/usage/Parameters.md) for more details on these and other parameters.
## Output Format
The output will be saved in both HTML and json formats. See [Sample Report](/sample-report) for an example of the output.
## Navigation
- Continue to [Limitations](/docs/usage/Limitations.md)
- Return to [Documentation Home](/README.md)
# Review Output
## Locating the Output
ScubaGoggles conformance reports are written to the output
directory you established during the [setup](../installation/DownloadAndInstall.md#scubagoggles-setup-utility) installation
step. For each `scubagoggles gws` run, a subdirectory is
created, which is named in the following format:
`GWSBaselineConformance_yyyy_mm_dd_hh_mm_ss`, the suffix
of which is based on the date & time the report was
generated:
| Abbreviation | Description |
|-------------|---------------------------------------------------|
| yyyy | Four digit year (e.g., 2025). |
| mm | Two digit month. |
| dd | Two digit day. |
| hh | Two digit hour (24-hour time). |
| mm | Two digit minute. |
| ss | Two digit seconds. |
Unless run with the `--quiet` parameter, the HTML report will open automatically using the system's default browser.
See [Usage: Parameters](Parameters.md) for more details on these and other parameters.
## Output Format
The output will be saved in both HTML and json formats. See [Sample Report](../../scubagoggles/sample-report) for an example of the output.
## Purging Older Report Directories
Each time you run ScubaGoggles, a directory (folder) is created that contains
the conformance report files. If you run ScubaGoggles often, these directories
will accumulate. When you use the default output directory and directory name
prefix (`GWSBaselineConformance`), you may use the `scubagoggles purge`
command to remove older report directories. The `--expire` option deletes all
report directories created earlier than the number of days specified. The
`--keep` option ensures that the number of directories you specify will not be
deleted. When given together, the keep count takes precedence over the expiry
days.
## Navigation
- Continue to [Limitations](Limitations.md)
- Return to [Documentation Home](/README.md)

View File

@@ -4,4 +4,4 @@ GWS.CALENDAR.1.2v0.3,"External sharing options for secondary calendars SHALL be
GWS.CALENDAR.2.1v0.3,External invitations warnings SHALL be enabled to prompt users before sending invitations.,Admin Log Event,Change Calendar Setting,ENABLE_EXTERNAL_GUEST_PROMPT,true,rules/00gjdgxs26jpj72,JK 07-28-23 @ 12:20
GWS.CALENDAR.3.1v0.3,Calendar Interop SHOULD be disabled unless agency mission fulfillment requires collaboration between users internal and external to an organization who use both Microsoft Exchange and Google Calendar.,Admin Log Event,Change Calendar Setting,ENABLE_EWS_INTEROP,false,rules/00gjdgxs3yipjmt,JK 07-28-23 @ 14:42
GWS.CALENDAR.3.2v0.3,OAuth 2.0 SHALL be used in lieu of basic authentication to establish connectivity between tenants or organizations in cases where Calendar Interop is deemed necessary for agency mission fulfillment.,N/A,N/A,N/A,N/A,N/A,"Not able to create rule due to bug in rule wizard. Applicable log event exists, but is not selectable within rule wizard."
GWS.CALENDAR.4.1v0.3,Appointment Schedule with Payments SHALL be disabled.,Admin Log Event,Change Application Setting,CalendarAppointmentSlotAdminSettingsProto payments_enabled,false,rules/00gjdgxs3oppjwl,JK 09-08-23 @ 10:47
GWS.CALENDAR.4.1v0.3,Appointment Schedule with Payments SHALL be disabled.,Admin Log Event,Change Application Setting,CalendarAppointmentSlotAdminSettingsProto payments_enabled,false,rules/00gjdgxs3oppjwl,JK 09-08-23 @ 10:47
1 PolicyId Name Data Source Event (Is) Setting Name (Is) New Value (Is Not) Rule ID Last Successful Test
4 GWS.CALENDAR.2.1v0.3 External invitations warnings SHALL be enabled to prompt users before sending invitations. Admin Log Event Change Calendar Setting ENABLE_EXTERNAL_GUEST_PROMPT true rules/00gjdgxs26jpj72 JK 07-28-23 @ 12:20
5 GWS.CALENDAR.3.1v0.3 Calendar Interop SHOULD be disabled unless agency mission fulfillment requires collaboration between users internal and external to an organization who use both Microsoft Exchange and Google Calendar. Admin Log Event Change Calendar Setting ENABLE_EWS_INTEROP false rules/00gjdgxs3yipjmt JK 07-28-23 @ 14:42
6 GWS.CALENDAR.3.2v0.3 OAuth 2.0 SHALL be used in lieu of basic authentication to establish connectivity between tenants or organizations in cases where Calendar Interop is deemed necessary for agency mission fulfillment. N/A N/A N/A N/A N/A Not able to create rule due to bug in rule wizard. Applicable log event exists, but is not selectable within rule wizard.
7 GWS.CALENDAR.4.1v0.3 Appointment Schedule with Payments SHALL be disabled. Admin Log Event Change Application Setting CalendarAppointmentSlotAdminSettingsProto payments_enabled false rules/00gjdgxs3oppjwl JK 09-08-23 @ 10:47

View File

@@ -5,7 +5,7 @@ GWS.CHAT.2.1v0.3,External file sharing SHALL be disabled to protect sensitive in
GWS.CHAT.3.1v0.3,Space history SHOULD be enabled for traceability of information.,Admin Log Event,Change Application Setting,RoomOtrSettingsProto otr_state,"ALWAYS_ON_THE_RECORD
OR
DEFAULT_ON_THE_RECORD",rules/00gjdgxs13kc3ei,JK 08-01-23 @ 11:58
GWS.CHAT.4.1v0.3(a),"External Chat messaging SHALL be restricted to allowlisted domains only.",Admin Log Event,Change Application Setting,RestrictChatProto restrictChatToOrganization,false,rules/00gjdgxs3vz76ij,JK 08-01-23 @ 13:17
GWS.CHAT.4.1v0.3(a),External Chat messaging SHALL be restricted to allowlisted domains only.,Admin Log Event,Change Application Setting,RestrictChatProto restrictChatToOrganization,false,rules/00gjdgxs3vz76ij,JK 08-01-23 @ 13:17
GWS.CHAT.4.1v0.3(b),External Chat messaging SHALL be restricted to allowlisted domains only.,Admin Log Event,Change Application Setting,RestrictChatProto externalChatRestriction,TRUSTED_DOMAINS,rules/00gjdgxs3exvv2u,JK 08-01-23 @ 13:27
GWS.CHAT.5.1v0.3,"Chat content reporting SHALL be enabled for all conversation types.",Admin Log Event,Create Application Setting,ContentReportingProto group_chat_reporting,CONTENT_REPORTING_STATE_ENABLED,N/A, MD @ 10-15-24 @ 16:47
GWS.CHAT.5.2v0.3,"All reporting message categories SHOULD be selected.",N/A,N/A,N/A,N/A,N/A,Not Alertable due to no specfic log event
GWS.CHAT.5.1v0.3,"Chat content reporting SHALL be enabled for all conversation types.",Admin Log Event,Create Application Setting,ContentReportingProto group_chat_reporting,CONTENT_REPORTING_STATE_ENABLED,N/A, MD @ 10-15-24 @ 16:47
GWS.CHAT.5.2v0.3,"All reporting message categories SHOULD be selected.",N/A,N/A,N/A,N/A,N/A,Not Alertable due to no specfic log event
1 PolicyId Name Data Source Event (Is) Setting Name (Is) New Value (Is Not) Rule ID Last Successful Test
5 GWS.CHAT.3.1v0.3 Space history SHOULD be enabled for traceability of information. Admin Log Event Change Application Setting RoomOtrSettingsProto otr_state ALWAYS_ON_THE_RECORD OR DEFAULT_ON_THE_RECORD rules/00gjdgxs13kc3ei JK 08-01-23 @ 11:58
6 GWS.CHAT.4.1v0.3(a) External Chat messaging SHALL be restricted to allowlisted domains only. Admin Log Event Change Application Setting RestrictChatProto restrictChatToOrganization false rules/00gjdgxs3vz76ij JK 08-01-23 @ 13:17
7 GWS.CHAT.4.1v0.3(b) External Chat messaging SHALL be restricted to allowlisted domains only. Admin Log Event Change Application Setting RestrictChatProto externalChatRestriction TRUSTED_DOMAINS rules/00gjdgxs3exvv2u JK 08-01-23 @ 13:27
8 GWS.CHAT.5.1v0.3 Chat content reporting SHALL be enabled for all conversation types. Admin Log Event Create Application Setting ContentReportingProto group_chat_reporting CONTENT_REPORTING_STATE_ENABLED N/A MD @ 10-15-24 @ 16:47 MD @ 10-15-24 @ 16:47
9 GWS.CHAT.5.2v0.3 All reporting message categories SHOULD be selected. N/A N/A N/A N/A N/A Not Alertable due to no specfic log event
10
11

View File

@@ -4,4 +4,4 @@ GWS.CLASSROOM.1.2v0.3,Which classes can users in your domain join SHALL be set t
GWS.CLASSROOM.2.1v0.3,Classroom API SHALL be disabled for users,Admin Log Events,Change Application Setting,ApiDataAccessSettingProto api_access_enabled,false,rules/00gjdgxs3aafl8p,JK 10-20-23 @ 13:31
GWS.CLASSROOM.3.1v0.3,Roster import with Clever SHOULD be turned off,Admin Log Events,Change Application Setting,RosterImportSettingsProto sis_integrator,SIS_INTEGRATOR_NONE,rules/00gjdgxs25t0l8g,JK 10-20-23 @ 13:42
GWS.CLASSROOM.4.1v0.3,Who can unenroll students from classes SHALL be set to Teachers Only,Admin Log Events,Change Application Setting,StudentUnenrollmentSettingsProto who_can_unenroll_students,ONLY_TEACHERS_CAN_UNENROLL_STUDENTS,rules/00gjdgxs44rgreu,JK 10-20-23 @ 13:50
GWS.CLASSROOM.5.1v0.3,Class creation SHALL be restricted to verified teachers only.,Admin Log Events,Change Application Setting,TeacherPermissionsSettingProto who_can_create_class,rules/00gjdgxs4cfwumr,JK 06-21-24 @ 11:58
GWS.CLASSROOM.5.1v0.3,Class creation SHALL be restricted to verified teachers only.,Admin Log Events,Change Application Setting,TeacherPermissionsSettingProto who_can_create_class,rules/00gjdgxs4cfwumr,JK 06-21-24 @ 11:58,
1 PolicyId,Name,Data Source,Event (Is),Setting Name (Is),New Value (Is Not),Rule ID,Last Successful Test PolicyId Name Data Source Event (Is) Setting Name (Is) New Value (Is Not) Rule ID Last Successful Test
4 GWS.CLASSROOM.2.1v0.3,Classroom API SHALL be disabled for users,Admin Log Events,Change Application Setting,ApiDataAccessSettingProto api_access_enabled,false,rules/00gjdgxs3aafl8p,JK 10-20-23 @ 13:31 GWS.CLASSROOM.2.1v0.3 Classroom API SHALL be disabled for users Admin Log Events Change Application Setting ApiDataAccessSettingProto api_access_enabled false rules/00gjdgxs3aafl8p JK 10-20-23 @ 13:31
5 GWS.CLASSROOM.3.1v0.3,Roster import with Clever SHOULD be turned off,Admin Log Events,Change Application Setting,RosterImportSettingsProto sis_integrator,SIS_INTEGRATOR_NONE,rules/00gjdgxs25t0l8g,JK 10-20-23 @ 13:42 GWS.CLASSROOM.3.1v0.3 Roster import with Clever SHOULD be turned off Admin Log Events Change Application Setting RosterImportSettingsProto sis_integrator SIS_INTEGRATOR_NONE rules/00gjdgxs25t0l8g JK 10-20-23 @ 13:42
6 GWS.CLASSROOM.4.1v0.3,Who can unenroll students from classes SHALL be set to Teachers Only,Admin Log Events,Change Application Setting,StudentUnenrollmentSettingsProto who_can_unenroll_students,ONLY_TEACHERS_CAN_UNENROLL_STUDENTS,rules/00gjdgxs44rgreu,JK 10-20-23 @ 13:50 GWS.CLASSROOM.4.1v0.3 Who can unenroll students from classes SHALL be set to Teachers Only Admin Log Events Change Application Setting StudentUnenrollmentSettingsProto who_can_unenroll_students ONLY_TEACHERS_CAN_UNENROLL_STUDENTS rules/00gjdgxs44rgreu JK 10-20-23 @ 13:50
7 GWS.CLASSROOM.5.1v0.3,Class creation SHALL be restricted to verified teachers only.,Admin Log Events,Change Application Setting,TeacherPermissionsSettingProto who_can_create_class,rules/00gjdgxs4cfwumr,JK 06-21-24 @ 11:58 GWS.CLASSROOM.5.1v0.3 Class creation SHALL be restricted to verified teachers only. Admin Log Events Change Application Setting TeacherPermissionsSettingProto who_can_create_class rules/00gjdgxs4cfwumr JK 06-21-24 @ 11:58

View File

@@ -39,7 +39,7 @@ GWS.COMMONCONTROLS.15.3v0.3,"The supplemental data storage region SHALL NOT be s
GWS.COMMONCONTROLS.16.1v0.3,"Service status for Google services that do not have an individual control SHOULD be set to OFF for everyone.",Admin Log Event,Toggle Service Enabled,DISABLE_UNLISTED_SERVICES, true, N/A, MD 09-12-2024 @ 11:12
GWS.COMMONCONTROLS.16.2v0.3,"Early Access Apps Service Status SHOULD be set to OFF for everyone.", Admin Log Event,Toggle Service Enabled,Early Access Apps, false, N/A, MD 09-12-2024 @ 11:16
GWS.COMMONCONTROLS.17.1v0.3,"Require multi party approval for sensitive admin actions SHALL be enabled.", Admin Log Event, Change Application Setting, Multi Party Approval (MPA) Control Multi Party Approval Control, enabled, N/A, MD 09-12-2024 @ 11:20
GWS.COMMONCONTROLS.18.1v0.3,"A custom policy SHALL be configured for Google Drive to protect PII and sensitive information, as defined by the agency. At a minimum, credit card numbers, U.S. Individual Taxpayer Identification Numbers (ITIN), and U.S. Social Security numbers (SSN) SHALL be blocked.",N/A,N/A,N/A,N/A,N/A,Not Alertable due to no specfic log event
GWS.COMMONCONTROLS.18.1v0.3,"A custom policy SHALL be configured for Google Drive to protect PII and sensitive information, as defined by the agency. At a minimum, credit card numbers, U.S. Individual Taxpayer Identification Numbers (ITIN), and U.S. Social Security numbers (SSN) SHALL be blocked.",N/A,N/A,N/A,N/A,N/A,Not Alertable due to no specfic log event
GWS.COMMONCONTROLS.18.2v0.3,"A custom policy SHALL be configured for Google Chat to protect PII and sensitive information, as defined by the agency. At a minimum, credit card numbers, U.S. Individual Taxpayer Identification Numbers (ITIN), and U.S. Social Security numbers (SSN) SHALL be blocked.",N/A,N/A,N/A,N/A,N/A,Not Alertable due to no specfic log event
GWS.COMMONCONTROLS.18.3v0.3,"A custom policy SHALL be configured for Gmail to protect PII and sensitive information, as defined by the agency. At a minimum, credit card numbers, U.S. Individual Taxpayer Identification Numbers (ITIN), and U.S. Social Security numbers (SSN) SHALL be blocked.",N/A,N/A,N/A,N/A,N/A,Not Alertable due to no specfic log event
GWS.COMMONCONTROLS.18.4v0.3,"The action for the custom DLP policy SHOULD be set to block external sharing.",N/A,N/A,N/A,N/A,N/A,Not Alertable due to no specfic log event
GWS.COMMONCONTROLS.18.4v0.3,"The action for the custom DLP policy SHOULD be set to block external sharing.",N/A,N/A,N/A,N/A,N/A,Not Alertable due to no specfic log event
1 PolicyId Name Data Source Event (Is) Setting Name (Is) New Value (Is Not) Rule ID Last Successful Test
39 GWS.COMMONCONTROLS.17.1v0.3 Require multi party approval for sensitive admin actions SHALL be enabled. Admin Log Event Change Application Setting Multi Party Approval (MPA) Control Multi Party Approval Control enabled N/A MD 09-12-2024 @ 11:20
40 GWS.COMMONCONTROLS.18.1v0.3 A custom policy SHALL be configured for Google Drive to protect PII and sensitive information, as defined by the agency. At a minimum, credit card numbers, U.S. Individual Taxpayer Identification Numbers (ITIN), and U.S. Social Security numbers (SSN) SHALL be blocked. N/A N/A N/A N/A N/A Not Alertable due to no specfic log event Not Alertable due to no specfic log event
41 GWS.COMMONCONTROLS.18.2v0.3 A custom policy SHALL be configured for Google Chat to protect PII and sensitive information, as defined by the agency. At a minimum, credit card numbers, U.S. Individual Taxpayer Identification Numbers (ITIN), and U.S. Social Security numbers (SSN) SHALL be blocked. N/A N/A N/A N/A N/A Not Alertable due to no specfic log event
42 GWS.COMMONCONTROLS.18.3v0.3 A custom policy SHALL be configured for Gmail to protect PII and sensitive information, as defined by the agency. At a minimum, credit card numbers, U.S. Individual Taxpayer Identification Numbers (ITIN), and U.S. Social Security numbers (SSN) SHALL be blocked. N/A N/A N/A N/A N/A Not Alertable due to no specfic log event
43 GWS.COMMONCONTROLS.18.4v0.3 The action for the custom DLP policy SHOULD be set to block external sharing. N/A N/A N/A N/A N/A Not Alertable due to no specfic log event
44
45

View File

@@ -50,6 +50,6 @@ GWS.GMAIL.17.1v0.3,Comprehensive mail storage SHOULD be enabled to ensure inform
GWS.GMAIL.18.1v0.3,Content filtering SHOULD be enabled within Gmail messages.,N/A,N/A,N/A,N/A,N/A,Not Alertable
GWS.GMAIL.18.2v0.3,Any third-party or outside application selected for advanced email content filtering SHOULD offer services comparable to those offered by Google Workspace.,N/A,N/A,N/A,N/A,N/A,Not Alertable
GWS.GMAIL.18.3v0.3,"Gmail or third-party applications SHALL be configured to protect PII and sensitive information as defined by the agency. At a minimum, credit card numbers, taxpayer Identification Numbers (TIN), and Social Security Numbers (SSN) SHALL be blocked.",N/A,N/A,N/A,N/A,N/A,Not Alertable
GWS.GMAIL.19.1v0.3,"Domains SHALL NOT be added to lists that bypass spam filters.",Admin Log Event,Change Gmail Setting,SPAM_CONTROL,N/A,rules/00gjdgxs12jr6zt,JGK 04-11-24 @ 09:45
GWS.GMAIL.19.2v0.3,"Domains SHALL NOT be added to lists that bypass spam filters and hide warnings.",Admin Log Event,Change Gmail Setting,SPAM_CONTROL,N/A,rules/00gjdgxs12jr6zt,JGK 04-11-24 @ 09:45
GWS.GMAIL.19.3v0.3,"Bypass spam filters and hide warnings for all messages from internal and external senders SHALL NOT be enabled.",Admin Log Event,Change Gmail Setting,SPAM_CONTROL,N/A,rules/00gjdgxs12jr6zt,JGK 04-11-24 @ 09:45
GWS.GMAIL.19.1v0.3,Domains SHALL NOT be added to lists that bypass spam filters.,Admin Log Event,Change Gmail Setting,SPAM_CONTROL,N/A,rules/00gjdgxs12jr6zt,JGK 04-11-24 @ 09:45
GWS.GMAIL.19.2v0.3,Domains SHALL NOT be added to lists that bypass spam filters and hide warnings.,Admin Log Event,Change Gmail Setting,SPAM_CONTROL,N/A,rules/00gjdgxs12jr6zt,JGK 04-11-24 @ 09:45
GWS.GMAIL.19.3v0.3,Bypass spam filters and hide warnings for all messages from internal and external senders SHALL NOT be enabled.,Admin Log Event,Change Gmail Setting,SPAM_CONTROL,N/A,rules/00gjdgxs12jr6zt,JGK 04-11-24 @ 09:45
1 PolicyId Name Data Source Event (Is) Setting Name (Is) New Value (Is Not) Rule ID Last Successful Test
50 GWS.GMAIL.18.1v0.3 Content filtering SHOULD be enabled within Gmail messages. N/A N/A N/A N/A N/A Not Alertable
51 GWS.GMAIL.18.2v0.3 Any third-party or outside application selected for advanced email content filtering SHOULD offer services comparable to those offered by Google Workspace. N/A N/A N/A N/A N/A Not Alertable
52 GWS.GMAIL.18.3v0.3 Gmail or third-party applications SHALL be configured to protect PII and sensitive information as defined by the agency. At a minimum, credit card numbers, taxpayer Identification Numbers (TIN), and Social Security Numbers (SSN) SHALL be blocked. N/A N/A N/A N/A N/A Not Alertable
53 GWS.GMAIL.19.1v0.3 Domains SHALL NOT be added to lists that bypass spam filters. Admin Log Event Change Gmail Setting SPAM_CONTROL N/A rules/00gjdgxs12jr6zt JGK 04-11-24 @ 09:45
54 GWS.GMAIL.19.2v0.3 Domains SHALL NOT be added to lists that bypass spam filters and hide warnings. Admin Log Event Change Gmail Setting SPAM_CONTROL N/A rules/00gjdgxs12jr6zt JGK 04-11-24 @ 09:45
55 GWS.GMAIL.19.3v0.3 Bypass spam filters and hide warnings for all messages from internal and external senders SHALL NOT be enabled. Admin Log Event Change Gmail Setting SPAM_CONTROL N/A rules/00gjdgxs12jr6zt JGK 04-11-24 @ 09:45

View File

@@ -4,4 +4,4 @@ GWS.GROUPS.2.1v0.3,Group owners ability to add external members to groups SHO
GWS.GROUPS.3.1v0.3,"Group owners ability to allow posting to a group by an external, non-group member SHOULD be disabled unless necessary for agency mission fulfillment.",Admin Log Event,Change Application Setting,GroupsSharingSettingsProto owners_can_allow_incoming_mail_from_public,false,rules/00gjdgxs0lw54bd,JK 08-01-23 @ 14:52
GWS.GROUPS.4.1v0.3,Group creation SHOULD be restricted to admins within the organization unless necessary for agency mission fulfillment.,Admin Log Event,Change Application Setting,GroupsSharingSettingsProto who_can_create_groups,ADMIN_ONLY,rules/00gjdgxs35vsmz6,JK 08-01-23 @ 15:06
GWS.GROUPS.5.1v0.3,The default permission to view conversations SHALL be set to All Group Members.,Admin Log Event,Change Application Setting,GroupsSharingSettingsProto default_view_topics_access_level,MEMBERS,rules/00gjdgxs24dq6r2,JK 08-01-23 @ 15:14
GWS.GROUPS.6.1v0.3,Group owners ability to hide groups from the directory SHOULD be disabled unless necessary for agency mission fulfillment.,Admin Log Event,Change Application Setting,GroupsSharingSettingsProto allow_unlisted_groups,false,rules/00gjdgxs0zbb0ae,JK 08-01-23 @ 15:22
GWS.GROUPS.6.1v0.3,Group owners ability to hide groups from the directory SHOULD be disabled unless necessary for agency mission fulfillment.,Admin Log Event,Change Application Setting,GroupsSharingSettingsProto allow_unlisted_groups,false,rules/00gjdgxs0zbb0ae,JK 08-01-23 @ 15:22
1 PolicyId Name Data Source Event (Is) Setting Name (Is) New Value (Is Not) Rule ID Last Successful Test
4 GWS.GROUPS.3.1v0.3 Group owners’ ability to allow posting to a group by an external, non-group member SHOULD be disabled unless necessary for agency mission fulfillment. Admin Log Event Change Application Setting GroupsSharingSettingsProto owners_can_allow_incoming_mail_from_public false rules/00gjdgxs0lw54bd JK 08-01-23 @ 14:52
5 GWS.GROUPS.4.1v0.3 Group creation SHOULD be restricted to admins within the organization unless necessary for agency mission fulfillment. Admin Log Event Change Application Setting GroupsSharingSettingsProto who_can_create_groups ADMIN_ONLY rules/00gjdgxs35vsmz6 JK 08-01-23 @ 15:06
6 GWS.GROUPS.5.1v0.3 The default permission to view conversations SHALL be set to All Group Members. Admin Log Event Change Application Setting GroupsSharingSettingsProto default_view_topics_access_level MEMBERS rules/00gjdgxs24dq6r2 JK 08-01-23 @ 15:14
7 GWS.GROUPS.6.1v0.3 Group owners’ ability to hide groups from the directory SHOULD be disabled unless necessary for agency mission fulfillment. Admin Log Event Change Application Setting GroupsSharingSettingsProto allow_unlisted_groups false rules/00gjdgxs0zbb0ae JK 08-01-23 @ 15:22

View File

@@ -3,4 +3,4 @@ GWS.MEET.1.1v0.3,Meeting access SHALL be restricted to users signed in with a Go
GWS.MEET.2.1v0.3,Meeting access SHALL be disabled for meetings created by users who are not members of any Google Workspace tenant or organization.,Admin Log Event,Change Application Setting,SafetyAccessLockProto meetings_allowed_to_join,WORKSPACE_DOMAINS,rules/00gjdgxs0rw9s95,JK 08-02-23 @ 16:02
GWS.MEET.3.1v0.3,Host Management meeting features SHALL be enabled so that they are available by default when a host starts their meeting.,Admin Log Event,Change Application Setting,SafetyModerationLockProto host_management_enabled,true,rules/00gjdgxs3bvxawy,JK 08-02-23 @ 16:05
GWS.MEET.4.1v0.3,Warn for external participants SHALL be enabled.,Admin Log Event,Change Application Setting,Warn for external participants External or unidentified participants in a meeting are given a label,true,rules/00gjdgxs2yp7uet,JK 10-16-23 @ 07:32
GWS.MEET.5.1v0.3,Users receive calls only from contacts and other users in the organization SHALL be selected.,Admin Log Event,Change Application Setting,Incoming call restrictions Allowed caller type,CONTACTS_AND_SAME_DOMAIN,rules/00gjdgxs188dve6,MD 06-11-24 @ 12:30
GWS.MEET.5.1v0.3,Users receive calls only from contacts and other users in the organization SHALL be selected.,Admin Log Event,Change Application Setting,Incoming call restrictions Allowed caller type,CONTACTS_AND_SAME_DOMAIN,rules/00gjdgxs188dve6,MD 06-11-24 @ 12:30
1 PolicyId Name Data Source Event (Is) Setting Name (Is) New Value (Is Not) Rule ID Last Successful Test
3 GWS.MEET.2.1v0.3 Meeting access SHALL be disabled for meetings created by users who are not members of any Google Workspace tenant or organization. Admin Log Event Change Application Setting SafetyAccessLockProto meetings_allowed_to_join WORKSPACE_DOMAINS rules/00gjdgxs0rw9s95 JK 08-02-23 @ 16:02
4 GWS.MEET.3.1v0.3 Host Management meeting features SHALL be enabled so that they are available by default when a host starts their meeting. Admin Log Event Change Application Setting SafetyModerationLockProto host_management_enabled true rules/00gjdgxs3bvxawy JK 08-02-23 @ 16:05
5 GWS.MEET.4.1v0.3 Warn for external participants SHALL be enabled. Admin Log Event Change Application Setting Warn for external participants External or unidentified participants in a meeting are given a label true rules/00gjdgxs2yp7uet JK 10-16-23 @ 07:32
6 GWS.MEET.5.1v0.3 Users receive calls only from contacts and other users in the organization SHALL be selected. Admin Log Event Change Application Setting Incoming call restrictions Allowed caller type CONTACTS_AND_SAME_DOMAIN rules/00gjdgxs188dve6 MD 06-11-24 @ 12:30

View File

@@ -1,2 +1,2 @@
PolicyId,Name,Data Source,Event (Is),Setting Name (Is),New Value (Is Not),Rule ID,Last Successful Test
GWS.SITES.1.1v0.3,Sites Service SHOULD be disabled for all users.,Admin Log Event,Toggle Service Enabled,No Setting Name,FALSE,rules/00gjdgxs3gdgxe3,JK 07-28-23 @ 11:12
GWS.SITES.1.1v0.3,Sites Service SHOULD be disabled for all users.,Admin Log Event,Toggle Service Enabled,No Setting Name,FALSE,rules/00gjdgxs3gdgxe3,JK 07-28-23 @ 11:12
1 PolicyId Name Data Source Event (Is) Setting Name (Is) New Value (Is Not) Rule ID Last Successful Test
2 GWS.SITES.1.1v0.3 Sites Service SHOULD be disabled for all users. Admin Log Event Toggle Service Enabled No Setting Name FALSE rules/00gjdgxs3gdgxe3 JK 07-28-23 @ 11:12

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

37
pyproject.toml Normal file
View File

@@ -0,0 +1,37 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[project]
name = "scubagoggles"
dynamic = ["version"]
classifiers = ["Development Status :: 4 - Beta",
"Intended Audience :: Information Technology",
"Topic :: Security",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13"]
dependencies = ["dnspython>=2.6.1",
"google-api-python-client>=2.142.0",
"google-auth-httplib2>=0.2.0",
"google-auth-oauthlib>=1.2.1",
"MarkupSafe>=2.1.5",
"pyyaml>=6.0.2",
"requests>=2.32.3",
"tqdm>=4.66.5"]
requires-python = ">= 3.9"
description='SCuBA security baseline assessment tool'
authors = [{name = "CISA"}]
license = {file = "LICENSE"}
readme = "README.md"
[project.scripts]
scubagoggles = "scubagoggles.main:dive"
[tool.setuptools.dynamic]
version = {attr = "scubagoggles.__version__"}
[tool.setuptools.packages.find]
where = ["."]

View File

@@ -1,302 +0,0 @@
package calendar
import data.utils
import future.keywords
LogEvents := utils.GetEvents("calendar_logs")
##################
# GWS.CALENDAR.1 #
##################
#
# Baseline GWS.CALENDAR.1.1v0.3
#--
GetFriendlyValue1_1(Value) := "Share all information, but outsiders cannot change calendars" if {
Value == "READ_ONLY_ACCESS"
} else := "Share all information, and outsiders can change calendars" if {
Value == "READ_WRITE_ACCESS"
} else := "Share all information, and allow managing of calendars" if {
Value == "MANAGE_ACCESS"
} else := Value
NonCompliantOUs1_1 contains {
"Name": OU,
"Value": concat(" ", [
"External sharing options for primary calendars is set to",
GetFriendlyValue1_1(LastEvent.NewValue)
])
} if {
some OU in utils.OUsWithEvents
Events := utils.FilterEventsOU(LogEvents, "SHARING_OUTSIDE_DOMAIN", OU)
# Ignore OUs without any events. We're already asserting that the
# top-level OU has at least one event; for all other OUs we assume
# they inherit from a parent OU if they have no events.
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue != "SHOW_ONLY_FREE_BUSY_INFORMATION"
LastEvent.NewValue != "INHERIT_FROM_PARENT"
}
NonCompliantGroups1_1 contains {
"Name": Group,
"Value": concat(" ", [
"External sharing options for primary calendars is set to",
GetFriendlyValue1_1(LastEvent.NewValue)
])
} if {
some Group in utils.GroupsWithEvents
Events := utils.FilterEventsGroup(LogEvents, "SHARING_OUTSIDE_DOMAIN", Group)
# Ignore Group without any events
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue != "SHOW_ONLY_FREE_BUSY_INFORMATION"
LastEvent.NewValue != "INHERIT_FROM_PARENT"
}
tests contains {
"PolicyId": "GWS.CALENDAR.1.1v0.3",
"Criticality": "Shall",
"ReportDetails": utils.NoSuchEventDetails(DefaultSafe, utils.TopLevelOU),
"ActualValue": "No relevant event for the top-level OU in the current logs.",
"RequirementMet": DefaultSafe,
"NoSuchEvent": true
}
if {
DefaultSafe := true
Events := utils.FilterEventsOU(LogEvents, "SHARING_OUTSIDE_DOMAIN", utils.TopLevelOU)
count(Events) == 0
}
tests contains {
"PolicyId": "GWS.CALENDAR.1.1v0.3",
"Criticality": "Shall",
"ReportDetails": utils.ReportDetails(NonCompliantOUs1_1, NonCompliantGroups1_1),
"ActualValue": {"NonCompliantOUs": NonCompliantOUs1_1, "NonCompliantGroups": NonCompliantGroups1_1},
"RequirementMet": Status,
"NoSuchEvent": false
}
if {
Events := utils.FilterEventsOU(LogEvents, "SHARING_OUTSIDE_DOMAIN", utils.TopLevelOU)
count(Events) > 0
Conditions := {count(NonCompliantOUs1_1) == 0, count(NonCompliantGroups1_1) == 0}
Status := (false in Conditions) == false
}
#--
#
# Baseline GWS.CALENDAR.1.2v0.3
#--
GetFriendlyValue1_2(Value) := "Secondary Calendars Share all information, but outsiders cannot change calendars." if {
Value == "READ_ONLY_ACCESS"
} else := "Share all information, and outsiders can change calendars." if {
Value == "READ_WRITE_ACCESS"
} else := "Share all information, and allow managing of calendars." if {
Value == "MANAGE_ACCESS"
} else := "Only free/busy information (hide event details)." if {
Value == "SHOW_ONLY_FREE_BUSY_INFORMATION"
} else := Value
tests contains {
"PolicyId": "GWS.CALENDAR.1.2v0.3",
"Criticality": "Shall",
"ReportDetails": utils.NoSuchEventDetails(DefaultSafe, utils.TopLevelOU),
"ActualValue": "No relevant event for the top-level OU in the current logs",
"RequirementMet": DefaultSafe,
"NoSuchEvent": true
}
if {
DefaultSafe := false
Events := utils.FilterEventsNoOU(LogEvents, "SHARING_OUTSIDE_DOMAIN_FOR_SECONDARY_CALENDAR")
count(Events) == 0
}
tests contains {
"PolicyId": "GWS.CALENDAR.1.2v0.3",
"Criticality": "Shall",
"ReportDetails": concat("",[utils.ReportDetailsBoolean(Status), "<br>Highest Level of Sharing: ",
GetFriendlyValue1_2(LastEvent.NewValue)]),
"ActualValue": {LastEvent.Setting: LastEvent.NewValue},
"RequirementMet": Status,
"NoSuchEvent": false
}
if {
Events := utils.FilterEventsNoOU(LogEvents, "SHARING_OUTSIDE_DOMAIN_FOR_SECONDARY_CALENDAR")
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
Status := LastEvent.NewValue == "SHOW_ONLY_FREE_BUSY_INFORMATION"
}
#--
##################
# GWS.CALENDAR.2 #
##################
#
# Baseline GWS.CALENDAR.2.1v0.3
#--
NonCompliantOUs2_1 contains {
"Name": OU,
"Value": "External Sharing Guest Prompt is disabled."
} if {
some OU in utils.OUsWithEvents
Events := utils.FilterEventsOU(LogEvents, "ENABLE_EXTERNAL_GUEST_PROMPT", OU)
# Ignore OUs without any events. We're already asserting that the
# top-level OU has at least one event; for all other OUs we assume
# they inherit from a parent OU if they have no events.
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue == "false"
}
NonCompliantGroups2_1 contains {
"Name": Group,
"Value": "External Sharing Guest Prompt is disabled."
} if {
some Group in utils.GroupsWithEvents
Events := utils.FilterEventsGroup(LogEvents, "ENABLE_EXTERNAL_GUEST_PROMPT", Group)
# Ignore groups without any events
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue == "false"
}
tests contains {
"PolicyId": "GWS.CALENDAR.2.1v0.3",
"Criticality": "Shall",
"ReportDetails": utils.NoSuchEventDetails(DefaultSafe, utils.TopLevelOU),
"ActualValue": "No relevant event for the top-level OU in the current logs",
"RequirementMet": DefaultSafe,
"NoSuchEvent": true
}
if {
DefaultSafe := true
Events := utils.FilterEventsOU(LogEvents, "ENABLE_EXTERNAL_GUEST_PROMPT", utils.TopLevelOU)
count(Events) == 0
}
tests contains {
"PolicyId": "GWS.CALENDAR.2.1v0.3",
"Criticality": "Shall",
"ReportDetails": utils.ReportDetails(NonCompliantOUs2_1, NonCompliantGroups2_1),
"ActualValue": {"NonCompliantOUs": NonCompliantOUs2_1, "NonCompliantGroups": NonCompliantGroups2_1},
"RequirementMet": Status,
"NoSuchEvent": false
}
if {
Events := utils.FilterEventsOU(LogEvents, "ENABLE_EXTERNAL_GUEST_PROMPT", utils.TopLevelOU)
count(Events) > 0
Conditions := {count(NonCompliantOUs2_1) == 0, count(NonCompliantGroups2_1) == 0}
Status := (false in Conditions) == false
}
#--
##################
# GWS.CALENDAR.3 #
##################
#
# Baseline GWS.CALENDAR.3.1v0.3
#--
tests contains {
"PolicyId": "GWS.CALENDAR.3.1v0.3",
"Criticality": "Should",
"ReportDetails": utils.NoSuchEventDetails(DefaultSafe, utils.TopLevelOU),
"ActualValue": "No relevant event for the top-level OU in the current logs",
"RequirementMet": DefaultSafe,
"NoSuchEvent": true
}
if {
DefaultSafe := true
Events := utils.FilterEventsNoOU(LogEvents, "ENABLE_EWS_INTEROP")
count(Events) == 0
}
tests contains {
"PolicyId": "GWS.CALENDAR.3.1v0.3",
"Criticality": "Should",
"ReportDetails": utils.ReportDetailsBoolean(Status),
"ActualValue": {LastEvent.Setting: LastEvent.NewValue},
"RequirementMet": Status,
"NoSuchEvent": false
}
if {
Events := utils.FilterEventsNoOU(LogEvents, "ENABLE_EWS_INTEROP")
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
Status := LastEvent.NewValue == "false"
}
#--
#
# Baseline GWS.CALENDAR.3.2v0.3
#--
tests contains {
"PolicyId": "GWS.CALENDAR.3.2v0.3",
"Criticality": "Shall/Not-Implemented",
"ReportDetails": "Currently not able to be tested automatically; please manually check.",
"ActualValue": "",
"RequirementMet": false,
"NoSuchEvent": true
}
#--
##################
# GWS.CALENDAR.4 #
##################
NonCompliantOUs4_1 contains {
"Name": OU,
"Value": "Paid calendar appointments are enabled."
} if {
some OU in utils.OUsWithEvents
Events := utils.FilterEventsOU(LogEvents, "CalendarAppointmentSlotAdminSettingsProto payments_enabled", OU)
# Ignore OUs without any events. We're already asserting that the
# top-level OU has at least one event; for all other OUs we assume
# they inherit from a parent OU if they have no events.
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue == "true"
}
#
# Baseline GWS.CALENDAR.4.1v0.3
#--
tests contains {
"PolicyId": "GWS.CALENDAR.4.1v0.3",
"Criticality": "Shall",
"ReportDetails": utils.NoSuchEventDetails(DefaultSafe, utils.TopLevelOU),
"ActualValue": "No relevant event for the top-level OU in the current logs.",
"RequirementMet": DefaultSafe,
"NoSuchEvent": true
}
if {
DefaultSafe := true
SettingName := "CalendarAppointmentSlotAdminSettingsProto payments_enabled"
Events := utils.FilterEventsOU(LogEvents, SettingName, utils.TopLevelOU)
count(Events) == 0
}
tests contains {
"PolicyId": "GWS.CALENDAR.4.1v0.3",
"Criticality": "Shall",
"ReportDetails": utils.ReportDetails(NonCompliantOUs4_1, []),
"ActualValue": {"NonCompliantOUs": NonCompliantOUs4_1},
"RequirementMet": Status,
"NoSuchEvent": false
}
if {
SettingName := "CalendarAppointmentSlotAdminSettingsProto payments_enabled"
Events := utils.FilterEventsOU(LogEvents, SettingName, utils.TopLevelOU)
count(Events) > 0
Status := count(NonCompliantOUs4_1) == 0
}
#--

View File

@@ -1,377 +0,0 @@
package classroom
import data.utils
import future.keywords
LogEvents := utils.GetEvents("classroom_logs")
###################
# GWS.CLASSROOM.1 #
###################
#
# Baseline GWS.CLASSROOM.1.1v0.3
#--
GetFriendlyValue1_1(Value) := "Users in your domain only" if {
Value == "1"
} else := "Users in allowlisted domains" if {
Value == "2"
} else := "Any Google Workspace user" if {
Value == "3"
} else := "Any user" if {
Value == "4"
} else := Value
NonCompliantOUs1_1 contains {
"Name": OU,
"Value": concat(" ", [
"Who can join classes in your domain is set to",
GetFriendlyValue1_1(LastEvent.NewValue)
])
} if {
some OU in utils.OUsWithEvents
Events := utils.FilterEventsOU(LogEvents, "ClassMembershipSettingProto who_can_join_classes", OU)
# Ignore OUs without any events. We're already asserting that the
# top-level OU has at least one event; for all other OUs we assume
# they inherit from a parent OU if they have no events.
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue != "1"
}
tests contains {
"PolicyId": "GWS.CLASSROOM.1.1v0.3",
"Criticality": "Shall",
"ReportDetails": utils.NoSuchEventDetails(DefaultSafe, utils.TopLevelOU),
"ActualValue": "No relevant event in the current logs",
"RequirementMet": DefaultSafe,
"NoSuchEvent": true
}
if {
DefaultSafe := true
Events := utils.FilterEventsOU(LogEvents, "ClassMembershipSettingProto who_can_join_classes", utils.TopLevelOU)
count(Events) == 0
}
tests contains {
"PolicyId": "GWS.CLASSROOM.1.1v0.3",
"Criticality": "Shall",
# Empty list is for noncompliant groups as classroom settings can't be modified at the group level
"ReportDetails": utils.ReportDetails(NonCompliantOUs1_1, []),
"ActualValue": {"NonCompliantOUs": NonCompliantOUs1_1},
"RequirementMet": Status,
"NoSuchEvent": false
}
if {
Events := utils.FilterEventsOU(LogEvents, "ClassMembershipSettingProto who_can_join_classes", utils.TopLevelOU)
count(Events) > 0
Status := count(NonCompliantOUs1_1) == 0
}
#--
#
# Baseline GWS.CLASSROOM.1.2v0.3
#--
GetFriendlyValue1_2(Value) := "Classes in your domain only" if {
Value == "1"
} else := "Classes in allowlisted domains" if {
Value == "2"
} else := "Any Google Workspace class" if {
Value == "3"
} else := Value
NonCompliantOUs1_2 contains {
"Name": OU,
"Value": concat(" ", [
"Which classes can users in your domain join is set to",
GetFriendlyValue1_2(LastEvent.NewValue)
])
} if {
some OU in utils.OUsWithEvents
Events := utils.FilterEventsOU(LogEvents, "ClassMembershipSettingProto which_classes_can_users_join", OU)
# Ignore OUs without any events. We're already asserting that the
# top-level OU has at least one event; for all other OUs we assume
# they inherit from a parent OU if they have no events.
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue != "1"
}
tests contains {
"PolicyId": "GWS.CLASSROOM.1.2v0.3",
"Criticality": "Shall",
"ReportDetails": utils.NoSuchEventDetails(DefaultSafe, utils.TopLevelOU),
"ActualValue": "No relevant event in the current logs",
"RequirementMet": DefaultSafe,
"NoSuchEvent": true
}
if {
DefaultSafe := true
SettingName := "ClassMembershipSettingProto which_classes_can_users_join"
Events := utils.FilterEventsOU(LogEvents, SettingName, utils.TopLevelOU)
count(Events) == 0
}
tests contains {
"PolicyId": "GWS.CLASSROOM.1.2v0.3",
"Criticality": "Shall",
# Empty list is for noncompliant groups as classroom settings can't be modified at the group level
"ReportDetails": utils.ReportDetails(NonCompliantOUs1_2, []),
"ActualValue": {"NonCompliantOUs": NonCompliantOUs1_2},
"RequirementMet": Status,
"NoSuchEvent": false
}
if {
SettingName := "ClassMembershipSettingProto which_classes_can_users_join"
Events := utils.FilterEventsOU(LogEvents, SettingName, utils.TopLevelOU)
count(Events) > 0
Status := count(NonCompliantOUs1_2) == 0
}
#--
###################
# GWS.CLASSROOM.2 #
###################
#
# Baseline GWS.CLASSROOM.2.1v0.3
#--
GetFriendlyValue2_1(Value) := "OFF" if {
Value == "false"
} else := "ON" if {
Value == "true"
} else := Value
NonCompliantOUs2_1 contains {
"Name": OU,
"Value": concat(" ", [
"Data access is set to",
GetFriendlyValue2_1(LastEvent.NewValue)
])
} if {
some OU in utils.OUsWithEvents
Events := utils.FilterEventsOU(LogEvents, "ApiDataAccessSettingProto api_access_enabled", OU)
# Ignore OUs without any events. We're already asserting that the
# top-level OU has at least one event; for all other OUs we assume
# they inherit from a parent OU if they have no events.
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue != "false"
LastEvent.NewValue != "DELETE_APPLICATION_SETTING"
}
tests contains {
"PolicyId": "GWS.CLASSROOM.2.1v0.3",
"Criticality": "Shall",
"ReportDetails": utils.NoSuchEventDetails(DefaultSafe, utils.TopLevelOU),
"ActualValue": "No relevant event in the current logs",
"RequirementMet": DefaultSafe,
"NoSuchEvent": true
}
if {
DefaultSafe := false
Events := utils.FilterEventsOU(LogEvents, "ApiDataAccessSettingProto api_access_enabled", utils.TopLevelOU)
count(Events) == 0
}
tests contains {
"PolicyId": "GWS.CLASSROOM.2.1v0.3",
"Criticality": "Shall",
# Empty list is for noncompliant groups as classroom settings can't be modified at the group level
"ReportDetails": utils.ReportDetails(NonCompliantOUs2_1, []),
"ActualValue": {"NonCompliantOUs": NonCompliantOUs2_1},
"RequirementMet": Status,
"NoSuchEvent": false
}
if {
Events := utils.FilterEventsOU(LogEvents, "ApiDataAccessSettingProto api_access_enabled", utils.TopLevelOU)
count(Events) > 0
Status := count(NonCompliantOUs2_1) == 0
}
#--
###################
# GWS.CLASSROOM.3 #
###################
#
# Baseline GWS.CLASSROOM.3.1v0.3
#--
GetFriendlyValue3_1(Value) := "OFF" if {
Value == "SIS_INTEGRATOR_NONE"
} else := "ON - CLEVER" if {
Value == "SIS_INTEGRATOR_CLEVER"
} else := Value
NonCompliantOUs3_1 contains {
"Name": OU,
"Value": concat(" ", [
"Roster import is set to",
GetFriendlyValue3_1(LastEvent.NewValue)
])
} if {
some OU in utils.OUsWithEvents
Events := utils.FilterEventsOU(LogEvents, "RosterImportSettingsProto sis_integrator", OU)
# Ignore OUs without any events. We're already asserting that the
# top-level OU has at least one event; for all other OUs we assume
# they inherit from a parent OU if they have no events.
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue != "SIS_INTEGRATOR_NONE"
LastEvent.NewValue != "DELETE_APPLICATION_SETTING"
}
tests contains {
"PolicyId": "GWS.CLASSROOM.3.1v0.3",
"Criticality": "Should",
"ReportDetails": utils.NoSuchEventDetails(DefaultSafe, utils.TopLevelOU),
"ActualValue": "No relevant event in the current logs",
"RequirementMet": DefaultSafe,
"NoSuchEvent": true
}
if {
DefaultSafe := true
Events := utils.FilterEventsOU(LogEvents, "RosterImportSettingsProto sis_integrator", utils.TopLevelOU)
count(Events) == 0
}
tests contains {
"PolicyId": "GWS.CLASSROOM.3.1v0.3",
"Criticality": "Should",
"ReportDetails": utils.ReportDetails(NonCompliantOUs3_1, []),
"ActualValue": {"NonCompliantOUs": NonCompliantOUs3_1},
"RequirementMet": Status,
"NoSuchEvent": false
}
if {
Events := utils.FilterEventsOU(LogEvents, "RosterImportSettingsProto sis_integrator", utils.TopLevelOU)
count(Events) > 0
Status := count(NonCompliantOUs3_1) == 0
}
#--
###################
# GWS.CLASSROOM.4 #
###################
#
# Baseline GWS.CLASSROOM.4.1v0.3
#--
GetFriendlyValue4_1(Value) := "Students and teachers" if {
Value == "STUDENTS_AND_TEACHERS_CAN_UNENROLL_STUDENTS"
} else := "Only teachers" if {
Value == "ONLY_TEACHERS_CAN_UNENROLL_STUDENTS"
} else := Value
NonCompliantOUs4_1 contains {
"Name": OU,
"Value": concat(" ", [
"Who can unenroll students from classes is set to",
GetFriendlyValue4_1(LastEvent.NewValue)
])
} if {
some OU in utils.OUsWithEvents
Events := utils.FilterEventsOU(LogEvents, "StudentUnenrollmentSettingsProto who_can_unenroll_students", OU)
# Ignore OUs without any events. We're already asserting that the
# top-level OU has at least one event; for all other OUs we assume
# they inherit from a parent OU if they have no events.
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue != "ONLY_TEACHERS_CAN_UNENROLL_STUDENTS"
LastEvent.NewValue != "DELETE_APPLICATION_SETTING"
}
tests contains {
"PolicyId": "GWS.CLASSROOM.4.1v0.3",
"Criticality": "Shall",
"ReportDetails": utils.NoSuchEventDetails(DefaultSafe, utils.TopLevelOU),
"ActualValue": "No relevant event in the current logs",
"RequirementMet": DefaultSafe,
"NoSuchEvent": true
}
if {
DefaultSafe := false
SettingName := "StudentUnenrollmentSettingsProto who_can_unenroll_students"
Events := utils.FilterEventsOU(LogEvents, SettingName, utils.TopLevelOU)
count(Events) == 0
}
tests contains {
"PolicyId": "GWS.CLASSROOM.4.1v0.3",
"Criticality": "Shall",
"ReportDetails": utils.ReportDetails(NonCompliantOUs4_1, []),
"ActualValue": {"NonCompliantOUs": NonCompliantOUs4_1},
"RequirementMet": Status,
"NoSuchEvent": false
}
if {
SettingName := "StudentUnenrollmentSettingsProto who_can_unenroll_students"
Events := utils.FilterEventsOU(LogEvents, SettingName, utils.TopLevelOU)
count(Events) > 0
Status := count(NonCompliantOUs4_1) == 0
}
#--
###################
# GWS.CLASSROOM.5 #
###################
#
# Baseline GWS.CLASSROOM.5.1v0.3
#--
GetFriendlyValue5_1(Value) := "anyone in this domain" if {
Value == "1"
} else := "all pending and verified teachers" if {
Value == "2"
} else := Value
NonCompliantOUs5_1 contains {
"Name": OU,
"Value": concat(" ", [
"Who can create classes is set to",
GetFriendlyValue5_1(LastEvent.NewValue)
])
} if {
some OU in utils.OUsWithEvents
Events := utils.FilterEventsOU(LogEvents, "TeacherPermissionsSettingProto who_can_create_class", OU)
# Ignore OUs without any events. We're already asserting that the
# top-level OU has at least one event; for all other OUs we assume
# they inherit from a parent OU if they have no events.
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue != "3"
LastEvent.NewValue != "DELETE_APPLICATION_SETTING"
}
tests contains {
"PolicyId": "GWS.CLASSROOM.5.1v0.3",
"Criticality": "Shall",
"ReportDetails": utils.NoSuchEventDetails(DefaultSafe, utils.TopLevelOU),
"ActualValue": "No relevant event in the current logs",
"RequirementMet": DefaultSafe,
"NoSuchEvent": true
}
if {
DefaultSafe := false
SettingName := "TeacherPermissionsSettingProto who_can_create_class"
Events := utils.FilterEventsOU(LogEvents, SettingName, utils.TopLevelOU)
count(Events) == 0
}
tests contains {
"PolicyId": "GWS.CLASSROOM.5.1v0.3",
"Criticality": "Shall",
"ReportDetails": utils.ReportDetails(NonCompliantOUs5_1, []),
"ActualValue": {"NonCompliantOUs": NonCompliantOUs5_1},
"RequirementMet": Status,
"NoSuchEvent": false
}
if {
SettingName := "TeacherPermissionsSettingProto who_can_create_class"
Events := utils.FilterEventsOU(LogEvents, SettingName, utils.TopLevelOU)
count(Events) > 0
Status := count(NonCompliantOUs5_1) == 0
}
#--

File diff suppressed because it is too large Load Diff

View File

@@ -1,378 +0,0 @@
package groups
import data.utils
import future.keywords
LogEvents := utils.GetEvents("groups_logs")
################
# GWS.GROUPS.1 #
################
#
# Baseline GWS.GROUPS.1.1v0.3
#--
GetFriendlyValue1_1(Value) :=
"disabled" if {
Value == "CLOSED"
} else := "enabled" if {
Value == "OPEN"
} else := Value
NonCompliantOUs1_1 contains {
"Name": OU,
"Value": concat("", ["Group access from outside the organization is ",
GetFriendlyValue1_1(LastEvent.NewValue)])
} if {
some OU in utils.OUsWithEvents
Events := utils.FilterEventsOU(LogEvents, "GroupsSharingSettingsProto collaboration_policy", OU)
# Ignore OUs without any events. We're already asserting that the
# top-level OU has at least one event; for all other OUs we assume
# they inherit from a parent OU if they have no events.
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue != "CLOSED"
}
tests contains {
"PolicyId": "GWS.GROUPS.1.1v0.3",
"Criticality": "Shall",
"ReportDetails": utils.NoSuchEventDetails(DefaultSafe, utils.TopLevelOU),
"ActualValue": "No relevant event in the current logs",
"RequirementMet": DefaultSafe,
"NoSuchEvent": true
}
if {
DefaultSafe := true
Events := utils.FilterEventsOU(LogEvents, "GroupsSharingSettingsProto collaboration_policy", utils.TopLevelOU)
count(Events) == 0
}
tests contains {
"PolicyId": "GWS.GROUPS.1.1v0.3",
"Criticality": "Shall",
"ReportDetails": utils.ReportDetails(NonCompliantOUs1_1, []),
"ActualValue": {"NonCompliantOUs": NonCompliantOUs1_1},
"RequirementMet": Status,
"NoSuchEvent": false
}
if {
Events := utils.FilterEventsOU(LogEvents, "GroupsSharingSettingsProto collaboration_policy", utils.TopLevelOU)
count(Events) > 0
Status := count(NonCompliantOUs1_1) == 0
}
#--
################
# GWS.GROUPS.2 #
################
#
# Baseline GWS.GROUPS.2.1v0.3
#--
GetFriendlyValue2_1(Value) :=
"Group owners have the ability to add external members to the group" if {
Value != "false"
} else := concat("", ["Group owners do not have the ability to ",
"add external members to the group"]) if {
Value == "false"
} else := Value
NonCompliantOUs2_1 contains {
"Name": OU,
"Value": GetFriendlyValue2_1(LastEvent.NewValue)
} if {
some OU in utils.OUsWithEvents
SettingName := "GroupsSharingSettingsProto owners_can_allow_external_members"
Events := utils.FilterEventsOU(LogEvents, SettingName, OU)
# Ignore OUs without any events. We're already asserting that the
# top-level OU has at least one event; for all other OUs we assume
# they inherit from a parent OU if they have no events.
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue != "false"
}
tests contains {
"PolicyId": "GWS.GROUPS.2.1v0.3",
"Criticality": "Should",
"ReportDetails": utils.NoSuchEventDetails(DefaultSafe, utils.TopLevelOU),
"ActualValue": "No relevant event in the current logs",
"RequirementMet": DefaultSafe,
"NoSuchEvent": true
}
if {
DefaultSafe := true
SettingName := "GroupsSharingSettingsProto owners_can_allow_external_members"
Events := utils.FilterEventsOU(LogEvents, SettingName, utils.TopLevelOU)
count(Events) == 0
}
tests contains {
"PolicyId": "GWS.GROUPS.2.1v0.3",
"Criticality": "Should",
"ReportDetails": utils.ReportDetails(NonCompliantOUs2_1, []),
"ActualValue": {"NonCompliantOUs":NonCompliantOUs2_1},
"RequirementMet": Status,
"NoSuchEvent": false
}
if {
SettingName := "GroupsSharingSettingsProto owners_can_allow_external_members"
Events := utils.FilterEventsOU(LogEvents, SettingName, utils.TopLevelOU)
count(Events) > 0
Status := count(NonCompliantOUs2_1) == 0
}
#--
################
# GWS.GROUPS.3 #
################
#
# Baseline GWS.GROUPS.3.1v0.3
#--
GetFriendlyValue3_1(Value) := concat("", ["Group owners have the ability to allow an ",
"external non-group member to post to the group"]) if {
Value == "true"
} else := concat("", ["Group owners do not have the ability to allow an ",
"external non-group member to post to the group"]) if {
Value == "false"
} else := Value
NonCompliantOUs3_1 contains {
"Name": OU,
"Value": GetFriendlyValue3_1(LastEvent.NewValue)
} if {
some OU in utils.OUsWithEvents
Events := utils.FilterEventsOU(LogEvents,
"GroupsSharingSettingsProto owners_can_allow_incoming_mail_from_public", OU)
# Ignore OUs without any events. We're already asserting that the
# top-level OU has at least one event; for all other OUs we assume
# they inherit from a parent OU if they have no events.
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue != "false"
}
tests contains {
"PolicyId": "GWS.GROUPS.3.1v0.3",
"Criticality": "Should",
"ReportDetails": utils.NoSuchEventDetails(DefaultSafe, utils.TopLevelOU),
"ActualValue": "No relevant event in the current logs",
"RequirementMet": DefaultSafe,
"NoSuchEvent": true
}
if {
DefaultSafe := true
SettingName := "GroupsSharingSettingsProto owners_can_allow_incoming_mail_from_public"
Events := utils.FilterEventsOU(LogEvents, SettingName, utils.TopLevelOU)
count(Events) == 0
}
tests contains {
"PolicyId": "GWS.GROUPS.3.1v0.3",
"Criticality": "Should",
"ReportDetails": utils.ReportDetails(NonCompliantOUs3_1, []),
"ActualValue": {"NonCompliantOUs": NonCompliantOUs3_1},
"RequirementMet": Status,
"NoSuchEvent": false
}
if {
SettingName := "GroupsSharingSettingsProto owners_can_allow_incoming_mail_from_public"
Events := utils.FilterEventsOU(LogEvents, SettingName, utils.TopLevelOU)
count(Events) > 0
Status := count(NonCompliantOUs3_1) == 0
}
#--
################
# GWS.GROUPS.4 #
################
#
# Baseline GWS.GROUPS.4.1v0.3
#--
GetFriendlyValue4_1(Value) :=
"Anyone in the organization can create groups" if {
Value == "USERS_IN_DOMAIN"
} else := "Anyone on the internet can create groups" if {
Value == "WORLD"
} else := Value
NonCompliantOUs4_1 contains {
"Name": OU,
"Value": GetFriendlyValue4_1(LastEvent.NewValue)
} if {
some OU in utils.OUsWithEvents
Events := utils.FilterEventsOU(LogEvents, "GroupsSharingSettingsProto who_can_create_groups", OU)
# Ignore OUs without any events. We're already asserting that the
# top-level OU has at least one event; for all other OUs we assume
# they inherit from a parent OU if they have no events.
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue != "ADMIN_ONLY"
}
tests contains {
"PolicyId": "GWS.GROUPS.4.1v0.3",
"Criticality": "Should",
"ReportDetails":utils.NoSuchEventDetails(DefaultSafe, utils.TopLevelOU),
"ActualValue": "No relevant event in the current logs",
"RequirementMet": DefaultSafe,
"NoSuchEvent": true
}
if {
DefaultSafe := false
Events := utils.FilterEventsOU(LogEvents, "GroupsSharingSettingsProto who_can_create_groups", utils.TopLevelOU)
count(Events) == 0
}
tests contains {
"PolicyId": "GWS.GROUPS.4.1v0.3",
"Criticality": "Should",
"ReportDetails": utils.ReportDetails(NonCompliantOUs4_1, []),
"ActualValue": {"NonCompliantOUs": NonCompliantOUs4_1},
"RequirementMet": Status,
"NoSuchEvent": false
}
if {
Events := utils.FilterEventsOU(LogEvents, "GroupsSharingSettingsProto who_can_create_groups", utils.TopLevelOU)
count(Events) > 0
Status := count(NonCompliantOUs4_1) == 0
}
#--
################
# GWS.GROUPS.5 #
################
#
# Baseline GWS.GROUPS.5.1v0.3
#--
GetFriendlyValue5_1(Value) := "owners"
if {
Value == "OWNERS"
} else := "managers" if {
Value == "MANAGERS"
} else := "domain users" if {
Value == "DOMAIN_USERS"
} else := "anyone on the internet" if {
Value == "PUBLIC"
} else := Value
NonCompliantOUs5_1 contains {
"Name": OU,
"Value": concat("", ["Permission to view conversations is set to ", GetFriendlyValue5_1(LastEvent.NewValue)])
} if {
some OU in utils.OUsWithEvents
Events := utils.FilterEventsOU(LogEvents, "GroupsSharingSettingsProto default_view_topics_access_level", OU)
# Ignore OUs without any events. We're already asserting that the
# top-level OU has at least one event; for all other OUs we assume
# they inherit from a parent OU if they have no events.
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue != "MEMBERS"
}
tests contains {
"PolicyId": "GWS.GROUPS.5.1v0.3",
"Criticality": "Should",
"ReportDetails": utils.NoSuchEventDetails(DefaultSafe, utils.TopLevelOU),
"ActualValue": "No relevant event in the current logs",
"RequirementMet": DefaultSafe,
"NoSuchEvent": true
}
if {
DefaultSafe := false
SettingName := "GroupsSharingSettingsProto default_view_topics_access_level"
Events := utils.FilterEventsOU(LogEvents, SettingName, utils.TopLevelOU)
count(Events) == 0
}
tests contains {
"PolicyId": "GWS.GROUPS.5.1v0.3",
"Criticality": "Should",
"ReportDetails": utils.ReportDetails(NonCompliantOUs5_1, []),
"ActualValue": {"NonCompliantOUs": NonCompliantOUs5_1},
"RequirementMet": Status,
"NoSuchEvent": false
}
if {
SettingName := "GroupsSharingSettingsProto default_view_topics_access_level"
Events := utils.FilterEvents(LogEvents, SettingName, utils.TopLevelOU)
count(Events) > 0
Status := count(NonCompliantOUs5_1) == 0
}
#--
################
# GWS.GROUPS.6 #
################
#
# Baseline GWS.GROUPS.6.1v0.3
#--
CheckGroups6_1Compliance(Events, OUs) := true if {
Groups := utils.FilterEventsOU(Events, "GroupsSharingSettingsProto allow_unlisted_groups", utils.TopLevelOU)
count(Groups) > 0
count(OUs) == 0
}
else := false
GetFriendlyValue6_1(Value) := "Groups can be hidden from the directory" if {
Value == "true"
} else := "Groups cannot be hidden from the directory" if {
Value == "false"
} else := Value
NonCompliantOUs6_1 contains {
"Name": OU,
"Value": GetFriendlyValue6_1(LastEvent.NewValue)
} if {
some OU in utils.OUsWithEvents
Events := utils.FilterEventsOU(LogEvents, "GroupsSharingSettingsProto allow_unlisted_groups", OU)
# Ignore OUs without any events. We're already asserting that the
# top-level OU has at least one event; for all other OUs we assume
# they inherit from a parent OU if they have no events.
count(Events) > 0
LastEvent := utils.GetLastEvent(Events)
LastEvent.NewValue != "false"
}
tests contains {
"PolicyId": "GWS.GROUPS.6.1v0.3",
"Criticality": "Shall",
"ReportDetails": utils.NoSuchEventDetails(DefaultSafe, utils.TopLevelOU),
"ActualValue":"No relevant event in the current logs",
"RequirementMet": DefaultSafe,
"NoSuchEvent": true
}
if {
DefaultSafe := true
Events := utils.FilterEventsOU(LogEvents, "GroupsSharingSettingsProto allow_unlisted_groups", utils.TopLevelOU)
count(Events) == 0
}
tests contains {
"PolicyId": "GWS.GROUPS.6.1v0.3",
"Criticality": "Shall",
"ReportDetails":utils.ReportDetails(NonCompliantOUs6_1, []),
"ActualValue": {"NonCompliantOUs": NonCompliantOUs6_1},
"RequirementMet": Status,
"NoSuchEvent": false
}
if {
Events := utils.FilterEventsOU(LogEvents, "GroupsSharingSettingsProto allow_unlisted_groups", utils.TopLevelOU)
count(Events) > 0
Status := count(NonCompliantOUs6_1) == 0
}
#--

View File

@@ -1,9 +1,25 @@
google-api-python-client==2.142.0
google-auth-httplib2==0.2.0
google-auth-oauthlib==1.2.1
MarkupSafe==2.1.5
dnspython==2.6.1
pandas==2.2.0
tqdm==4.66.5
requests==2.32.3
pyyaml==6.0.2
# This package is used for software development and is not needed by
# the Scubagoggles users:
build
# There are many Python versions for users to install for ScubaGoggles, and
# because of this, it is too restrictive to limit versions of the dependent
# packages to an exact version (using ==). One package version might not be
# available in a version of Python, but a subsequent package version is
# and will work just fine. We have already run into user support issues
# because of this. By requiring a minimum version (using >=), we
# are requiring a version that we support and any subsequent version - this
# gives users much more flexibility in their Python environments.
#
# Any changes to this package dependency list MUST also be reflected in the
# pyproject.toml file.
#
# These packages are the minimum required versions for running Scubagoggles:
dnspython>=2.6.1
google-api-python-client>=2.142.0
google-auth-httplib2>=0.2.0
google-auth-oauthlib>=1.2.1
MarkupSafe>=2.1.5
pyyaml>=6.0.2
requests>=2.32.3
tqdm>=4.66.5

View File

@@ -6,18 +6,7 @@ scuba.py a script that imports and runs the scubagoggles
package
"""
# lets us import files from the scubagoggles folder
import sys
sys.path.insert(1, './scubagoggles')
# However, pylint doesn't like this
from scubagoggles.main import dive # pylint: disable=import-error wrong-import-position
def main():
"""
SCuBA
"""
dive()
from scubagoggles.main import dive
if __name__ == '__main__':
main()
dive()

View File

@@ -15,10 +15,10 @@ This README outlines the ScubaGoggles software test automation structure and its
- [Running Remotely via GitHub Actions](#running-remotely-via-github-actions)
- [Adding New Tests](#adding-new-tests)
## Smoke Testing Prerequisites ##
## Smoke Testing Prerequisites ##
Running the ScubaGoggles functional smoke tests requires a Windows, MacOS, or Linux computer or VM. The development environment should have Python v3.10.x installed at a minimum ([refer to our installing Python dependencies documentation if its not already installed](https://github.com/cisagov/ScubaGoggles/blob/main/docs/installation/DownloadAndInstall.md#installing-python-dependencies)), Pytest, and Selenium installed locally.
### Pytest and Selenium ###
### Pytest and Selenium ###
Pytest is a Python testing framework which is commonly used for unit, integration, and functional testing. ([Pytest Get Started](https://docs.pytest.org/en/stable/getting-started.html))
Selenium supports automation of all the major browsers in the market through the use of WebDriver. ([Selenium Get Started](https://www.selenium.dev/documentation/webdriver/getting_started/))
@@ -42,27 +42,27 @@ Take note of the `subjectemail`, the email used to authenticate with GWS that ha
## Functional Smoke Testing Structure ##
ScubaGoggles functional smoke testing has two main components: the smoke testing orchestrator and the automated workflow run via GitHub Actions.
### Smoke Testing Classes and Methods ###
### Smoke Testing Classes and Methods ###
The smoke testing orchestrator ([/Testing/Functional/SmokeTests/smoke_test.py](https://github.com/cisagov/ScubaGoggles/blob/main/Testing/Functional/SmokeTests/smoke_test.py)) executes each test declared inside the `SmokeTest` class. The tests currently cover:
- if the `scubagoggles gws` command generates valid output for all baselines
- if ScubaResults.json contains API errors or exceptions
- if the generated baseline reports, i.e. BaselineReports.html, CalendarReport.html, ChatReport.html, etc., contain valid content and all links redirect accordingly
- if the generated baseline reports, i.e. BaselineReports.html, CalendarReport.html, ChatReport.html, etc., contain valid content and all links redirect accordingly
The smoke testing utils ([/Testing/Functional/SmokeTests/smoke_test_utils.py](https://github.com/cisagov/ScubaGoggles/blob/main/Testing/Functional/SmokeTests/smoke_test_utils.py)) stores helper methods which perform various operations.
The Selenium Browser class ([/Testing/Functional/SmokeTests/selenium_browser.py](https://github.com/cisagov/ScubaGoggles/blob/main/Testing/Functional/SmokeTests/selenium_browser.py)) encapsulates the setup, usage, and teardown of Selenium WebDriver instances.
The Pytest configuration methods ([/Testing/Functional/SmokeTests/conftest.py](https://github.com/cisagov/ScubaGoggles/blob/main/Testing/Functional/conftest.py)) declare various Pytest fixtures, allowing for the use of CLI arguments when invoking the Pytest command.
The Pytest configuration methods ([/Testing/Functional/SmokeTests/conftest.py](https://github.com/cisagov/ScubaGoggles/blob/main/Testing/Functional/conftest.py)) declare various Pytest fixtures, allowing for the use of CLI arguments when invoking the Pytest command.
### Automated Workflow via GitHub Actions ###
### Automated Workflow via GitHub Actions ###
The automated workflow for running the functional smoke tests ([/.github/workflows/run_smoke_test.yml](https://github.com/cisagov/ScubaGoggles/blob/main/.github/workflows/run_smoke_test.yml)) is triggered on `push` events to the main branch, `pull_request` events when a pull request is opened/reopened/reviewed, and manually with custom user input via workflow_dispatch.
## Functional Smoke Testing Usage ##
## Functional Smoke Testing Usage ##
After completing all of the prerequisite steps, the functional smoke tests can be run in a local development environment or remotely via GitHub Actions.
### Running in a Local Development Environment ###
### Running in a Local Development Environment ###
> [!IMPORTANT]
> Ensure that you have correctly setup a Google service account and that the `credentials.json` stored at the root directory of the ScubaGoggles project is up to date. If you haven't already, please refer back to the [prerequisite step on Google Service Accounts](#google-service-account) for how to setup before proceeding.
> Ensure that you have correctly setup a Google service account and that the `credentials.json` stored at the root directory of the ScubaGoggles project is up to date. If you haven't already, please refer back to the [prerequisite step on Google Service Accounts](#google-service-account) for how to setup before proceeding.
The following arguments are required when running the functional smoke tests:
- `--subjectemail="user@domain.com"` (the email used to authenticate with GWS, must have necessary administrator permissions)
@@ -90,8 +90,8 @@ Common Pytest parameters and their use cases:
Run `pytest -h` for a full list of CLI options or [learn more about Pytest usage here.](https://docs.pytest.org/en/7.1.x/how-to/usage.html)
### Running Remotely via GitHub Actions ###
Go to the [run_smoke_test.yml workflow](https://github.com/cisagov/ScubaGoggles/actions/workflows/run_smoke_test.yml) in the GitHub Actions tab, then click the "Run workflow" dropdown button.
### Running Remotely via GitHub Actions ###
Go to the [run_smoke_test.yml workflow](https://github.com/cisagov/ScubaGoggles/actions/workflows/run_smoke_test.yml) in the GitHub Actions tab, then click the "Run workflow" dropdown button.
The default values are the following:
- ref branch: `main` but can be set to any branch
@@ -107,8 +107,8 @@ Feel free to play around with the inputs then click the "Run workflow" button wh
Some factors to consider:
- Each input is required so an empty string will fail validation. `[]`, `['']`, `['', ]` may also cause the workflow to error out, although this is expected behavior.
- `ubuntu-latest` has not been tested as a value for operating system. Support can be added for this, although its dependent on if this is something we want to test for ScubaGoggles as a whole.
- Python versions <3.10.x are not supported and will cause the smoke test workflow to fail.
- `ubuntu-latest` has not been tested as a value for operating system. Support can be added for this, although its dependent on if this is something we want to test for ScubaGoggles as a whole.
- Python versions <3.10.x are not supported and will cause the smoke test workflow to fail.
- [Due to the lack of an array input type from GitHub](https://github.com/orgs/community/discussions/11692), the required format is an array of strings for the operating system and python version inputs. This is something to capture as a future todo once arrays are available.
## Adding New Tests ##
@@ -123,7 +123,7 @@ class SmokeTest:
def test_scubagoggles_execution(self, subjectemail):
"""
Test if the `scubagoggles gws` command succeeds or fails.
Args:
subjectemail: The email address of an admin user who created the service account
"""

View File

@@ -0,0 +1,3 @@
# These packages are only required for the functional smoke testing
pytest
selenium

View File

@@ -1,10 +1,11 @@
"""
selenium_browser.py declares a Browser class for use in ScubaGoggles testing.
selenium_browser.py declares a Browser class for use in ScubaGoggles testing.
"""
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
class Browser:
"""
The Browser class encapsulates the setup, usage, and teardown of a
@@ -12,10 +13,10 @@ class Browser:
"""
def __init__(self):
chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--window-size=1200,800")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument('--headless')
chrome_options.add_argument('--window-size=1200,800')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
self.driver = webdriver.Chrome(options=chrome_options)
@@ -30,16 +31,16 @@ class Browser:
def quit(self):
"""
Quits the driver, closing every associated window.
Quits the driver, closing every associated window.
"""
self.driver.quit()
def find_element(self, by, value):
"""
Find the first WebElement using the given method.
This method is affected by the 'implicit wait' times in force at the time and execution.
The find_element(...) invocation will return a matching row, or try again repeatedly
until the configured timeout is reached.
Find the first WebElement using the given method. This method is
affected by the 'implicit wait' times in force at the time and
execution. The find_element(...) invocation will return a matching
row, or try again repeatedly until the configured timeout is reached.
Args:
by: The locating mechanism to use, i.e. By.CLASS_NAME, By.TAG_NAME
@@ -52,23 +53,26 @@ class Browser:
def find_elements(self, by, value):
"""
Find all WebElements within the current page.
This method is affected by the 'implicit wait' times in force at the time and execution.
The find_elements(...) invocation will return as soon as there are more than 0 items in
the found collection, or will return an empty list of the timeout is reached.
Find all WebElements within the current page. This method is affected
by the 'implicit wait' times in force at the time and execution. The
find_elements(...) invocation will return as soon as there are more
than 0 items in the found collection, or will return an empty list of
the timeout is reached.
Args:
by: The locating mechanism to use, i.e. By.CLASS_NAME, By.TAG_NAME
value: The locator, i.e. "h1", "header"
Returns:
WebElement: A list of all matching WebElements, or an empty list if nothing matches
WebElement: A list of all matching WebElements, or an empty list
if nothing matches
"""
return self.driver.find_elements(by, value)
def current_url(self):
"""
Get a string representing the current URL that the browser is looking at.
Get a string representing the current URL that the browser is looking
at.
Returns:
The URL of the page currently loaded in the browser

View File

@@ -0,0 +1,82 @@
"""
smoke_test.py declares a SmokeTest class for ScubaGoggles automation testing.
"""
import subprocess
import pytest
from smoke_test_utils import (get_output_path,
get_required_entries,
run_selenium,
sample_report_dir,
top_report_url,
verify_all_outputs_exist,
verify_output_type,
verify_scubaresults)
class SmokeTest:
"""
Pytest class to encapsulate the following test cases:
- Generate the correct output files (BaselineReports.html,
ScubaResults.json, etc)
- Check the content of html files, verify href attributes are
correct, etc
- Check if ScubaResults.json contains errors in the summary. If errors
exist, then either API calls or functions produced exceptions which
need to be handled
"""
@staticmethod
def test_scubagoggles_output(subjectemail: str):
"""
Test if the `scubagoggles gws` command generates correct output for
all baselines.
Args:
subjectemail: The email address of a user for the service account.
If None (or the empty string), the user's OAuth credentials are
used instead.
"""
svc_account_option = (f' --subjectemail {subjectemail}' if subjectemail
else '')
command = f'scubagoggles gws{svc_account_option} --quiet'
try:
subprocess.run(command, shell=True, check=True)
output_path = get_output_path()
output: list = verify_output_type(output_path, [])
report_dir = sample_report_dir()
required_entries = get_required_entries(report_dir, [])
verify_all_outputs_exist(output, required_entries)
except (OSError, ValueError, Exception) as e:
pytest.fail(f'An error occurred, {e}')
@staticmethod
def test_scubaresults():
"""
Determine if ScubaResults.json contains API errors or exceptions.
"""
try:
output_path = get_output_path()
verify_scubaresults(output_path)
except (ValueError, Exception) as e:
pytest.fail(f'An error occurred, {e}')
@staticmethod
def test_scubagoggles_report(browser, customerdomain):
"""
Test if the generated baseline reports are correct,
i.e. BaselineReports.html, CalendarReport.html, ChatReport.html
"""
try:
output_path = get_output_path()
report_path: str = top_report_url(output_path)
browser.get(report_path)
run_selenium(browser, customerdomain)
except (ValueError, AssertionError, Exception) as e:
browser.quit()
pytest.fail(f'An error occurred, {e}')

View File

@@ -1,21 +1,28 @@
"""
Helper methods for running the functional smoke tests.
Helper methods for running the functional smoke tests.
"""
import os
import json
from operator import itemgetter
from pathlib import Path
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
from scubagoggles.orchestrator import Orchestrator
from scubagoggles.utils import get_package_version
from scubagoggles.config import UserConfig
from scubagoggles.user_setup import default_file_names
from scubagoggles.version import Version
OUTPUT_DIRECTORY = "GWSBaselineConformance"
BASELINE_REPORT_H1 = "SCuBA GWS Secure Configuration Baseline Reports"
CISA_GOV_URL = "https://www.cisa.gov/scuba"
SCUBAGOGGLES_BASELINES_URL = "https://github.com/cisagov/ScubaGoggles/tree/main/baselines"
OUTPUT_DIRECTORY = 'GWSBaselineConformance'
BASELINE_REPORT_H1 = 'SCuBA GWS Secure Configuration Baseline Reports'
CISA_GOV_URL = 'https://www.cisa.gov/scuba'
SCUBAGOGGLES_BASELINES_URL = 'https://github.com/cisagov/ScubaGoggles/tree/main/baselines'
def get_output_path() -> str:
def get_output_path() -> Path:
"""
Get the latest output directory created by `scubagoggles gws`.
The default name is "GWSBaselineConformance_<timestamp>.
@@ -23,12 +30,17 @@ def get_output_path() -> str:
Returns:
str: The path to the latest output directory
"""
directories: list = [
d for d in os.listdir()
if os.path.isdir(d) and d.startswith(OUTPUT_DIRECTORY)
]
directories.sort(key=os.path.getctime, reverse=True)
return os.path.join(os.getcwd(), directories[0])
config = UserConfig()
output_dir = config.output_dir
dir_pattern = f'{default_file_names.output_folder_name}*'
directories = [(d, d.stat().st_ctime)
for d in output_dir.glob(dir_pattern)]
directories.sort(key = itemgetter(1), reverse = True)
return directories[0][0]
def prepend_file_protocol(path: str) -> str:
"""
@@ -37,46 +49,81 @@ def prepend_file_protocol(path: str) -> str:
Returns:
str: Path to a file with the local filesystem prepended
"""
if not path.startswith("file://"):
path = "file://" + path
if not path.startswith('file://'):
path = 'file://' + path
return path
def verify_output_type(output_path: str, output: list) -> list:
def verify_output_type(output_path: Path, output: list) -> list:
"""
Checks if the output generated from `scubagoggles` creates the correct output.
Validate files/directories and catch invalid json.
Validate files/directories and catch invalid json.
Args:
output_path: The output path, i.e. "GWSBaselineConformance_<timestamp>"
output: Initialized as an empty list
Returns:
list: All output file and directory names
"""
entries: list = os.listdir(output_path)
for entry in entries:
for entry in output_path.iterdir():
output.append(entry)
# Check if entry is a valid directory or file
# If a valid directory, then recurse
child_path: str = os.path.join(output_path, entry)
if os.path.isdir(child_path):
if entry.is_dir():
assert True
verify_output_type(child_path, output)
elif os.path.isfile(child_path):
verify_output_type(entry, output)
elif os.path.isfile(entry):
# Check for valid json
if child_path.endswith(".json"):
if entry.suffix.lower() == '.json':
try:
with open(child_path, encoding="utf-8") as jsonfile:
with entry.open(encoding = 'utf-8') as jsonfile:
json.load(jsonfile)
except ValueError as e:
raise ValueError(f"{child_path} contains invalid json") from e
raise ValueError(f'{entry} contains invalid json') from e
assert True
else:
raise OSError("Entry is not a directory or file (symlink, etc.)")
raise OSError('Entry is not a directory or file (symlink, etc.)')
return output
def sample_report_dir() -> Path:
"""Returns the location of the ScubaGoggles sample report directory. It's
assumed that this directory located up the directory hierarchy where this
script is located.
:return: Path pointing to the sample report directory.
"""
current_dir = Path(__file__).parent
while current_dir.anchor != str(current_dir):
report_path = current_dir / 'sample-report'
if report_path.is_dir():
return report_path
current_dir = current_dir.parent
raise NotADirectoryError('? sample report directory missing')
def top_report_url(output_path: Path) -> str:
"""Returns the URL for the top-level HTML ScubaGoggles baseline report,
given the output directory from a conformance run.
:param Path output_path: ScubaGoggles output directory
:return: local (file://) URL for the top-level HTML report.
"""
report_path = output_path / f'{default_file_names.report_output_name}.html'
return prepend_file_protocol(str(report_path))
def get_required_entries(sample_report, required_entries) -> list:
"""
From the "sample-report" directory, add all file and directory names
@@ -86,17 +133,18 @@ def get_required_entries(sample_report, required_entries) -> list:
Args:
sample_report: Path where "sample-report" is located in the project
required_entries: Initialized as an empty list
Returns:
list: All required file and directory names
"""
with os.scandir(sample_report) as entries:
for entry in entries:
required_entries.append(entry.name)
if entry.is_dir():
get_required_entries(entry.path, required_entries)
for entry in sample_report.iterdir():
required_entries.append(entry.name)
if entry.is_dir():
get_required_entries(entry, required_entries)
return required_entries
def verify_all_outputs_exist(output: list, required_entries: list):
"""
Verify all files and directories are created after running `scubagoggles gws`.
@@ -105,25 +153,32 @@ def verify_all_outputs_exist(output: list, required_entries: list):
output: a list of all files and directories generated by `scubagoggles gws`
required_entries: a list of all required file and directory names
"""
output_names = {entry.name for entry in output}
for required_entry in required_entries:
if required_entry in output:
if required_entry in output_names:
assert True
else:
raise ValueError(f"{required_entry} was not found in the generated report")
raise ValueError(f'{required_entry} was not found in the generated report')
def verify_scubaresults(jsonfile):
def verify_scubaresults(output_path: Path):
"""
Verify "ScubaResults.json" is valid, and check if any errors
are displayed in the reports.
Args:
jsonfile: Path to a json file
output_path: ScubaGoggles output directory containing the results JSON
file.
"""
scubaresults = json.load(jsonfile)
summaries = scubaresults["Summary"]
results_path = output_path / f'{default_file_names.json_output_name}.json'
with results_path.open(encoding = 'utf-8') as jsonfile:
scubaresults = json.load(jsonfile)
summaries = scubaresults['Summary']
for product, summary in summaries.items():
if summary["Errors"] != 0:
raise ValueError(f"{product} contains errors in the report")
if summary['Errors'] != 0:
raise ValueError(f'{product} contains errors in the report')
def run_selenium(browser, customerdomain):
"""
@@ -134,13 +189,13 @@ def run_selenium(browser, customerdomain):
customerdomain: The customer domain
"""
verify_navigation_links(browser)
h1 = browser.find_element(By.TAG_NAME, "h1").text
h1 = browser.find_element(By.TAG_NAME, 'h1').text
assert h1 == BASELINE_REPORT_H1
gws_products = Orchestrator.gws_products()
products = {
product: { "title": f"{product} Baseline Report" }
for product in gws_products["prod_to_fullname"].values()
product: { 'title': f'{product} Baseline Report' }
for product in gws_products['prod_to_fullname'].values()
}
# Before entering loop check that we actually display 10 rows in table
@@ -154,61 +209,62 @@ def run_selenium(browser, customerdomain):
verify_tenant_table(browser, customerdomain, True)
reports_table = get_reports_table(browser)[i]
baseline_report = reports_table.find_elements(By.TAG_NAME, "td")[0]
baseline_report = reports_table.find_elements(By.TAG_NAME, 'td')[0]
product = baseline_report.text
assert product in products
individual_report_anchor = baseline_report.find_element(By.TAG_NAME, "a")
individual_report_anchor_href = individual_report_anchor.get_attribute("href")
individual_report_anchor = baseline_report.find_element(By.TAG_NAME, 'a')
individual_report_anchor_href = individual_report_anchor.get_attribute('href')
individual_report_anchor.click()
current_url = browser.current_url()
assert individual_report_anchor_href == current_url
# Check at the individual report level
verify_navigation_links(browser)
h1 = browser.find_element(By.TAG_NAME, "h1").text
assert h1 == products[product]["title"]
h1 = browser.find_element(By.TAG_NAME, 'h1').text
assert h1 == products[product]['title']
# Check if customerdomain and tool version are present in individual report
verify_tenant_table(browser, customerdomain, False)
policy_tables = browser.find_elements(By.TAG_NAME, "table")
policy_tables = browser.find_elements(By.TAG_NAME, 'table')
for table in policy_tables[1:]:
# Verify policy table headers are correct
headers = (
table.find_element(By.TAG_NAME, "thead")
.find_elements(By.TAG_NAME, "tr")[0]
.find_elements(By.TAG_NAME, "th")
table.find_element(By.TAG_NAME, 'thead')
.find_elements(By.TAG_NAME, 'tr')[0]
.find_elements(By.TAG_NAME, 'th')
)
assert len(headers) == 5
assert headers[0].text == "Control ID"
assert headers[1].text in "Requirements" or headers[1].text in "Rule Name"
assert headers[2].text == "Result"
assert headers[3].text == "Criticality"
assert headers[4].text in "Details" or headers[4].text in "Rule Description"
assert headers[0].text == 'Control ID'
assert headers[1].text in 'Requirements' or headers[1].text in 'Rule Name'
assert headers[2].text == 'Result'
assert headers[3].text == 'Criticality'
assert headers[4].text in 'Details' or headers[4].text in 'Rule Description'
# Verify policy table rows are populated
tbody = table.find_element(By.TAG_NAME, "tbody")
rows = tbody.find_elements(By.TAG_NAME, "tr")
tbody = table.find_element(By.TAG_NAME, 'tbody')
rows = tbody.find_elements(By.TAG_NAME, 'tr')
assert len(rows) > 0
parent_report_anchor = (
browser.find_element(By.TAG_NAME, "header")
.find_element(By.TAG_NAME, "a")
browser.find_element(By.TAG_NAME, 'header')
.find_element(By.TAG_NAME, 'a')
)
parent_report_anchor_href = parent_report_anchor.get_attribute("href")
parent_report_anchor_href = parent_report_anchor.get_attribute('href')
parent_report_anchor.click()
current_url = browser.current_url()
assert parent_report_anchor_href == current_url
WebDriverWait(browser, 10).until(
expected_conditions.presence_of_element_located(
(By.TAG_NAME, "body")
(By.TAG_NAME, 'body')
)
)
else:
raise ValueError("Expected the reports table to have a length of 10")
raise ValueError('Expected the reports table to have a length of 10')
def verify_navigation_links(browser):
"""
@@ -218,12 +274,13 @@ def verify_navigation_links(browser):
browser: A Selenium WebDriver instance
"""
links = (
browser.find_element(By.CLASS_NAME, "links")
.find_elements(By.TAG_NAME, "a")
browser.find_element(By.CLASS_NAME, 'links')
.find_elements(By.TAG_NAME, 'a')
)
if len(links) == 2:
assert links[0].get_attribute("href") == CISA_GOV_URL
assert links[1].get_attribute("href") == SCUBAGOGGLES_BASELINES_URL
assert links[0].get_attribute('href') == CISA_GOV_URL
assert links[1].get_attribute('href') == SCUBAGOGGLES_BASELINES_URL
def get_reports_table(browser):
"""
@@ -234,9 +291,9 @@ def get_reports_table(browser):
browser: A Selenium WebDriver instance
"""
return (
browser.find_elements(By.TAG_NAME, "table")[1]
.find_element(By.TAG_NAME, "tbody")
.find_elements(By.TAG_NAME, "tr")
browser.find_elements(By.TAG_NAME, 'table')[1]
.find_element(By.TAG_NAME, 'tbody')
.find_elements(By.TAG_NAME, 'tr')
)
def verify_tenant_table(browser, customerdomain, parent):
@@ -250,19 +307,18 @@ def verify_tenant_table(browser, customerdomain, parent):
parent: boolean to determine parent/individual reports
"""
tenant_table_rows = (
browser.find_element(By.TAG_NAME, "table")
.find_element(By.TAG_NAME, "tbody")
.find_elements(By.TAG_NAME, "tr")
browser.find_element(By.TAG_NAME, 'table')
.find_element(By.TAG_NAME, 'tbody')
.find_elements(By.TAG_NAME, 'tr')
)
assert len(tenant_table_rows) == 2
domain = tenant_table_rows[1].find_elements(By.TAG_NAME, "td")[0].text
domain = tenant_table_rows[1].find_elements(By.TAG_NAME, 'td')[0].text
assert domain == customerdomain
if not parent:
# Check for correct tool version, e.g. 0.2.0
version = get_package_version("scubagoggles")
tool_version = tenant_table_rows[1].find_elements(By.TAG_NAME, "td")[3].text
assert version == tool_version
tool_version = tenant_table_rows[1].find_elements(By.TAG_NAME, 'td')[3].text
assert tool_version == Version.current
# Baseline version should also be checked in this method
# Add as an additional todo

View File

@@ -5,6 +5,7 @@
import pytest
from SmokeTests.selenium_browser import Browser
def pytest_addoption(parser):
"""
Add custom cli arguments when running `pytest`.
@@ -15,6 +16,7 @@ def pytest_addoption(parser):
parser.addoption("--subjectemail", action="store")
parser.addoption("--customerdomain", action="store")
@pytest.fixture
def subjectemail(pytestconfig):
"""
@@ -25,6 +27,7 @@ def subjectemail(pytestconfig):
"""
return pytestconfig.getoption("subjectemail")
@pytest.fixture
def customerdomain(pytestconfig):
"""
@@ -35,6 +38,7 @@ def customerdomain(pytestconfig):
"""
return pytestconfig.getoption("customerdomain")
@pytest.fixture
def browser():
"""

View File

@@ -1,12 +1,19 @@
package calendar
import future.keywords
import data.utils.FailTestBothNonCompliant
import data.utils.FailTestGroupNonCompliant
import data.utils.FailTestNoEvent
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
#
# GWS.CALENDAR.1.1v0.3
# GWS.CALENDAR.1.1
#--
test_ExtSharingPrimaryCal_Correct_V1 if {
# Test external sharing for primary calendars when there's only one event
PolicyId := "GWS.CALENDAR.1.1v0.3"
PolicyId := CalendarId1_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -26,16 +33,12 @@ test_ExtSharingPrimaryCal_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_ExtSharingPrimaryCal_Correct_V2 if {
# Test external sharing for primary calendars when there's multiple events and the most most recent is correct
PolicyId := "GWS.CALENDAR.1.1v0.3"
PolicyId := CalendarId1_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -66,16 +69,12 @@ test_ExtSharingPrimaryCal_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_ExtSharingPrimaryCal_Correct_V3 if {
# Test external sharing for primary calendars when there's multiple OUs
PolicyId := "GWS.CALENDAR.1.1v0.3"
PolicyId := CalendarId1_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -106,16 +105,12 @@ test_ExtSharingPrimaryCal_Correct_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_ExtSharingPrimaryCal_Correct_V4 if {
# Test external sharing for primary calendars when there's multiple OUs, and an older event is non-compliant
PolicyId := "GWS.CALENDAR.1.1v0.3"
PolicyId := CalendarId1_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -157,16 +152,12 @@ test_ExtSharingPrimaryCal_Correct_V4 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_ExtSharingPrimaryCal_Correct_V5 if {
# Test external sharing for primary, inherit from parent
PolicyId := "GWS.CALENDAR.1.1v0.3"
PolicyId := CalendarId1_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -208,16 +199,12 @@ test_ExtSharingPrimaryCal_Correct_V5 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_ExtSharingPrimaryCal_Correct_V6 if {
# Test group
PolicyId := "GWS.CALENDAR.1.1v0.3"
PolicyId := CalendarId1_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -249,16 +236,12 @@ test_ExtSharingPrimaryCal_Correct_V6 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_ExtSharingPrimaryCal_Incorrect_V1 if {
# Test external sharing for primary calendars when there are no relevant events
PolicyId := "GWS.CALENDAR.1.1v0.3"
PolicyId := CalendarId1_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -278,20 +261,12 @@ test_ExtSharingPrimaryCal_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}
test_ExtSharingPrimaryCal_Incorrect_V2 if {
# Test external sharing for primary calendars when there's only one event and it's wrong
PolicyId := "GWS.CALENDAR.1.1v0.3"
PolicyId := CalendarId1_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -311,18 +286,14 @@ test_ExtSharingPrimaryCal_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"External sharing options for primary calendars is set to ",
"Share all information, but outsiders cannot change calendars</li></ul>"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage1_1("Share all information, but outsiders cannot change calendars")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_ExtSharingPrimaryCal_Incorrect_V3 if {
# Test external sharing for primary calendars when there are multiple events and the most recent is wrong
PolicyId := "GWS.CALENDAR.1.1v0.3"
PolicyId := CalendarId1_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -353,19 +324,15 @@ test_ExtSharingPrimaryCal_Incorrect_V3 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"External sharing options for primary calendars is set to ",
"Share all information, but outsiders cannot change calendars</li></ul>"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage1_1("Share all information, but outsiders cannot change calendars")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_ExtSharingPrimaryCal_Incorrect_V4 if {
# Test external sharing for primary calendars when there is no event for the Top-level OU
# but there is one for a different OU
PolicyId := "GWS.CALENDAR.1.1v0.3"
PolicyId := CalendarId1_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -385,21 +352,13 @@ test_ExtSharingPrimaryCal_Incorrect_V4 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}
test_ExtSharingPrimaryCal_Incorrect_V5 if {
# Test external sharing for primary calendars when the Top-Level OU is compliant,
# but a secondary OU is non-compliant
PolicyId := "GWS.CALENDAR.1.1v0.3"
PolicyId := CalendarId1_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -430,18 +389,14 @@ test_ExtSharingPrimaryCal_Incorrect_V5 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Secondary OU: ",
"External sharing options for primary calendars is set to ",
"Share all information, but outsiders cannot change calendars</li></ul>"])
failedOU := [{"Name": "Secondary OU",
"Value": NonComplianceMessage1_1("Share all information, but outsiders cannot change calendars")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_ExtSharingPrimaryCal_Incorrect_V6 if {
# Test: top-level OU is compliant but a group is non-compliant
PolicyId := "GWS.CALENDAR.1.1v0.3"
PolicyId := CalendarId1_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -473,18 +428,15 @@ test_ExtSharingPrimaryCal_Incorrect_V6 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following groups are non-compliant:<ul><li>group1@example.com: ",
"External sharing options for primary calendars is set to ",
"Share all information, but outsiders cannot change calendars</li></ul>"])
Value := "Share all information, but outsiders cannot change calendars"
failedGroup := [{"Name": "group1@example.com",
"Value": NonComplianceMessage1_1(Value)}]
FailTestGroupNonCompliant(PolicyId, Output, failedGroup)
}
test_ExtSharingPrimaryCal_Incorrect_V if {
# Test: top-level OU and a group are non-compliant
PolicyId := "GWS.CALENDAR.1.1v0.3"
PolicyId := CalendarId1_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -516,25 +468,22 @@ test_ExtSharingPrimaryCal_Incorrect_V if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"External sharing options for primary calendars is set to ",
"Share all information, but outsiders cannot change calendars</li></ul><br>",
"The following groups are non-compliant:<ul><li>group1@example.com: ",
"External sharing options for primary calendars is set to ",
"Share all information, but outsiders cannot change calendars</li></ul>"])
Value := "Share all information, but outsiders cannot change calendars"
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage1_1(Value)}]
failedGroup := [{"Name": "group1@example.com",
"Value": NonComplianceMessage1_1(Value)}]
FailTestBothNonCompliant(PolicyId, Output, failedOU, failedGroup)
}
#--
#
# GWS.CALENDAR.1.2v0.3
# GWS.CALENDAR.1.2
#--
test_ExtSharingSecondaryCal_Correct_V1 if {
# Test external sharing for secondary calendars when there's only one event
PolicyId := "GWS.CALENDAR.1.2v0.3"
PolicyId := CalendarId1_2
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -554,19 +503,12 @@ test_ExtSharingSecondaryCal_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"Requirement met.<br>",
"Highest Level of Sharing: Only free/busy information (hide event details)."
])
PassTestResult(PolicyId, Output)
}
test_ExtSharingSecondaryCal_Correct_V2 if {
# Test external sharing for secondary calendars when there's multiple events and the most most recent is correct
PolicyId := "GWS.CALENDAR.1.2v0.3"
PolicyId := CalendarId1_2
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -597,19 +539,12 @@ test_ExtSharingSecondaryCal_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"Requirement met.<br>",
"Highest Level of Sharing: Only free/busy information (hide event details)."
])
PassTestResult(PolicyId, Output)
}
test_ExtSharingSecondaryCal_Incorrect_V1 if {
# Test external sharing for secondary calendars when there are no relevant events
PolicyId := "GWS.CALENDAR.1.2v0.3"
PolicyId := CalendarId1_2
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -629,20 +564,12 @@ test_ExtSharingSecondaryCal_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
test_ExtSharingSecondaryCal_Incorrect_V2 if {
# Test external sharing for secondary calendars when there's only one event and it's wrong
PolicyId := "GWS.CALENDAR.1.2v0.3"
PolicyId := CalendarId1_2
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -662,20 +589,14 @@ test_ExtSharingSecondaryCal_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"Requirement not met.<br>",
"Highest Level of Sharing: Secondary Calendars Share all information,",
" but outsiders cannot change calendars."
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage1_2("Share all information, but outsiders cannot change calendars")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_ExtSharingSecondaryCal_Incorrect_V3 if {
# Test external sharing for secondary calendars when there are multiple events and the most recent is wrong
PolicyId := "GWS.CALENDAR.1.2v0.3"
PolicyId := CalendarId1_2
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -706,15 +627,8 @@ test_ExtSharingSecondaryCal_Incorrect_V3 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"Requirement not met.<br>",
"Highest Level of Sharing: Secondary Calendars Share all information,",
" but outsiders cannot change calendars."
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage1_2("Share all information, but outsiders cannot change calendars")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
#--

View File

@@ -1,12 +1,18 @@
package calendar
import future.keywords
import data.utils.FailTestBothNonCompliant
import data.utils.FailTestNoEvent
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
#
# Policy 1
# GWS.CALENDAR.2.1
#--
test_ExtInvitationsWarning_Correct_V1 if {
# Test external invitations warnings when there's only one event
PolicyId := "GWS.CALENDAR.2.1v0.3"
PolicyId := CalendarId2_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -26,16 +32,12 @@ test_ExtInvitationsWarning_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_ExtInvitationsWarning_Correct_V2 if {
# Test external invitations warning when there's multiple events and the most most recent is correct
PolicyId := "GWS.CALENDAR.2.1v0.3"
PolicyId := CalendarId2_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -66,16 +68,12 @@ test_ExtInvitationsWarning_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_ExtInvitationsWarning_Correct_V3 if {
# Test external invitations warning when there's multiple OUs
PolicyId := "GWS.CALENDAR.2.1v0.3"
PolicyId := CalendarId2_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -106,16 +104,12 @@ test_ExtInvitationsWarning_Correct_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_ExtInvitationsWarning_Correct_V4 if {
# Test external invitations warning when there's multiple OUs, and an older event is non-compliant
PolicyId := "GWS.CALENDAR.2.1v0.3"
PolicyId := CalendarId2_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -157,16 +151,12 @@ test_ExtInvitationsWarning_Correct_V4 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_ExtInvitationsWarning_Incorrect_V1 if {
# Test external invitations warning when there are no relevant events
PolicyId := "GWS.CALENDAR.2.1v0.3"
PolicyId := CalendarId2_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -186,20 +176,12 @@ test_ExtInvitationsWarning_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}
test_ExtInvitationsWarning_Incorrect_V2 if {
# Test external invitations warning when there's only one event and it's wrong
PolicyId := "GWS.CALENDAR.2.1v0.3"
PolicyId := CalendarId2_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -219,18 +201,14 @@ test_ExtInvitationsWarning_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:",
"<ul><li>Test Top-Level OU: External Sharing Guest Prompt is disabled.</li></ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage2_1("disabled")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_ExtInvitationsWarning_Incorrect_V3 if {
# Test external invitations warning when there are multiple events and the most recent is wrong
PolicyId := "GWS.CALENDAR.2.1v0.3"
PolicyId := CalendarId2_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -261,19 +239,14 @@ test_ExtInvitationsWarning_Incorrect_V3 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>",
"Test Top-Level OU: External Sharing Guest Prompt is disabled.</li></ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage2_1("disabled")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_ExtInvitationsWarning_Incorrect_V4 if {
# Test external invitations warning when there is no event for the Top-level OU but there is one for a different OU
PolicyId := "GWS.CALENDAR.2.1v0.3"
PolicyId := CalendarId2_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -293,20 +266,12 @@ test_ExtInvitationsWarning_Incorrect_V4 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}
test_ExtInvitationsWarning_Incorrect_V5 if {
# Test external invitations warning when the Top-Level OU is compliant, but a secondary OU is non-compliant
PolicyId := "GWS.CALENDAR.2.1v0.3"
PolicyId := CalendarId2_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -337,18 +302,14 @@ test_ExtInvitationsWarning_Incorrect_V5 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:",
"<ul><li>Secondary OU: ",
"External Sharing Guest Prompt is disabled.</li></ul>"])
failedOU := [{"Name": "Secondary OU",
"Value": NonComplianceMessage2_1("disabled")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_ExtInvitationsWarning_Incorrect_V6 if {
# Test ou and group
PolicyId := "GWS.CALENDAR.2.1v0.3"
PolicyId := CalendarId2_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -380,14 +341,10 @@ test_ExtInvitationsWarning_Incorrect_V6 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("",["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"External Sharing Guest Prompt is disabled.</li></ul><br>",
"The following groups are non-compliant:",
"<ul><li>group1@example.com: ",
"External Sharing Guest Prompt is disabled.</li></ul>"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage2_1("disabled")}]
failedGroup := [{"Name": "group1@example.com",
"Value": NonComplianceMessage2_1("disabled")}]
FailTestBothNonCompliant(PolicyId, Output, failedOU, failedGroup)
}
#--
#--

View File

@@ -1,13 +1,17 @@
package calendar
import future.keywords
import future.keywords
import data.utils.FailTestNoEvent
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
#
# Policy 1
# GWS.CALENDAR.3.1
#--
test_CalInteropMan_Correct_V1 if {
# Test calendar interop management when there's only one event
PolicyId := "GWS.CALENDAR.3.1v0.3"
PolicyId := CalendarId3_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -27,17 +31,12 @@ test_CalInteropMan_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails ==
"Requirement met."
PassTestResult(PolicyId, Output)
}
test_CalInteropMan_Correct_V2 if {
# Test calendar interop management when there's multiple events and the most most recent is correct
PolicyId := "GWS.CALENDAR.3.1v0.3"
PolicyId := CalendarId3_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -68,17 +67,12 @@ test_CalInteropMan_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails ==
"Requirement met."
PassTestResult(PolicyId, Output)
}
test_CalInteropMan_Incorrect_V1 if {
# Test calendar interop management when there are no relevant events
PolicyId := "GWS.CALENDAR.3.1v0.3"
PolicyId := CalendarId3_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -98,20 +92,12 @@ test_CalInteropMan_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}
test_CalInteropMan_Incorrect_V2 if {
# Test calendar interop management when there's only one event and it's wrong
PolicyId := "GWS.CALENDAR.3.1v0.3"
PolicyId := CalendarId3_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -131,16 +117,14 @@ test_CalInteropMan_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement not met."
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage3_1("enabled")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_CalInteropMan_Incorrect_V3 if {
# Test calendar interop management when there are multiple events and the most recent is wrong
PolicyId := "GWS.CALENDAR.3.1v0.3"
PolicyId := CalendarId3_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -171,21 +155,19 @@ test_CalInteropMan_Incorrect_V3 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement not met."
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage3_1("enabled")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
#
# GWS.CALENDAR.3.2v0.3
# GWS.CALENDAR.3.2
#--
test_OAuth_Correct_V1 if {
# Not-Implemented
PolicyId := "GWS.CALENDAR.3.2v0.3"
PolicyId := CalendarId3_2
Output := tests with input as {
"calendar_logs": {"items": [
]},
@@ -200,4 +182,4 @@ test_OAuth_Correct_V1 if {
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Currently not able to be tested automatically; please manually check."
}
#--
#--

View File

@@ -1,12 +1,16 @@
package calendar
import future.keywords
import data.utils.FailTestNoEvent
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
#
# GWS.CALENDAR.4.1v0.3
# GWS.CALENDAR.4.1
#--
test_CalendarAppointmentSlot_Correct_V1 if {
# Test Calendar Appointment Slot when there's only one event
PolicyId := "GWS.CALENDAR.4.1v0.3"
PolicyId := CalendarId4_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -25,16 +29,12 @@ test_CalendarAppointmentSlot_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_CalendarAppointmentSlot_Correct_V2 if {
# Test Calendar Appointment Slot when there's multiple events and the most recent is correct
PolicyId := "GWS.CALENDAR.4.1v0.3"
PolicyId := CalendarId4_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -63,16 +63,12 @@ test_CalendarAppointmentSlot_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_CalendarAppointmentSlot_Correct_V3 if {
# Test Calendar Appointment Slot when there's correct events in multiple OUs
PolicyId := "GWS.CALENDAR.4.1v0.3"
PolicyId := CalendarId4_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -101,16 +97,12 @@ test_CalendarAppointmentSlot_Correct_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_CalendarAppointmentSlot_Incorrect_V1 if {
# Test Calendar Appointment Slot when there are no relevant events
PolicyId := "GWS.CALENDAR.4.1v0.3"
PolicyId := CalendarId4_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -129,20 +121,12 @@ test_CalendarAppointmentSlot_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}
test_CalendarAppointmentSlot_Incorrect_V2 if {
# Test Calendar Appointment Slot when there's only one event and it's wrong
PolicyId := "GWS.CALENDAR.4.1v0.3"
PolicyId := CalendarId4_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -161,17 +145,14 @@ test_CalendarAppointmentSlot_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Paid calendar appointments are enabled.</li></ul>"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage4_1("enabled")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_CalendarAppointmentSlot_Incorrect_V3 if {
# Test Calendar Appointment Slot when there are multiple events and the most recent is wrong
PolicyId := "GWS.CALENDAR.4.1v0.3"
PolicyId := CalendarId4_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -200,17 +181,14 @@ test_CalendarAppointmentSlot_Incorrect_V3 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Paid calendar appointments are enabled.</li></ul>"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage4_1("enabled")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_CalendarAppointmentSlot_Incorrect_V4 if {
# Test Calendar Appointment Slot when there's only one event and it's wrong
PolicyId := "GWS.CALENDAR.4.1v0.3"
PolicyId := CalendarId4_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -229,17 +207,14 @@ test_CalendarAppointmentSlot_Incorrect_V4 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Secondary OU: ",
"Paid calendar appointments are enabled.</li></ul>"])
failedOU := [{"Name": "Secondary OU",
"Value": NonComplianceMessage4_1("enabled")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_CalendarAppointmentSlot_Incorrect_V5 if {
# Test Calendar Appointment Slot when there are multiple events and the most recent is wrong
PolicyId := "GWS.CALENDAR.4.1v0.3"
PolicyId := CalendarId4_1
Output := tests with input as {
"calendar_logs": {"items": [
{
@@ -268,11 +243,8 @@ test_CalendarAppointmentSlot_Incorrect_V5 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Secondary OU: ",
"Paid calendar appointments are enabled.</li></ul>"])
failedOU := [{"Name": "Secondary OU",
"Value": NonComplianceMessage4_1("enabled")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
#--

View File

@@ -0,0 +1,76 @@
package calendar
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
GoodCalendarApi01 := {
"policies": {
"topOU": {
"calendar_primary_calendar_max_allowed_external_sharing": {
"maxAllowedExternalSharing": "EXTERNAL_FREE_BUSY_ONLY"},
"calendar_secondary_calendar_max_allowed_external_sharing": {
"maxAllowedExternalSharing": "EXTERNAL_FREE_BUSY_ONLY"},
"calendar_service_status": {"serviceState": "ENABLED"}
},
"nextOU": {
"calendar_primary_calendar_max_allowed_external_sharing": {
"maxAllowedExternalSharing": "EXTERNAL_ALL_INFO_READ_WRITE"},
"calendar_secondary_calendar_max_allowed_external_sharing": {
"maxAllowedExternalSharing": "EXTERNAL_ALL_INFO_READ_WRITE_MANAGE"},
"calendar_service_status": {"serviceState": "DISABLED"}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
BadCalendarApi01 := {
"policies": {
"topOU": {
"calendar_primary_calendar_max_allowed_external_sharing": {
"maxAllowedExternalSharing": "EXTERNAL_ALL_INFO_READ_WRITE"},
"calendar_secondary_calendar_max_allowed_external_sharing": {
"maxAllowedExternalSharing": "EXTERNAL_ALL_INFO_READ_WRITE_MANAGE"},
"calendar_service_status": {"serviceState": "ENABLED"}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
test_CalendarAPI_PrimaryShare_Correct_1 if {
PolicyId := CalendarId1_1
Output := tests with input as GoodCalendarApi01
PassTestResult(PolicyId, Output)
}
test_CalendarAPI_PrimaryShare_Incorrect_1 if {
PolicyId := CalendarId1_1
Output := tests with input as BadCalendarApi01
failedMsgValue := GetFriendlyValue1_1("EXTERNAL_ALL_INFO_READ_WRITE")
failedOU := [{"Name": "topOU",
"Value": NonComplianceMessage1_1(failedMsgValue)}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_CalendarAPI_SecondaryShare_Correct_1 if {
PolicyId := CalendarId1_2
Output := tests with input as GoodCalendarApi01
PassTestResult(PolicyId, Output)
}
test_CalendarAPI_SecondaryShare_Incorrect_1 if {
PolicyId := CalendarId1_2
Output := tests with input as BadCalendarApi01
failedMsgValue := GetFriendlyValue1_2("EXTERNAL_ALL_INFO_READ_WRITE_MANAGE")
failedOU := [{"Name": "topOU",
"Value": NonComplianceMessage1_2(failedMsgValue)}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}

View File

@@ -0,0 +1,49 @@
package calendar
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
GoodCalendarApi02 := {
"policies": {
"topOU": {
"calendar_external_invitations": {"warnOnInvite": true},
"calendar_service_status": {"serviceState": "ENABLED"}
},
"nextOU": {
"calendar_external_invitations": {"warnOnInvite": false},
"calendar_service_status": {"serviceState": "DISABLED"}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
BadCalendarApi02 := {
"policies": {
"topOU": {
"calendar_external_invitations": {"warnOnInvite": false},
"calendar_service_status": {"serviceState": "ENABLED"}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
test_CalendarAPI_WarnExternal_Correct_1 if {
PolicyId := CalendarId2_1
Output := tests with input as GoodCalendarApi02
PassTestResult(PolicyId, Output)
}
test_CalendarAPI_WarnExternal_Incorrect_1 if {
PolicyId := CalendarId2_1
Output := tests with input as BadCalendarApi02
failedOU := [{"Name": "topOU",
"Value": NonComplianceMessage2_1("disabled")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}

View File

@@ -0,0 +1,49 @@
package calendar
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
GoodCalendarApi03 := {
"policies": {
"topOU": {
"calendar_interoperability": {"enableInteroperability": false},
"calendar_service_status": {"serviceState": "ENABLED"}
},
"nextOU": {
"calendar_interoperability": {"enableInteroperability": true},
"calendar_service_status": {"serviceState": "DISABLED"}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
BadCalendarApi03 := {
"policies": {
"topOU": {
"calendar_interoperability": {"enableInteroperability": true},
"calendar_service_status": {"serviceState": "ENABLED"}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
test_CalendarAPI_Interoperability_Correct_1 if {
PolicyId := CalendarId3_1
Output := tests with input as GoodCalendarApi03
PassTestResult(PolicyId, Output)
}
test_CalendarAPI_Interoperability_Incorrect_1 if {
PolicyId := CalendarId3_1
Output := tests with input as BadCalendarApi03
failedOU := [{"Name": "topOU",
"Value": NonComplianceMessage3_1("enabled")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}

View File

@@ -0,0 +1,49 @@
package calendar
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
GoodCalendarApi04 := {
"policies": {
"topOU": {
"calendar_appointment_schedules": {"enablePayments": false},
"calendar_service_status": {"serviceState": "ENABLED"}
},
"nextOU": {
"calendar_appointment_schedules": {"enablePayments": true},
"calendar_service_status": {"serviceState": "DISABLED"}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
BadCalendarApi04 := {
"policies": {
"topOU": {
"calendar_appointment_schedules": {"enablePayments": true},
"calendar_service_status": {"serviceState": "ENABLED"}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
test_CalendarAPI_Payments_Correct_1 if {
PolicyId := CalendarId4_1
Output := tests with input as GoodCalendarApi04
PassTestResult(PolicyId, Output)
}
test_CalendarAPI_Payments_Incorrect_1 if {
PolicyId := CalendarId4_1
Output := tests with input as BadCalendarApi04
failedOU := [{"Name": "topOU",
"Value": NonComplianceMessage4_1("enabled")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}

View File

@@ -1,12 +1,16 @@
package chat
import future.keywords
import data.utils.FailTestNoEvent
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
#
#GWS.CHAT.1.1v0.3
# GWS.CHAT.1.1
#--
test_History_Correct_V1 if {
# Test history setting when there's only one event
PolicyId := "GWS.CHAT.1.1v0.3"
PolicyId := ChatId1_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -25,17 +29,12 @@ test_History_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_History_Correct_V2 if {
# Test history setting when there's multiple events and the most most recent is correct
PolicyId := "GWS.CHAT.1.1v0.3"
PolicyId := ChatId1_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -64,16 +63,12 @@ test_History_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_History_Correct_V3 if {
# Test history setting when there's multiple OUs
PolicyId := "GWS.CHAT.1.1v0.3"
PolicyId := ChatId1_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -102,16 +97,12 @@ test_History_Correct_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_History_Correct_V4 if {
# Test history setting when there's multiple OUs and an older event non-compliant
PolicyId := "GWS.CHAT.1.1v0.3"
PolicyId := ChatId1_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -150,16 +141,12 @@ test_History_Correct_V4 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_History_Correct_V5 if {
# Test history setting when set to inherit from parent
PolicyId := "GWS.CHAT.1.1v0.3"
PolicyId := ChatId1_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -198,16 +185,12 @@ test_History_Correct_V5 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_History_Incorrect_V1 if {
# Test history setting when there are no relevant events
PolicyId := "GWS.CHAT.1.1v0.3"
PolicyId := ChatId1_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -226,20 +209,12 @@ test_History_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}
test_History_Incorrect_V2 if {
# Test history setting when there's only one event and it's wrong
PolicyId := "GWS.CHAT.1.1v0.3"
PolicyId := ChatId1_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -258,17 +233,14 @@ test_History_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Default conversation history is set to History is OFF</li></ul>"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage1_1("OFF")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_History_Incorrect_V3 if {
# Test history setting when there are multiple events and the most recent is wrong
PolicyId := "GWS.CHAT.1.1v0.3"
PolicyId := ChatId1_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -297,17 +269,14 @@ test_History_Incorrect_V3 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Default conversation history is set to History is OFF</li></ul>"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage1_1("OFF")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_History_Incorrect_V4 if {
# Test history setting when there is no event for the Top-level OU but there is one for a different OU
PolicyId := "GWS.CHAT.1.1v0.3"
PolicyId := ChatId1_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -326,21 +295,13 @@ test_History_Incorrect_V4 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}
#--
test_History_Incorrect_V5 if {
# Test history setting when the Top-level OU is compliant but a secondary OU is non-compliant
PolicyId := "GWS.CHAT.1.1v0.3"
PolicyId := ChatId1_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -369,21 +330,18 @@ test_History_Incorrect_V5 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Secondary OU: ",
"Default conversation history is set to History is OFF</li></ul>"])
failedOU := [{"Name": "Secondary OU",
"Value": NonComplianceMessage1_1("OFF")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
#
# GWS.CHAT.1.2v0.3
# GWS.CHAT.1.2
#--
test_Change_History_Setting_Correct_V1 if {
# Test allow user to change history setting when there's only one event
PolicyId := "GWS.CHAT.1.2v0.3"
PolicyId := ChatId1_2
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -405,16 +363,12 @@ test_Change_History_Setting_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Change_History_Setting_Correct_V2 if {
# Test allow user to change history setting when there's multiple events and the most most recent is correct
PolicyId := "GWS.CHAT.1.2v0.3"
PolicyId := ChatId1_2
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -449,16 +403,12 @@ test_Change_History_Setting_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Change_History_Setting_Correct_V3 if {
# Test history setting when set to inherit from parent
PolicyId := "GWS.CHAT.1.2v0.3"
PolicyId := ChatId1_2
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -506,16 +456,12 @@ test_Change_History_Setting_Correct_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Change_History_Setting_Incorrect_V1 if {
# Test allow user to change history setting when there are no relevant events
PolicyId := "GWS.CHAT.1.2v0.3"
PolicyId := ChatId1_2
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -534,20 +480,12 @@ test_Change_History_Setting_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
test_Change_History_Setting_Incorrect_V2 if {
# Test allow user to change history setting when there's only one event and it's wrong
PolicyId := "GWS.CHAT.1.2v0.3"
PolicyId := ChatId1_2
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -569,17 +507,14 @@ test_Change_History_Setting_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Allow users to change their history setting is set to true</li></ul>"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage1_2("Yes")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Change_History_Setting_Incorrect_V3 if {
# Test allow user to change history setting when there are multiple events and the most recent is wrong
PolicyId := "GWS.CHAT.1.2v0.3"
PolicyId := ChatId1_2
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -614,18 +549,15 @@ test_Change_History_Setting_Incorrect_V3 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Allow users to change their history setting is set to true</li></ul>"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage1_2("Yes")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
test_Change_History_Setting_Incorrect_V4 if {
# Test allow user to change history setting when there are multiple OU and a secondary OU is wrong
PolicyId := "GWS.CHAT.1.2v0.3"
PolicyId := ChatId1_2
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -660,18 +592,15 @@ test_Change_History_Setting_Incorrect_V4 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Secondary OU: ",
"Allow users to change their history setting is set to true</li></ul>"])
failedOU := [{"Name": "Test Secondary OU",
"Value": NonComplianceMessage1_2("Yes")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
test_Change_History_Setting_Incorrect_V5 if {
# Test allow user to change history setting when the primary OU is missing but a different one is present
PolicyId := "GWS.CHAT.1.2v0.3"
PolicyId := ChatId1_2
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -693,14 +622,6 @@ test_Change_History_Setting_Incorrect_V5 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
#--
#--

View File

@@ -1,12 +1,16 @@
package chat
import future.keywords
import data.utils.FailTestNoEvent
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
#
# GWS.CHAT.2.1v0.3
# GWS.CHAT.2.1
#--
test_External_File_Sharing_Correct_V1 if {
# Test users are not allowed to share files externally when there's only one event
PolicyId := "GWS.CHAT.2.1v0.3"
PolicyId := ChatId2_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -28,17 +32,13 @@ test_External_File_Sharing_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_External_File_Sharing_Correct_V2 if {
# Test users are not allowed to share files externally when there's multiple events
# and the most most recent is correct
PolicyId := "GWS.CHAT.2.1v0.3"
PolicyId := ChatId2_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -73,16 +73,12 @@ test_External_File_Sharing_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_External_File_Sharing_Correct_V3 if {
# Test OU inheriting from parent
PolicyId := "GWS.CHAT.2.1v0.3"
PolicyId := ChatId2_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -130,16 +126,12 @@ test_External_File_Sharing_Correct_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_External_File_Sharing_Incorrect_V1 if {
# Test no relevant events
PolicyId := "GWS.CHAT.2.1v0.3"
PolicyId := ChatId2_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -158,20 +150,12 @@ test_External_File_Sharing_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
test_External_File_Sharing_Incorrect_V2 if {
# Test all allowed
PolicyId := "GWS.CHAT.2.1v0.3"
PolicyId := ChatId2_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -193,17 +177,14 @@ test_External_File_Sharing_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"External filesharing is set to Allow all files</li></ul>"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage2_1("Allow all files")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_External_File_Sharing_Incorrect_V3 if {
# Test images allowed
PolicyId := "GWS.CHAT.2.1v0.3"
PolicyId := ChatId2_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -225,17 +206,14 @@ test_External_File_Sharing_Incorrect_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"External filesharing is set to Images only</li></ul>"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage2_1("Images only")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_External_File_Sharing_Incorrect_V4 if {
# Test sharing allowed when there are multiple events
PolicyId := "GWS.CHAT.2.1v0.3"
PolicyId := ChatId2_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -270,17 +248,14 @@ test_External_File_Sharing_Incorrect_V4 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"External filesharing is set to Allow all files</li></ul>"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage2_1("Allow all files")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_External_File_Sharing_Incorrect_V5 if {
# Test allowing images, multiple events
PolicyId := "GWS.CHAT.2.1v0.3"
PolicyId := ChatId2_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -315,17 +290,14 @@ test_External_File_Sharing_Incorrect_V5 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"External filesharing is set to Images only</li></ul>"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage2_1("Images only")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_External_File_Sharing_Incorrect_V6 if {
# Test there's one event for a secondary OU but none for the primary OU
PolicyId := "GWS.CHAT.2.1v0.3"
PolicyId := ChatId2_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -347,20 +319,12 @@ test_External_File_Sharing_Incorrect_V6 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
test_External_File_Sharing_Incorrect_V7 if {
# Test there's multiple OUs
PolicyId := "GWS.CHAT.2.1v0.3"
PolicyId := ChatId2_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -395,11 +359,8 @@ test_External_File_Sharing_Incorrect_V7 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Some other OU: ",
"External filesharing is set to Allow all files</li></ul>"])
failedOU := [{"Name": "Some other OU",
"Value": NonComplianceMessage2_1("Allow all files")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
#--

View File

@@ -1,12 +1,16 @@
package chat
import future.keywords
import data.utils.FailTestNoEvent
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
#
# GWS.CHAT.3.1v0.3
# GWS.CHAT.3.1
#--
test_Space_History_Setting_Correct_V1 if {
# Test space history setting when there's only one event - use case #1
PolicyId := "GWS.CHAT.3.1v0.3"
PolicyId := ChatId3_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -25,16 +29,12 @@ test_Space_History_Setting_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Space_History_Setting_Correct_V2 if {
# Test space history setting when there's only one event - use case #2
PolicyId := "GWS.CHAT.3.1v0.3"
PolicyId := ChatId3_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -53,16 +53,12 @@ test_Space_History_Setting_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Space_History_Setting_Correct_V3 if {
# Test space history setting when there's multiple events and the most most recent is correct - use case #1
PolicyId := "GWS.CHAT.3.1v0.3"
PolicyId := ChatId3_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -91,16 +87,12 @@ test_Space_History_Setting_Correct_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Space_History_Setting_Correct_V4 if {
# Test space history setting when there's multiple events and the most most recent is correct - use case #2
PolicyId := "GWS.CHAT.3.1v0.3"
PolicyId := ChatId3_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -129,16 +121,12 @@ test_Space_History_Setting_Correct_V4 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Space_History_Setting_Incorrect_V1 if {
# Test space history setting when there are no relevant events
PolicyId := "GWS.CHAT.3.1v0.3"
PolicyId := ChatId3_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -157,20 +145,12 @@ test_Space_History_Setting_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}
test_Space_History_Setting_Incorrect_V2 if {
# Test space history setting when there's only one event and it's wrong - use case #1
PolicyId := "GWS.CHAT.3.1v0.3"
PolicyId := ChatId3_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -189,17 +169,14 @@ test_Space_History_Setting_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Conversation history settings for spaces is set to History is ALWAYS OFF</li></ul>"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage3_1("ALWAYS OFF")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Space_History_Setting_Incorrect_V3 if {
# Test space history setting when there's only one event and it's wrong - use case #2
PolicyId := "GWS.CHAT.3.1v0.3"
PolicyId := ChatId3_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -218,17 +195,14 @@ test_Space_History_Setting_Incorrect_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Conversation history settings for spaces is set to History is OFF by default</li></ul>"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage3_1("OFF by default")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Space_History_Setting_Incorrect_V4 if {
# Test space history setting when there are multiple events and the most recent is wrong - use case #1
PolicyId := "GWS.CHAT.3.1v0.3"
PolicyId := ChatId3_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -257,17 +231,14 @@ test_Space_History_Setting_Incorrect_V4 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Conversation history settings for spaces is set to History is OFF by default</li></ul>"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage3_1("OFF by default")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Space_History_Setting_Incorrect_V5 if {
# Test space history setting when there are multiple events and the most recent is wrong - use case #2
PolicyId := "GWS.CHAT.3.1v0.3"
PolicyId := ChatId3_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -296,17 +267,14 @@ test_Space_History_Setting_Incorrect_V5 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Conversation history settings for spaces is set to History is ALWAYS OFF</li></ul>"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage3_1("ALWAYS OFF")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Space_History_Setting_Incorrect_V6 if {
# Test there's an event for a secondary OU but not the top-level OU
PolicyId := "GWS.CHAT.3.1v0.3"
PolicyId := ChatId3_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -325,20 +293,12 @@ test_Space_History_Setting_Incorrect_V6 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}
test_Space_History_Setting_Incorrect_V7 if {
# Test multiple OUs
PolicyId := "GWS.CHAT.3.1v0.3"
PolicyId := ChatId3_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -367,14 +327,10 @@ test_Space_History_Setting_Incorrect_V7 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul>",
"<li>Some other OU: Conversation history settings for spaces is set to History is ALWAYS OFF</li>",
"<li>Test Top-Level OU: Conversation history settings for spaces is set to History is ALWAYS OFF</li>",
"</ul>"
])
failedOU := [{"Name": "Some other OU",
"Value": NonComplianceMessage3_1("ALWAYS OFF")},
{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage3_1("ALWAYS OFF")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
#--

View File

@@ -1,12 +1,16 @@
package chat
import future.keywords
import data.utils.FailTestNoEvent
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
#
# GWS.CHAT.4.1v0.3
# GWS.CHAT.4.1
#--
test_External_Chat_Sharing_Setting_Correct_V1 if {
# Test external chat sharing setting when there's only one event - use case #1
PolicyId := "GWS.CHAT.4.1v0.3"
PolicyId := ChatId4_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -35,16 +39,12 @@ test_External_Chat_Sharing_Setting_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_External_Chat_Sharing_Setting_Correct_V2 if {
# Test external chat sharing setting when there's only one event - use case #2
PolicyId := "GWS.CHAT.4.1v0.3"
PolicyId := ChatId4_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -73,16 +73,12 @@ test_External_Chat_Sharing_Setting_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_External_Chat_Sharing_Setting_Correct_V3 if {
# Test external chat sharing setting when there's multiple events and the most most recent is correct - use case #1
PolicyId := "GWS.CHAT.4.1v0.3"
PolicyId := ChatId4_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -131,16 +127,12 @@ test_External_Chat_Sharing_Setting_Correct_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_External_Chat_Sharing_Setting_Correct_V4 if {
# Test external chat sharing setting when there's multiple events and the most most recent is correct - use case #2
PolicyId := "GWS.CHAT.4.1v0.3"
PolicyId := ChatId4_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -189,16 +181,12 @@ test_External_Chat_Sharing_Setting_Correct_V4 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_External_Chat_Sharing_Setting_Incorrect_V1 if {
# Test external chat sharing setting when there are no relevant events
PolicyId := "GWS.CHAT.4.1v0.3"
PolicyId := ChatId4_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -217,20 +205,12 @@ test_External_Chat_Sharing_Setting_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
test_External_Chat_Sharing_Setting_Incorrect_V2 if {
# Test external chat sharing setting when there's only one event and it's wrong - use case #1
PolicyId := "GWS.CHAT.4.1v0.3"
PolicyId := ChatId4_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -259,17 +239,14 @@ test_External_Chat_Sharing_Setting_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"External chat is enabled for all domains</li></ul>"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": "External chat is enabled for all domains"}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_External_Chat_Sharing_Setting_Incorrect_V3 if {
# Test external chat sharing setting when there are multiple events and the most recent is wrong - use case #1
PolicyId := "GWS.CHAT.4.1v0.3"
PolicyId := ChatId4_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -318,17 +295,14 @@ test_External_Chat_Sharing_Setting_Incorrect_V3 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"External chat is enabled for all domains</li></ul>"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": "External chat is enabled for all domains"}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_External_Chat_Sharing_Setting_Incorrect_V4 if {
# Test there's an event for a secondary OU but not the top-level OU
PolicyId := "GWS.CHAT.4.1v0.3"
PolicyId := ChatId4_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -357,20 +331,12 @@ test_External_Chat_Sharing_Setting_Incorrect_V4 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
test_External_Chat_Sharing_Setting_Incorrect_V5 if {
# Test multiple OUs
PolicyId := "GWS.CHAT.4.1v0.3"
PolicyId := ChatId4_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -420,14 +386,10 @@ test_External_Chat_Sharing_Setting_Incorrect_V5 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", ["The following OUs are non-compliant:<ul>",
"<li>Some other OU: External chat is enabled for all domains</li>",
"<li>Test Top-Level OU: External chat is enabled for all domains</li>",
"</ul>"
])
failedOU := [{"Name": "Some other OU",
"Value": "External chat is enabled for all domains"},
{"Name": "Test Top-Level OU",
"Value": "External chat is enabled for all domains"}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
#--

View File

@@ -2,11 +2,11 @@ package chat
import future.keywords
#
# GWS.CHAT.5.1v0.3
# GWS.CHAT.5.1
#--
test_Enable_Correct_V1 if {
# Test correct 1 OU
PolicyId := "GWS.CHAT.5.1v0.3"
PolicyId := ChatId5_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -64,7 +64,7 @@ test_Enable_Correct_V1 if {
test_Enable_Correct_V2 if {
# Test correct 2 OUs, child OU overrides top-level settings
PolicyId := "GWS.CHAT.5.1v0.3"
PolicyId := ChatId5_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -162,7 +162,7 @@ test_Enable_Correct_V2 if {
test_Enable_Correct_V3 if {
# Test correct 2 OUs, child OU inherits
PolicyId := "GWS.CHAT.5.1v0.3"
PolicyId := ChatId5_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -260,7 +260,7 @@ test_Enable_Correct_V3 if {
test_Enable_Incorrect_V1 if {
# Test incorrect 1 OU, one conversation type is disabled
PolicyId := "GWS.CHAT.5.1v0.3"
PolicyId := ChatId5_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -323,7 +323,7 @@ test_Enable_Incorrect_V1 if {
test_Enable_Incorrect_V2 if {
# Test incorrect 1 OU, spaces restricted
PolicyId := "GWS.CHAT.5.1v0.3"
PolicyId := ChatId5_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -386,7 +386,7 @@ test_Enable_Incorrect_V2 if {
test_Enable_Incorrect_V3 if {
# Test correct 2 OUs, child OU overrides top-level settings
PolicyId := "GWS.CHAT.5.1v0.3"
PolicyId := ChatId5_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -489,7 +489,7 @@ test_Enable_Incorrect_V3 if {
test_Enable_Incorrect_V4 if {
# Test incorrect 1 OU, one setting is missing
PolicyId := "GWS.CHAT.5.1v0.3"
PolicyId := ChatId5_1
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -541,11 +541,11 @@ test_Enable_Incorrect_V4 if {
#--
#
# GWS.CHAT.5.2v0.3
# GWS.CHAT.5.2
#--
test_Categories_Correct_V1 if {
# Test correct 1 OU
PolicyId := "GWS.CHAT.5.2v0.3"
PolicyId := ChatId5_2
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -581,7 +581,7 @@ test_Categories_Correct_V1 if {
test_Categories_Correct_V2 if {
# Test correct, 2 OUs, child OU overrides
PolicyId := "GWS.CHAT.5.2v0.3"
PolicyId := ChatId5_2
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -635,7 +635,7 @@ test_Categories_Correct_V2 if {
test_Categories_Correct_V3 if {
# Test correct, 2 OUs, child OU inherits
PolicyId := "GWS.CHAT.5.2v0.3"
PolicyId := ChatId5_2
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -681,7 +681,7 @@ test_Categories_Correct_V3 if {
test_Categories_Incorrect_V1 if {
# Test incorrect 1 OU
PolicyId := "GWS.CHAT.5.2v0.3"
PolicyId := ChatId5_2
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -720,7 +720,7 @@ test_Categories_Incorrect_V1 if {
test_Categories_Incorrect_V2 if {
# Test incorrect 2 OUs
PolicyId := "GWS.CHAT.5.2v0.3"
PolicyId := ChatId5_2
Output := tests with input as {
"chat_logs": {"items": [
{
@@ -777,7 +777,7 @@ test_Categories_Incorrect_V2 if {
test_Categories_Incorrect_V3 if {
# Test incorrect no events
PolicyId := "GWS.CHAT.5.2v0.3"
PolicyId := ChatId5_2
Output := tests with input as {
"chat_logs": {"items": [
@@ -796,4 +796,4 @@ test_Categories_Incorrect_V3 if {
"While we are unable to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])
}
}

View File

@@ -0,0 +1,73 @@
package chat
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
GoodChatApi01 := {
"policies": {
"topOU": {
"chat_chat_history": {"allowUserModification": false,
"historyOnByDefault": true},
"chat_service_status": {"serviceState": "ENABLED"}
},
"nextOU": {
"chat_chat_history": {"allowUserModification": true,
"historyOnByDefault": false},
"chat_service_status": {"serviceState": "DISABLED"}
},
"thirdOU": {
"security_session_controls": {
"webSessionDuration": "700m"
}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
BadChatApi01 := {
"policies": {
"topOU": {
"chat_chat_history": {"allowUserModification": true,
"historyOnByDefault": false},
"chat_service_status": {"serviceState": "ENABLED"}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
test_ChatAPI_History_Correct_1 if {
PolicyId := ChatId1_1
Output := tests with input as GoodChatApi01
PassTestResult(PolicyId, Output)
}
test_ChatAPI_History_Incorrect_1 if {
PolicyId := ChatId1_1
Output := tests with input as BadChatApi01
failedOU := [{"Name": "topOU",
"Value": NonComplianceMessage1_1("OFF")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_ChatAPI_Change_History_Correct_1 if {
PolicyId := ChatId1_2
Output := tests with input as GoodChatApi01
PassTestResult(PolicyId, Output)
}
test_ChatAPI_Change_History_Incorrect_1 if {
PolicyId := ChatId1_2
Output := tests with input as BadChatApi01
failedOU := [{"Name": "topOU",
"Value": NonComplianceMessage1_2("Yes")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}

View File

@@ -0,0 +1,57 @@
package chat
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
GoodChatApi02 := {
"policies": {
"topOU": {
"chat_chat_file_sharing": {"externalFileSharing": "NO_FILES",
"internalFileSharing": "ALL_FILES"},
"chat_service_status": {"serviceState": "ENABLED"}
},
"nextOU": {
"chat_chat_file_sharing": {"externalFileSharing": "IMAGES_ONLY",
"internalFileSharing": "ALL_FILES"},
"chat_service_status": {"serviceState": "DISABLED"}
},
"thirdOU": {
"security_session_controls": {
"webSessionDuration": "700m"
}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
BadChatApi02 := {
"policies": {
"topOU": {
"chat_chat_file_sharing": {"externalFileSharing": "IMAGES_ONLY",
"internalFileSharing": "FILE_SHARING_OPTION_UNSPECIFIED"},
"chat_service_status": {"serviceState": "ENABLED"}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
test_ChatAPI_External_Sharing_Correct_1 if {
PolicyId := ChatId2_1
Output := tests with input as GoodChatApi02
PassTestResult(PolicyId, Output)
}
test_ChatAPI_External_Sharing_Incorrect_1 if {
PolicyId := ChatId2_1
Output := tests with input as BadChatApi02
failedOU := [{"Name": "topOU",
"Value": NonComplianceMessage2_1("Images only")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}

View File

@@ -0,0 +1,82 @@
package chat
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
GoodChatApi03 := {
"policies": {
"topOU": {
"chat_space_history": {"historyState": "DEFAULT_HISTORY_ON"},
"chat_service_status": {"serviceState": "ENABLED"}
},
"nextOU": {
"chat_space_history": {"historyState": "HISTORY_ALWAYS_ON"}
},
"thirdOU": {
"security_session_controls": {
"webSessionDuration": "700m"
}
},
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
BadChatApi03 := {
"policies": {
"topOU": {
"chat_space_history": {"historyState": "DEFAULT_HISTORY_OFF"},
"chat_service_status": {"serviceState": "ENABLED"}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
BadChatApi03a := {
"policies": {
"topOU": {
"chat_space_history": {"historyState": "HISTORY_ALWAYS_ON"},
"chat_service_status": {"serviceState": "ENABLED"}
},
"secondOU": {
"chat_space_history": {"historyState": "HISTORY_ALWAYS_OFF"}
},
"thirdOU": {
"chat_space_history": {"historyState": "HISTORY_STATE_UNSPECIFIED"}
},
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
test_ChatAPI_Space_History_Correct_1 if {
PolicyId := ChatId3_1
Output := tests with input as GoodChatApi03
PassTestResult(PolicyId, Output)
}
test_ChatAPI_Space_History_Incorrect_1 if {
PolicyId := ChatId3_1
Output := tests with input as BadChatApi03
failedOU := [{"Name": "topOU",
"Value": NonComplianceMessage3_1("OFF by default")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_ChatAPI_Space_History_Incorrect_2 if {
PolicyId := ChatId3_1
Output := tests with input as BadChatApi03a
failedOU := [{"Name": "secondOU",
"Value": NonComplianceMessage3_1("ALWAYS OFF")},
{"Name": "thirdOU",
"Value": NonComplianceMessage3_1("Unspecified")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}

View File

@@ -0,0 +1,91 @@
package chat
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
GoodChatApi04 := {
"policies": {
"topOU": {
"chat_external_chat_restriction": {
"allowExternalChat": false,
"externalChatRestriction": "TRUSTED_DOMAINS"},
"chat_service_status": {"serviceState": "ENABLED"}
},
"nextOU": {
"chat_external_chat_restriction": {
"allowExternalChat": true,
"externalChatRestriction": "TRUSTED_DOMAINS"}
},
"thirdOU": {
"chat_external_chat_restriction": {
"allowExternalChat": true,
"externalChatRestriction": "NO_RESTRICTION"},
"chat_service_status": {"serviceState": "DISABLED"}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
BadChatApi04 := {
"policies": {
"topOU": {
"chat_external_chat_restriction": {
"allowExternalChat": true,
"externalChatRestriction": "NO_RESTRICTION"},
"chat_service_status": {"serviceState": "ENABLED"}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
BadChatApi04a := {
"policies": {
"topOU": {
"chat_external_chat_restriction": {
"allowExternalChat": true,
"externalChatRestriction": "TRUSTED_DOMAINS"},
"chat_service_status": {"serviceState": "ENABLED"}
},
"secondOU": {
"chat_external_chat_restriction": {
"allowExternalChat": true,
"externalChatRestriction": "RESTRICTION_UNSPECIFIED"},
},
"thirdOU": {
"chat_space_history": {"historyState": "HISTORY_STATE_UNSPECIFIED"}
},
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
test_ChatAPI_External_Messages_Correct_1 if {
PolicyId := ChatId4_1
Output := tests with input as GoodChatApi04
PassTestResult(PolicyId, Output)
}
test_ChatAPI_External_Messages_Incorrect_1 if {
PolicyId := ChatId4_1
Output := tests with input as BadChatApi04
failedOU := [{"Name": "topOU",
"Value": NonComplianceMessage4_1("all domains")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_ChatAPI_External_Messages_Incorrect_2 if {
PolicyId := ChatId4_1
Output := tests with input as BadChatApi04a
failedOU := [{"Name": "secondOU",
"Value": NonComplianceMessage4_1("Unspecified")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}

View File

@@ -1,13 +1,16 @@
package classroom
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.FailTestNoEvent
import data.utils.PassTestResult
#
# GWS.CLASSROOM.1.1v0.3
# GWS.CLASSROOM.1.1
#--
test_JoinClassroom_Correct_V1 if {
# Test enforcing who can join classroom when there's only one event
PolicyId := "GWS.CLASSROOM.1.1v0.3"
PolicyId := ClassroomId1_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -27,17 +30,13 @@ test_JoinClassroom_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_JoinClassroom_Correct_V2 if {
# Test enforcing MFA when there's multiple events, with the chronological latest
# correct but not last in json list
PolicyId := "GWS.CLASSROOM.1.1v0.3"
PolicyId := ClassroomId1_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -68,16 +67,12 @@ test_JoinClassroom_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_JoinClassroom_Incorrect_V1 if {
# Test enforcing who can join classroom when there's only one event and it's wrong
PolicyId := "GWS.CLASSROOM.1.1v0.3"
PolicyId := ClassroomId1_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -97,20 +92,15 @@ test_JoinClassroom_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Who can join classes in your domain is set to Users in allowlisted domains</li></ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage1_1("Users in allowlisted domains")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_JoinClassroom_Incorrect_V2 if {
# Test who can join classroom when there's multiple events, with the chronological latest
# incorrect but not last in json list
PolicyId := "GWS.CLASSROOM.1.1v0.3"
PolicyId := ClassroomId1_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -141,20 +131,15 @@ test_JoinClassroom_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Who can join classes in your domain is set to Users in allowlisted domains</li></ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage1_1("Users in allowlisted domains")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_JoinClassroom_Incorrect_V3 if {
# Test enforcing who can join classroom when there no applicable event
PolicyId := "GWS.CLASSROOM.1.1v0.3"
PolicyId := ClassroomId1_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -173,26 +158,17 @@ test_JoinClassroom_Incorrect_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}
#--
#
# GWS.CLASSROOM.1.2v0.3
# GWS.CLASSROOM.1.2
#--
test_WhichClasses_Correct_V1 if {
# Test enforcing which classes users can join when there's only one event
PolicyId := "GWS.CLASSROOM.1.2v0.3"
PolicyId := ClassroomId1_2
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -212,17 +188,13 @@ test_WhichClasses_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_WhichClasses_Correct_V2 if {
# Test enforcing which classes users can join when there's multiple events, with the chronological latest
# correct but not last in json list
PolicyId := "GWS.CLASSROOM.1.2v0.3"
PolicyId := ClassroomId1_2
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -253,16 +225,12 @@ test_WhichClasses_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_WhichClasses_Incorrect_V1 if {
# Test enforcing which classes users can join when there's only one event and it's wrong
PolicyId := "GWS.CLASSROOM.1.2v0.3"
PolicyId := ClassroomId1_2
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -282,20 +250,15 @@ test_WhichClasses_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Which classes can users in your domain join is set to Classes in allowlisted domains</li></ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage1_2("Classes in allowlisted domains")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_WhichClasses_Incorrect_V2 if {
# Test enforcing which classes users can join when there's multiple events, with the chronological latest
# incorrect but not last in json list
PolicyId := "GWS.CLASSROOM.1.2v0.3"
PolicyId := ClassroomId1_2
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -325,20 +288,14 @@ test_WhichClasses_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Which classes can users in your domain join is set to Classes in allowlisted domains</li></ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage1_2("Classes in allowlisted domains")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_WhichClasses_Incorrect_V3 if {
# Test enforcing which classes users can join when there no applicable event
PolicyId := "GWS.CLASSROOM.1.2v0.3"
PolicyId := ClassroomId1_2
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -357,13 +314,5 @@ test_WhichClasses_Incorrect_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is compliant; manual check recommended."
])
}
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}

View File

@@ -1,13 +1,15 @@
package classroom
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.FailTestNoEvent
import data.utils.PassTestResult
# GWS.CLASSROOM.2.1v0.3
# GWS.CLASSROOM.2.1
#--
test_APIAccess_Correct_V1 if {
# Test API Access is disabled when there's only one event
PolicyId := "GWS.CLASSROOM.2.1v0.3"
PolicyId := ClassroomId2_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -27,17 +29,13 @@ test_APIAccess_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_APIAccess_Correct_V2 if {
# Test enforcing API Access is disabled when there's multiple events, with the chronological latest
# correct but not last in json list
PolicyId := "GWS.CLASSROOM.2.1v0.3"
PolicyId := ClassroomId2_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -68,16 +66,12 @@ test_APIAccess_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_APIAccess_Correct_V3 if {
# Test enforcing API Access is disabled is correct when there are events in multiple OUs
PolicyId := "GWS.CLASSROOM.2.1v0.3"
PolicyId := ClassroomId2_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -106,16 +100,12 @@ test_APIAccess_Correct_V3 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_APIAccess_Correct_V4 if {
# Test API Access is disabled when set to inherit from parent
PolicyId := "GWS.CLASSROOM.2.1v0.3"
PolicyId := ClassroomId2_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -154,16 +144,12 @@ test_APIAccess_Correct_V4 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_APIAccess_Incorrect_V1 if {
# Test API Access is disabled when there's only one event and it's wrong
PolicyId := "GWS.CLASSROOM.2.1v0.3"
PolicyId := ClassroomId2_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -183,20 +169,15 @@ test_APIAccess_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Data access is set to ON</li></ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage2_1(GetFriendlyValue2_1("true"))}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_APIAccess_Incorrect_V2 if {
# Test API Access is disabled when there's multiple events, with the chronological latest
# incorrect but not last in json list
PolicyId := "GWS.CLASSROOM.2.1v0.3"
PolicyId := ClassroomId2_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -227,20 +208,14 @@ test_APIAccess_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Data access is set to ON</li></ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage2_1(GetFriendlyValue2_1("true"))}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_APIAccess_Incorrect_V3 if {
# Test API Access is disabled when there no applicable event
PolicyId := "GWS.CLASSROOM.2.1v0.3"
PolicyId := ClassroomId2_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -260,19 +235,12 @@ test_APIAccess_Incorrect_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
test_APIAccess_Incorrect_V4 if {
# Test allow API Access is disabled when there are multiple OU and a secondary OU is wrong
PolicyId := "GWS.CLASSROOM.2.1v0.3"
PolicyId := ClassroomId2_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -301,20 +269,15 @@ test_APIAccess_Incorrect_V4 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Secondary OU: ",
"Data access is set to ON</li></ul>"
])
failedOU := [{"Name": "Test Secondary OU",
"Value": NonComplianceMessage2_1(GetFriendlyValue2_1("true"))}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
test_APIAccess_Incorrect_V5 if {
# Test API Access is disabled when the primary OU is missing but a different one is present
PolicyId := "GWS.CLASSROOM.2.1v0.3"
PolicyId := ClassroomId2_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -333,20 +296,12 @@ test_APIAccess_Incorrect_V5 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
test_APIAccess_Incorrect_V6 if {
# Test API Access is disabled access when there's only one event and it's wrong
PolicyId := "GWS.CLASSROOM.2.1v0.3"
PolicyId := ClassroomId2_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -365,19 +320,14 @@ test_APIAccess_Incorrect_V6 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Data access is set to SAME_DOMAIN</li></ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage2_1("SAME_DOMAIN")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_APIAccess_Incorrect_V7 if {
# Test API Access is disabled when there are multiple events and the most recent is wrong
PolicyId := "GWS.CLASSROOM.2.1v0.3"
PolicyId := ClassroomId2_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -406,19 +356,14 @@ test_APIAccess_Incorrect_V7 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Data access is set to SAME_DOMAIN</li></ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage2_1("SAME_DOMAIN")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_APIAccess_Incorrect_V8 if {
# Test API Access is disabled when there are multiple OU and a secondary OU is wrong
PolicyId := "GWS.CLASSROOM.2.1v0.3"
PolicyId := ClassroomId2_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -447,20 +392,15 @@ test_APIAccess_Incorrect_V8 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Secondary OU: ",
"Data access is set to SAME_DOMAIN</li></ul>"
])
failedOU := [{"Name": "Test Secondary OU",
"Value": NonComplianceMessage2_1("SAME_DOMAIN")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
test_APIAccess_Incorrect_V9 if {
# Test API Access is disabled when the primary OU is missing but a different one is present
PolicyId := "GWS.CLASSROOM.2.1v0.3"
PolicyId := ClassroomId2_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -479,14 +419,6 @@ test_APIAccess_Incorrect_V9 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
#--

View File

@@ -1,13 +1,15 @@
package classroom
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.FailTestNoEvent
import data.utils.PassTestResult
# GWS.CLASSROOM.3.1v0.3
# GWS.CLASSROOM.3.1
#--
test_CleverRosterDisabled_Correct_V1 if {
# Test Clever Roster is disabled when there's only one event
PolicyId := "GWS.CLASSROOM.3.1v0.3"
PolicyId := ClassroomId3_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -27,17 +29,13 @@ test_CleverRosterDisabled_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_CleverRosterDisabled_Correct_V2 if {
# Test enforcing Clever Roster is disabled when there's multiple events, with the chronological latest
# correct but not last in json list
PolicyId := "GWS.CLASSROOM.3.1v0.3"
PolicyId := ClassroomId3_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -68,16 +66,12 @@ test_CleverRosterDisabled_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_CleverRosterDisabled_Correct_V3 if {
# Test enforcing Clever Roster is disabled is correct when there are events in multiple OUs
PolicyId := "GWS.CLASSROOM.3.1v0.3"
PolicyId := ClassroomId3_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -106,16 +100,12 @@ test_CleverRosterDisabled_Correct_V3 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_CleverRosterDisabled_Correct_V4 if {
# Test Clever Roster is disabled when set to inherit from parent
PolicyId := "GWS.CLASSROOM.3.1v0.3"
PolicyId := ClassroomId3_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -154,16 +144,12 @@ test_CleverRosterDisabled_Correct_V4 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_CleverRosterDisabled_Incorrect_V1 if {
# Test Clever Roster is disabled when there's only one event and it's wrong
PolicyId := "GWS.CLASSROOM.3.1v0.3"
PolicyId := ClassroomId3_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -183,20 +169,15 @@ test_CleverRosterDisabled_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Roster import is set to ON - CLEVER</li></ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage3_1("ON - CLEVER")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_CleverRosterDisabled_Incorrect_V2 if {
# Test Clever Roster is disabled when there's multiple events, with the chronological latest
# incorrect but not last in json list
PolicyId := "GWS.CLASSROOM.3.1v0.3"
PolicyId := ClassroomId3_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -227,20 +208,15 @@ test_CleverRosterDisabled_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Roster import is set to ON - CLEVER</li></ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage3_1("ON - CLEVER")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_CleverRosterDisabled_Incorrect_V3 if {
# Test Clever Roster is disabled when there no applicable event
PolicyId := "GWS.CLASSROOM.3.1v0.3"
PolicyId := ClassroomId3_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -260,19 +236,12 @@ test_CleverRosterDisabled_Incorrect_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}
test_CleverRosterDisabled_Incorrect_V4 if {
# Test allow Clever Roster is disabled when there are multiple OU and a secondary OU is wrong
PolicyId := "GWS.CLASSROOM.3.1v0.3"
PolicyId := ClassroomId3_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -301,20 +270,15 @@ test_CleverRosterDisabled_Incorrect_V4 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Secondary OU: ",
"Roster import is set to ON - CLEVER</li></ul>"
])
failedOU := [{"Name": "Test Secondary OU",
"Value": NonComplianceMessage3_1("ON - CLEVER")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
test_CleverRosterDisabled_Incorrect_V5 if {
# Test Clever Roster is disabled when the primary OU is missing but a different one is present
PolicyId := "GWS.CLASSROOM.3.1v0.3"
PolicyId := ClassroomId3_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -333,20 +297,12 @@ test_CleverRosterDisabled_Incorrect_V5 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}
test_CleverRosterDisabled_Incorrect_V6 if {
# Test Clever Roster is disabled access when there's only one event and it's wrong
PolicyId := "GWS.CLASSROOM.3.1v0.3"
PolicyId := ClassroomId3_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -365,19 +321,14 @@ test_CleverRosterDisabled_Incorrect_V6 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Roster import is set to SAME_DOMAIN</li></ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage3_1("SAME_DOMAIN")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_CleverRosterDisabled_Incorrect_V7 if {
# Test Clever Roster is disabled when there are multiple events and the most recent is wrong
PolicyId := "GWS.CLASSROOM.3.1v0.3"
PolicyId := ClassroomId3_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -406,19 +357,14 @@ test_CleverRosterDisabled_Incorrect_V7 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Roster import is set to SAME_DOMAIN</li></ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage3_1("SAME_DOMAIN")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_CleverRosterDisabled_Incorrect_V8 if {
# Test Clever Roster is disabled when there are multiple OU and a secondary OU is wrong
PolicyId := "GWS.CLASSROOM.3.1v0.3"
PolicyId := ClassroomId3_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -447,20 +393,15 @@ test_CleverRosterDisabled_Incorrect_V8 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Secondary OU: ",
"Roster import is set to SAME_DOMAIN</li></ul>"
])
failedOU := [{"Name": "Test Secondary OU",
"Value": NonComplianceMessage3_1("SAME_DOMAIN")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
test_CleverRosterDisabled_Incorrect_V9 if {
# Test Clever Roster is disabled when the primary OU is missing but a different one is present
PolicyId := "GWS.CLASSROOM.3.1v0.3"
PolicyId := ClassroomId3_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -479,14 +420,6 @@ test_CleverRosterDisabled_Incorrect_V9 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}
#--

View File

@@ -1,13 +1,16 @@
package classroom
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.FailTestNoEvent
import data.utils.PassTestResult
#
# GWS.CLASSROOM.4.1v0.3
# GWS.CLASSROOM.4.1
#--
test_UnenrollStudents_Correct_V1 if {
# Test only teachers can unenroll students when there's only one event
PolicyId := "GWS.CLASSROOM.4.1v0.3"
PolicyId := ClassroomId4_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -27,17 +30,13 @@ test_UnenrollStudents_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_UnenrollStudents_Correct_V2 if {
# Test enforcing only teachers can unenroll students when there's multiple events, with the chronological latest
# correct but not last in json list
PolicyId := "GWS.CLASSROOM.4.1v0.3"
PolicyId := ClassroomId4_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -68,16 +67,12 @@ test_UnenrollStudents_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_UnenrollStudents_Correct_V3 if {
# Test enforcing only teachers can unenroll students is correct when there are events in multiple OUs
PolicyId := "GWS.CLASSROOM.4.1v0.3"
PolicyId := ClassroomId4_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -106,16 +101,12 @@ test_UnenrollStudents_Correct_V3 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_UnenrollStudents_Correct_V4 if {
# Test only teachers can unenroll students when set to inherit from parent
PolicyId := "GWS.CLASSROOM.4.1v0.3"
PolicyId := ClassroomId4_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -154,16 +145,12 @@ test_UnenrollStudents_Correct_V4 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_UnenrollStudents_Incorrect_V1 if {
# Test only teachers can unenroll students when there's only one event and it's wrong
PolicyId := "GWS.CLASSROOM.4.1v0.3"
PolicyId := ClassroomId4_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -183,20 +170,15 @@ test_UnenrollStudents_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Who can unenroll students from classes is set to Students and teachers</li></ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage4_1("Students and teachers")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_UnenrollStudents_Incorrect_V2 if {
# Test only teachers can unenroll students when there's multiple events, with the chronological latest
# incorrect but not last in json list
PolicyId := "GWS.CLASSROOM.4.1v0.3"
PolicyId := ClassroomId4_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -227,20 +209,15 @@ test_UnenrollStudents_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Who can unenroll students from classes is set to Students and teachers</li></ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage4_1("Students and teachers")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_UnenrollStudents_Incorrect_V3 if {
# Test only teachers can unenroll students when there no applicable event
PolicyId := "GWS.CLASSROOM.4.1v0.3"
PolicyId := ClassroomId4_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -260,19 +237,12 @@ test_UnenrollStudents_Incorrect_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
test_UnenrollStudents_Incorrect_V4 if {
# Test allow only teachers can unenroll students when there are multiple OU and a secondary OU is wrong
PolicyId := "GWS.CLASSROOM.4.1v0.3"
PolicyId := ClassroomId4_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -301,20 +271,15 @@ test_UnenrollStudents_Incorrect_V4 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Secondary OU: ",
"Who can unenroll students from classes is set to Students and teachers</li></ul>"
])
failedOU := [{"Name": "Test Secondary OU",
"Value": NonComplianceMessage4_1("Students and teachers")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
test_UnenrollStudents_Incorrect_V5 if {
# Test only teachers can unenroll students when the primary OU is missing but a different one is present
PolicyId := "GWS.CLASSROOM.4.1v0.3"
PolicyId := ClassroomId4_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -333,20 +298,12 @@ test_UnenrollStudents_Incorrect_V5 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
test_UnenrollStudents_Incorrect_V6 if {
# Test only teachers can unenroll students access when there's only one event and it's wrong
PolicyId := "GWS.CLASSROOM.4.1v0.3"
PolicyId := ClassroomId4_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -365,19 +322,14 @@ test_UnenrollStudents_Incorrect_V6 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Who can unenroll students from classes is set to SAME_DOMAIN</li></ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage4_1("SAME_DOMAIN")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_UnenrollStudents_Incorrect_V7 if {
# Test only teachers can unenroll students when there are multiple events and the most recent is wrong
PolicyId := "GWS.CLASSROOM.4.1v0.3"
PolicyId := ClassroomId4_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -406,19 +358,14 @@ test_UnenrollStudents_Incorrect_V7 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Who can unenroll students from classes is set to SAME_DOMAIN</li></ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage4_1("SAME_DOMAIN")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_UnenrollStudents_Incorrect_V8 if {
# Test only teachers can unenroll students when there are multiple OU and a secondary OU is wrong
PolicyId := "GWS.CLASSROOM.4.1v0.3"
PolicyId := ClassroomId4_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -447,20 +394,15 @@ test_UnenrollStudents_Incorrect_V8 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Secondary OU: ",
"Who can unenroll students from classes is set to SAME_DOMAIN</li></ul>"
])
failedOU := [{"Name": "Test Secondary OU",
"Value": NonComplianceMessage4_1("SAME_DOMAIN")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
test_UnenrollStudents_Incorrect_V9 if {
# Test only teachers can unenroll students when the primary OU is missing but a different one is present
PolicyId := "GWS.CLASSROOM.4.1v0.3"
PolicyId := ClassroomId4_1
Output := tests with input as {
"classroom_logs": {"items": [
{
@@ -479,14 +421,6 @@ test_UnenrollStudents_Incorrect_V9 if {
},
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
#--

View File

@@ -1,188 +1,164 @@
package classroom
import future.keywords
#
# GWS.CLASSROOM.5.1v0.3
#--
test_ClassroomCreation_Correct_V1 if {
# Test only teachers can unenroll students when there's only one event
PolicyId := "GWS.CLASSROOM.5.1v0.3"
Output := tests with input as {
"classroom_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"parameters": [
{"name":"SETTING_NAME",
"value": "TeacherPermissionsSettingProto who_can_create_class"},
{"name": "NEW_VALUE", "value": "3"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
}
test_ClassroomCreation_Correct_V2 if {
# Test when there's multiple events, with the chronological latest
# correct but not last in json list
PolicyId := "GWS.CLASSROOM.5.1v0.3"
Output := tests with input as {
"classroom_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"parameters": [
{"name":"SETTING_NAME",
"value": "TeacherPermissionsSettingProto who_can_create_class"},
{"name": "NEW_VALUE", "value": "3"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
},
{
"id": {"time": "2021-12-20T00:02:28.672Z"},
"events": [{
"parameters": [
{"name":"SETTING_NAME",
"value": "TeacherPermissionsSettingProto who_can_create_class"},
{"name": "NEW_VALUE", "value": "2"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
}
# No tests for multiple OUs, inheritance, groups, etc as this setting can't be controlled at the OU or group level
test_ClassroomCreation_Incorrect_V1 if {
# Test when there's only one event and it's wrong
PolicyId := "GWS.CLASSROOM.5.1v0.3"
Output := tests with input as {
"classroom_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"parameters": [
{"name":"SETTING_NAME",
"value": "TeacherPermissionsSettingProto who_can_create_class"},
{"name": "NEW_VALUE", "value": "1"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Who can create classes is set to anyone in this domain</li></ul>"
])
}
test_ClassroomCreation_Incorrect_V2 if {
# Test when there's multiple events, with the chronological latest
# incorrect but not last in json list
PolicyId := "GWS.CLASSROOM.5.1v0.3"
Output := tests with input as {
"classroom_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"parameters": [
{"name":"SETTING_NAME",
"value": "TeacherPermissionsSettingProto who_can_create_class"},
{"name": "NEW_VALUE", "value": "2"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
},
{
"id": {"time": "2021-12-20T00:02:28.672Z"},
"events": [{
"parameters": [
{"name":"SETTING_NAME",
"value": "TeacherPermissionsSettingProto who_can_create_class"},
{"name": "NEW_VALUE", "value": "3"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul><li>Test Top-Level OU: ",
"Who can create classes is set to all pending and verified teachers</li></ul>"
])
}
test_ClassroomCreation_Incorrect_V3 if {
# Test when there no applicable event
PolicyId := "GWS.CLASSROOM.5.1v0.3"
Output := tests with input as {
"classroom_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"parameters": [
{"name":"SETTING_NAME",
"value": "something else"},
{"name": "NEW_VALUE", "value": "false"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. ",
"While we are unable to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])
}
package classroom
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.FailTestNoEvent
import data.utils.PassTestResult
#
# GWS.CLASSROOM.5.1
#--
test_ClassroomCreation_Correct_V1 if {
# Test only teachers can unenroll students when there's only one event
PolicyId := ClassroomId5_1
Output := tests with input as {
"classroom_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"parameters": [
{"name":"SETTING_NAME",
"value": "TeacherPermissionsSettingProto who_can_create_class"},
{"name": "NEW_VALUE", "value": "3"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
PassTestResult(PolicyId, Output)
}
test_ClassroomCreation_Correct_V2 if {
# Test when there's multiple events, with the chronological latest
# correct but not last in json list
PolicyId := ClassroomId5_1
Output := tests with input as {
"classroom_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"parameters": [
{"name":"SETTING_NAME",
"value": "TeacherPermissionsSettingProto who_can_create_class"},
{"name": "NEW_VALUE", "value": "3"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
},
{
"id": {"time": "2021-12-20T00:02:28.672Z"},
"events": [{
"parameters": [
{"name":"SETTING_NAME",
"value": "TeacherPermissionsSettingProto who_can_create_class"},
{"name": "NEW_VALUE", "value": "2"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
PassTestResult(PolicyId, Output)
}
# No tests for multiple OUs, inheritance, groups, etc as this setting can't be controlled at the OU or group level
test_ClassroomCreation_Incorrect_V1 if {
# Test when there's only one event and it's wrong
PolicyId := ClassroomId5_1
Output := tests with input as {
"classroom_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"parameters": [
{"name":"SETTING_NAME",
"value": "TeacherPermissionsSettingProto who_can_create_class"},
{"name": "NEW_VALUE", "value": "1"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage5_1("anyone in this domain")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_ClassroomCreation_Incorrect_V2 if {
# Test when there's multiple events, with the chronological latest
# incorrect but not last in json list
PolicyId := ClassroomId5_1
Output := tests with input as {
"classroom_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"parameters": [
{"name":"SETTING_NAME",
"value": "TeacherPermissionsSettingProto who_can_create_class"},
{"name": "NEW_VALUE", "value": "2"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
},
{
"id": {"time": "2021-12-20T00:02:28.672Z"},
"events": [{
"parameters": [
{"name":"SETTING_NAME",
"value": "TeacherPermissionsSettingProto who_can_create_class"},
{"name": "NEW_VALUE", "value": "3"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage5_1("all pending and verified teachers")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_ClassroomCreation_Incorrect_V3 if {
# Test when there no applicable event
PolicyId := ClassroomId5_1
Output := tests with input as {
"classroom_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"parameters": [
{"name":"SETTING_NAME",
"value": "something else"},
{"name": "NEW_VALUE", "value": "false"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}

View File

@@ -0,0 +1,90 @@
package classroom
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
GoodClassroomApi01 := {
"policies": {
"topOU": {
"classroom_class_membership": {
"whoCanJoinClasses": "ANYONE_IN_DOMAIN",
"whichClassesCanUsersJoin": "CLASSES_IN_DOMAIN"
},
"classroom_service_status": {"serviceState": "ENABLED"}
},
"nextOU": {
},
"thirdOU": {
"security_session_controls": {
"webSessionDuration": "700m"
}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
BadClassroomApi01 := {
"policies": {
"topOU": {
"classroom_class_membership": {
"whoCanJoinClasses": "ANYONE_IN_DOMAIN",
"whichClassesCanUsersJoin": "CLASSES_IN_ALLOWLISTED_DOMAINS"
},
"classroom_service_status": {"serviceState": "ENABLED"}
},
"nextOU": {
},
"thirdOU": {
"classroom_class_membership": {
"whoCanJoinClasses": "ANY_GOOGLE_WORKSPACE_USER",
"whichClassesCanUsersJoin": "CLASSES_IN_ALLOWLISTED_DOMAINS"
},
},
"fourthOU": {
"security_session_controls": {
"webSessionDuration": "12H"
},
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
test_ClassroomAPI_JoinClassroom_Correct_1 if {
PolicyId := ClassroomId1_1
Output := tests with input as GoodClassroomApi01
PassTestResult(PolicyId, Output)
}
test_ClassroomAPI_JoinClassroom_Incorrect_1 if {
PolicyId := ClassroomId1_1
Output := tests with input as BadClassroomApi01
failedOU := [{"Name": "thirdOU",
"Value": NonComplianceMessage1_1("Any Google Workspace user")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_ClassroomAPI_JoinClasses_Correct_1 if {
PolicyId := ClassroomId1_2
Output := tests with input as GoodClassroomApi01
PassTestResult(PolicyId, Output)
}
test_ClassroomAPI_JoinClasses_Incorrect_1 if {
PolicyId := ClassroomId1_2
Output := tests with input as BadClassroomApi01
whichClasses := "Classes in allowlisted domains"
failedOU := [{"Name": "thirdOU",
"Value": NonComplianceMessage1_2(whichClasses)},
{"Name": "topOU",
"Value": NonComplianceMessage1_2(whichClasses)}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}

View File

@@ -0,0 +1,62 @@
package classroom
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
GoodClassroomApi02 := {
"policies": {
"topOU": {
"classroom_api_data_access": {
"enableApiAccess": false
},
"classroom_service_status": {"serviceState": "ENABLED"}
},
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
BadClassroomApi02 := {
"policies": {
"topOU": {
"classroom_api_data_access": {
"enableApiAccess": false
},
"classroom_service_status": {"serviceState": "ENABLED"}
},
"nextOU": {
},
"thirdOU": {
"classroom_class_membership": {
"whoCanJoinClasses": "ANY_GOOGLE_WORKSPACE_USER",
"whichClassesCanUsersJoin": "CLASSES_IN_ALLOWLISTED_DOMAINS"
}
},
"fourthOU": {
"classroom_api_data_access": {
"enableApiAccess": true
}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
test_ClassroomAPI_DataAccess_Correct_1 if {
PolicyId := ClassroomId2_1
Output := tests with input as GoodClassroomApi02
PassTestResult(PolicyId, Output)
}
test_ClassroomAPI_DataAccess_Incorrect_1 if {
PolicyId := ClassroomId2_1
Output := tests with input as BadClassroomApi02
failedOU := [{"Name": "fourthOU",
"Value": NonComplianceMessage2_1(GetFriendlyValue2_1(true))}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}

View File

@@ -0,0 +1,65 @@
package classroom
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
GoodClassroomApi03 := {
"policies": {
"topOU": {
"classroom_roster_import": {
"rosterImportOption": "OFF"
},
"classroom_service_status": {"serviceState": "ENABLED"}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
BadClassroomApi03 := {
"policies": {
"topOU": {
"classroom_roster_import": {
"rosterImportOption": "OFF"
},
"classroom_service_status": {"serviceState": "ENABLED"}
},
"nextOU": {
},
"thirdOU": {
"classroom_class_membership": {
"whoCanJoinClasses": "ANY_GOOGLE_WORKSPACE_USER",
"whichClassesCanUsersJoin": "CLASSES_IN_ALLOWLISTED_DOMAINS"
}
},
"fourthOU": {
"classroom_api_data_access": {
"enableApiAccess": true
},
"classroom_roster_import": {
"rosterImportOption": "ON_CLEVER"
}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
test_ClassroomAPI_RosterImport_Correct_1 if {
PolicyId := ClassroomId3_1
Output := tests with input as GoodClassroomApi03
PassTestResult(PolicyId, Output)
}
test_ClassroomAPI_DataAccess_Incorrect_1 if {
PolicyId := ClassroomId3_1
Output := tests with input as BadClassroomApi03
failedOU := [{"Name": "fourthOU",
"Value": NonComplianceMessage3_1("ON - CLEVER")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}

View File

@@ -0,0 +1,65 @@
package classroom
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
GoodClassroomApi04 := {
"policies": {
"topOU": {
"classroom_student_unenrollment": {
"whoCanUnenrollStudents": "TEACHERS_ONLY"
}
},
"classroom_service_status": {"serviceState": "ENABLED"}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
BadClassroomApi04 := {
"policies": {
"topOU": {
"classroom_student_unenrollment": {
"whoCanUnenrollStudents": "TEACHERS_ONLY"
},
"classroom_service_status": {"serviceState": "ENABLED"}
},
"nextOU": {
},
"thirdOU": {
"classroom_class_membership": {
"whoCanJoinClasses": "ANY_GOOGLE_WORKSPACE_USER",
"whichClassesCanUsersJoin": "CLASSES_IN_ALLOWLISTED_DOMAINS"
},
"classroom_student_unenrollment": {
"whoCanUnenrollStudents": "STUDENTS_AND_TEACHERS"
}
},
"fourthOU": {
"classroom_roster_import": {
"rosterImportOption": "ON_CLEVER"
}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
test_ClassroomAPI_Unenrollment_Correct_1 if {
PolicyId := ClassroomId4_1
Output := tests with input as GoodClassroomApi04
PassTestResult(PolicyId, Output)
}
test_ClassroomAPI_Unenrollment_Incorrect_1 if {
PolicyId := ClassroomId4_1
Output := tests with input as BadClassroomApi04
failedOU := [{"Name": "thirdOU",
"Value": NonComplianceMessage4_1("Students and teachers")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}

View File

@@ -0,0 +1,65 @@
package classroom
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
GoodClassroomApi05 := {
"policies": {
"topOU": {
"classroom_teacher_permissions": {
"whoCanCreateClasses": "VERIFIED_TEACHERS_ONLY"
},
"classroom_service_status": {"serviceState": "ENABLED"}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
BadClassroomApi05 := {
"policies": {
"topOU": {
"classroom_teacher_permissions": {
"whoCanCreateClasses": "VERIFIED_TEACHERS_ONLY"
},
"classroom_service_status": {"serviceState": "ENABLED"}
},
"nextOU": {
},
"thirdOU": {
"classroom_class_membership": {
"whoCanJoinClasses": "ANY_GOOGLE_WORKSPACE_USER",
"whichClassesCanUsersJoin": "CLASSES_IN_ALLOWLISTED_DOMAINS"
},
"classroom_student_unenrollment": {
"whoCanUnenrollStudents": "STUDENTS_AND_TEACHERS"
}
},
"fourthOU": {
"classroom_teacher_permissions": {
"whoCanCreateClasses": "ALL_PENDING_AND_VERIFIED_TEACHERS"
}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
test_ClassroomAPI_Unenrollment_Correct_1 if {
PolicyId := ClassroomId5_1
Output := tests with input as GoodClassroomApi05
PassTestResult(PolicyId, Output)
}
test_ClassroomAPI_Unenrollment_Incorrect_1 if {
PolicyId := ClassroomId5_1
Output := tests with input as BadClassroomApi05
failedOU := [{"Name": "fourthOU",
"Value": NonComplianceMessage5_1("all pending and verified teachers")}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}

View File

@@ -2,11 +2,11 @@ package commoncontrols
import future.keywords
#
# GWS.COMMONCONTROLS.1.1v0.3
# GWS.COMMONCONTROLS.1.1
#--
test_EnforceMFA_Correct_V1 if {
# Test enforcing MFA when there's only one event
PolicyId := "GWS.COMMONCONTROLS.1.1v0.3"
PolicyId := CommonControlsId1_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -55,7 +55,7 @@ test_EnforceMFA_Correct_V1 if {
test_EnforceMFA_Correct_V2 if {
# Test enforcing MFA when there's multiple events, with the chronological latest
# correct but not last in json list
PolicyId := "GWS.COMMONCONTROLS.1.1v0.3"
PolicyId := CommonControlsId1_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -113,7 +113,7 @@ test_EnforceMFA_Correct_V2 if {
test_EnforceMFA_Incorrect_V1 if {
# Test enforcing MFA when there's only one event and it's wrong
PolicyId := "GWS.COMMONCONTROLS.1.1v0.3"
PolicyId := CommonControlsId1_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -166,7 +166,7 @@ test_EnforceMFA_Incorrect_V1 if {
test_EnforceMFA_Incorrect_V2 if {
# Test enforcing MFA when there's multiple events, with the chronological latest
# incorrect but not last in json list
PolicyId := "GWS.COMMONCONTROLS.1.1v0.3"
PolicyId := CommonControlsId1_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -229,7 +229,7 @@ test_EnforceMFA_Incorrect_V2 if {
test_EnforceMFA_Incorrect_V3 if {
# Test enforcing MFA when there's no enforce mfa event
PolicyId := "GWS.COMMONCONTROLS.1.1v0.3"
PolicyId := CommonControlsId1_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -261,7 +261,7 @@ test_EnforceMFA_Incorrect_V3 if {
test_EnforceMFA_Incorrect_V4 if {
# Test enforcing MFA when there's no change methods event
PolicyId := "GWS.COMMONCONTROLS.1.1v0.3"
PolicyId := CommonControlsId1_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -294,7 +294,7 @@ test_EnforceMFA_Incorrect_V4 if {
test_EnforceMFA_Incorrect_V5 if {
# Test, mfa not allowed
PolicyId := "GWS.COMMONCONTROLS.1.1v0.3"
PolicyId := CommonControlsId1_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -346,7 +346,7 @@ test_EnforceMFA_Incorrect_V5 if {
test_EnforceMFA_Incorrect_V6 if {
# Test, mfa not phishing resistant
PolicyId := "GWS.COMMONCONTROLS.1.1v0.3"
PolicyId := CommonControlsId1_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -401,7 +401,7 @@ test_EnforceMFA_Incorrect_V6 if {
test_EnforceMFA_Incorrect_V7 if {
# Test, mfa not phishing resistant
PolicyId := "GWS.COMMONCONTROLS.1.1v0.3"
PolicyId := CommonControlsId1_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -468,17 +468,17 @@ test_EnforceMFA_Incorrect_V7 if {
"<br>",
"The following groups are non-compliant:<ul>",
"<li>test@test.com: Allowed methods is set to Any except verification codes via text, phone call</li>",
"</ul>",
"</ul>",
])
}
#--
#
# GWS.COMMONCONTROLS.1.2v0.3
# GWS.COMMONCONTROLS.1.2
#--
test_Enforcement_Correct_V1 if {
# Test enforcing MFA when there's only one event
PolicyId := "GWS.COMMONCONTROLS.1.2v0.3"
PolicyId := CommonControlsId1_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -507,7 +507,7 @@ test_Enforcement_Correct_V1 if {
test_Enforcement_Correct_V2 if {
# Test enforcing MFA when there's multiple events, with the chronological latest
# correct but not last in json list
PolicyId := "GWS.COMMONCONTROLS.1.2v0.3"
PolicyId := CommonControlsId1_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -545,7 +545,7 @@ test_Enforcement_Correct_V2 if {
test_Enforcement_Correct_V3 if {
# Test enforcing MFA inheritance
PolicyId := "GWS.COMMONCONTROLS.1.2v0.3"
PolicyId := CommonControlsId1_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -593,7 +593,7 @@ test_Enforcement_Correct_V3 if {
test_Enforcement_Incorrect_V1 if {
# Test enforcing MFA when there's only one event and it's wrong
PolicyId := "GWS.COMMONCONTROLS.1.2v0.3"
PolicyId := CommonControlsId1_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -626,7 +626,7 @@ test_Enforcement_Incorrect_V1 if {
test_Enforcement_Incorrect_V2 if {
# Test enforcing MFA when there's multiple events, with the chronological latest
# incorrect but not last in json list
PolicyId := "GWS.COMMONCONTROLS.1.2v0.3"
PolicyId := CommonControlsId1_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -669,7 +669,7 @@ test_Enforcement_Incorrect_V2 if {
test_Enforcement_Incorrect_V3 if {
# Test enforcing MFA when there no applicable event
PolicyId := "GWS.COMMONCONTROLS.1.2v0.3"
PolicyId := CommonControlsId1_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -701,11 +701,12 @@ test_Enforcement_Incorrect_V3 if {
}
#
# GWS.COMMONCONTROLS.1.4v0.3
# GWS.COMMONCONTROLS.1.3
#--
test_Disable_Trusted_Device_Correct_V1 if {
# Test disable trusted device when there's only one event
PolicyId := "GWS.COMMONCONTROLS.1.3v0.3"
PolicyId := CommonControlsId1_3
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -734,7 +735,7 @@ test_Disable_Trusted_Device_Correct_V1 if {
test_Disable_Trusted_Device_Correct_V2 if {
# Test disabled trusted device when there's multiple events, with the chronological latest
# correct but not last in json list
PolicyId := "GWS.COMMONCONTROLS.1.3v0.3"
PolicyId := CommonControlsId1_3
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -772,7 +773,7 @@ test_Disable_Trusted_Device_Correct_V2 if {
test_Disable_Trusted_Device_Incorrect_V1 if {
# Test disable trusted device when there's only one event and it's wrong
PolicyId := "GWS.COMMONCONTROLS.1.3v0.3"
PolicyId := CommonControlsId1_3
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -805,7 +806,7 @@ test_Disable_Trusted_Device_Incorrect_V1 if {
test_Disable_Trusted_Device_Incorrect_V2 if {
# Test disabled trusted device when there's multiple events, with the chronological latest
# incorrect but not last in json list
PolicyId := "GWS.COMMONCONTROLS.1.3v0.3"
PolicyId := CommonControlsId1_3
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -848,7 +849,7 @@ test_Disable_Trusted_Device_Incorrect_V2 if {
test_Disable_Trusted_Device_Incorrect_V3 if {
# Test disabled trusted device when there no applicable event
PolicyId := "GWS.COMMONCONTROLS.1.3v0.3"
PolicyId := CommonControlsId1_3
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -881,12 +882,12 @@ test_Disable_Trusted_Device_Incorrect_V3 if {
#--
#
# GWS.COMMONCONTROLS.1.4v0.3
# GWS.COMMONCONTROLS.1.4
#--
test_NotPhone_Correct_V1 if {
# Test enforcing MFA when there's only one event set to only key
PolicyId := "GWS.COMMONCONTROLS.1.4v0.3"
PolicyId := CommonControlsId1_4
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -914,7 +915,7 @@ test_NotPhone_Correct_V1 if {
test_NotPhone_Correct_V2 if {
# Test enforcing MFA when there's only one event set to any except phone
PolicyId := "GWS.COMMONCONTROLS.1.4v0.3"
PolicyId := CommonControlsId1_4
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -942,7 +943,7 @@ test_NotPhone_Correct_V2 if {
test_NotPhone_Correct_V3 if {
# Test enforcing MFA when there are multiple events
PolicyId := "GWS.COMMONCONTROLS.1.4v0.3"
PolicyId := CommonControlsId1_4
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -980,7 +981,7 @@ test_NotPhone_Correct_V3 if {
test_NotPhone_Incorrect_V1 if {
# Test enforcing MFA when there's only one event set to any
PolicyId := "GWS.COMMONCONTROLS.1.4v0.3"
PolicyId := CommonControlsId1_4
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -1012,7 +1013,7 @@ test_NotPhone_Incorrect_V1 if {
test_NotPhone_Incorrect_V2 if {
# Test enforcing MFA when there's multiple events
PolicyId := "GWS.COMMONCONTROLS.1.4v0.3"
PolicyId := CommonControlsId1_4
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -1054,7 +1055,7 @@ test_NotPhone_Incorrect_V2 if {
test_NotPhone_Incorrect_V3 if {
# Test enforcing MFA when there are no relevant events
PolicyId := "GWS.COMMONCONTROLS.1.4v0.3"
PolicyId := CommonControlsId1_4
Output := tests with input as {
"commoncontrols_logs": {"items": [
]},
@@ -1077,7 +1078,7 @@ test_NotPhone_Incorrect_V3 if {
test_NotPhone_Incorrect_V4 if {
# Test enforcing MFA when there are no relevant events for the top-level OU
PolicyId := "GWS.COMMONCONTROLS.1.4v0.3"
PolicyId := CommonControlsId1_4
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -1109,7 +1110,7 @@ test_NotPhone_Incorrect_V4 if {
test_NotPhone_Correct_V5 if {
# Test enforcing MFA when there are multiple OUs
PolicyId := "GWS.COMMONCONTROLS.1.4v0.3"
PolicyId := CommonControlsId1_4
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -1148,4 +1149,4 @@ test_NotPhone_Correct_V5 if {
"</ul>"
])
}
#--
#--

View File

@@ -2,12 +2,12 @@ package commoncontrols
import future.keywords
#
# GWS.COMMONCONTROLS.2.1v0.3
# GWS.COMMONCONTROLS.2.1
#--
test_CAA_Correct_V1 if {
# Test 1 event
PolicyId := "GWS.COMMONCONTROLS.2.1v0.3"
PolicyId := CommonControlsId2_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -33,7 +33,7 @@ test_CAA_Correct_V1 if {
test_CAA_Correct_V2 if {
# Test multiple events
PolicyId := "GWS.COMMONCONTROLS.2.1v0.3"
PolicyId := CommonControlsId2_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -68,7 +68,7 @@ test_CAA_Correct_V2 if {
test_CAA_Incorrect_V1 if {
# Test 1 event
PolicyId := "GWS.COMMONCONTROLS.2.1v0.3"
PolicyId := CommonControlsId2_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -95,7 +95,7 @@ test_CAA_Incorrect_V1 if {
test_CAA_Incorrect_V2 if {
# Test multiple events
PolicyId := "GWS.COMMONCONTROLS.2.1v0.3"
PolicyId := CommonControlsId2_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -131,7 +131,7 @@ test_CAA_Incorrect_V2 if {
test_CAA_Incorrect_V3 if {
# Test no relevant events
PolicyId := "GWS.COMMONCONTROLS.2.1v0.3"
PolicyId := CommonControlsId2_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
]},
@@ -150,4 +150,4 @@ test_CAA_Incorrect_V3 if {
"is non-compliant; manual check recommended."
])
}
#--
#--

View File

@@ -1,13 +1,17 @@
package commoncontrols
import future.keywords
import data.utils.FailTestNoEvent
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
#
# GWS.COMMONCONTROLS.3.1v0.3
# GWS.COMMONCONTROLS.3.1
#--
test_SSO_Correct_V1 if {
# Test 1 event
PolicyId := "GWS.COMMONCONTROLS.3.1v0.3"
PolicyId := CommonControlsId3_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -27,16 +31,12 @@ test_SSO_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_SSO_Correct_V2 if {
# Test multiple events
PolicyId := "GWS.COMMONCONTROLS.3.1v0.3"
PolicyId := CommonControlsId3_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -67,16 +67,12 @@ test_SSO_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_SSO_Correct_V3 if {
# Test inheritance
PolicyId := "GWS.COMMONCONTROLS.3.1v0.3"
PolicyId := CommonControlsId3_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -118,16 +114,12 @@ test_SSO_Correct_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_SSO_Incorrect_V1 if {
# Test 1 event
PolicyId := "GWS.COMMONCONTROLS.3.1v0.3"
PolicyId := CommonControlsId3_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -147,20 +139,14 @@ test_SSO_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Post-SSO verification is disabled</li>",
"</ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage3_1}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_SSO_Incorrect_V2 if {
# Test multiple events
PolicyId := "GWS.COMMONCONTROLS.3.1v0.3"
PolicyId := CommonControlsId3_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -191,20 +177,14 @@ test_SSO_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Post-SSO verification is disabled</li>",
"</ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage3_1}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_SSO_Incorrect_V3 if {
# Test no relevant events
PolicyId := "GWS.COMMONCONTROLS.3.1v0.3"
PolicyId := CommonControlsId3_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
@@ -214,20 +194,12 @@ test_SSO_Incorrect_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, ",
"Test Top-Level OU. While we are unable ",
"to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])}
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
test_SSO_Incorrect_V4 if {
# Test no relevant events in the top-level OU
PolicyId := "GWS.COMMONCONTROLS.3.1v0.3"
PolicyId := CommonControlsId3_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -247,20 +219,12 @@ test_SSO_Incorrect_V4 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, ",
"Test Top-Level OU. While we are unable ",
"to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])}
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
test_SSO_Incorrect_V5 if {
# Test multiple OUs
PolicyId := "GWS.COMMONCONTROLS.3.1v0.3"
PolicyId := CommonControlsId3_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -291,15 +255,10 @@ test_SSO_Incorrect_V5 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Second-Level OU: Post-SSO verification is disabled</li>",
"<li>Test Top-Level OU: Post-SSO verification is disabled</li>",
"</ul>"
])
failedOU := [{"Name": "Test Second-Level OU",
"Value": NonComplianceMessage3_1},
{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage3_1}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
#--

View File

@@ -1,12 +1,16 @@
package commoncontrols
import future.keywords
import data.utils.FailTestNoEvent
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
#
# GWS.COMMONCONTROLS.4.1v0.3
# GWS.COMMONCONTROLS.4.1
#--
test_Limit_Correct_V1 if {
# Test 1 event
PolicyId := "GWS.COMMONCONTROLS.4.1v0.3"
PolicyId := CommonControlsId4_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -26,16 +30,12 @@ test_Limit_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Limit_Correct_V2 if {
# Test 1 event, smaller limit than needed
PolicyId := "GWS.COMMONCONTROLS.4.1v0.3"
PolicyId := CommonControlsId4_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -55,16 +55,12 @@ test_Limit_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Limit_Correct_V3 if {
# Test multiple events
PolicyId := "GWS.COMMONCONTROLS.4.1v0.3"
PolicyId := CommonControlsId4_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -95,16 +91,12 @@ test_Limit_Correct_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Limit_Correct_V4 if {
# Test 1 event, tenant_info["topLevelOU"] empty
PolicyId := "GWS.COMMONCONTROLS.4.1v0.3"
PolicyId := CommonControlsId4_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -130,16 +122,12 @@ test_Limit_Correct_V4 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Limit_Correct_V5 if {
# Test inheritance
PolicyId := "GWS.COMMONCONTROLS.4.1v0.3"
PolicyId := CommonControlsId4_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -181,16 +169,12 @@ test_Limit_Correct_V5 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Limit_Incorrect_V1 if {
# Test 1 event
PolicyId := "GWS.COMMONCONTROLS.4.1v0.3"
PolicyId := CommonControlsId4_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -210,20 +194,14 @@ test_Limit_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Web session duration is set to 24 hours</li>",
"</ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage4_1(GetFriendlyValue4_1(86400))}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Limit_Incorrect_V2 if {
# Test multiple events
PolicyId := "GWS.COMMONCONTROLS.4.1v0.3"
PolicyId := CommonControlsId4_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -254,19 +232,14 @@ test_Limit_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Web session duration is set to 24 hours</li>",
"</ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage4_1(GetFriendlyValue4_1(86400))}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Limit_Incorrect_V3 if {
# Test multiple OUs
PolicyId := "GWS.COMMONCONTROLS.4.1v0.3"
PolicyId := CommonControlsId4_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -297,20 +270,14 @@ test_Limit_Incorrect_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Web session duration is set to 24 hours</li>",
"</ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage4_1(GetFriendlyValue4_1(86400))}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Limit_Incorrect_V4 if {
# Test no relevant events
PolicyId := "GWS.COMMONCONTROLS.4.1v0.3"
PolicyId := CommonControlsId4_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
]},
@@ -319,20 +286,12 @@ test_Limit_Incorrect_V4 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, ",
"Test Top-Level OU. While we are unable ",
"to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])}
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
test_Limit_Incorrect_V5 if {
# Test no relevant events in top-level OU
PolicyId := "GWS.COMMONCONTROLS.4.1v0.3"
PolicyId := CommonControlsId4_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -352,14 +311,6 @@ test_Limit_Incorrect_V5 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, ",
"Test Top-Level OU. While we are unable ",
"to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])}
#--
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
#--

View File

@@ -2,11 +2,11 @@ package commoncontrols
import future.keywords
#
# GWS.COMMONCONTROLS.6.1v0.3
# GWS.COMMONCONTROLS.6.1
#--
test_Separate_Correct_V1 if {
# Test not implemented
PolicyId := "GWS.COMMONCONTROLS.6.1v0.3"
PolicyId := CommonControlsId6_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
@@ -25,11 +25,11 @@ test_Separate_Correct_V1 if {
#--
#
# GWS.COMMONCONTROLS.6.2v0.3
# GWS.COMMONCONTROLS.6.2
#--
test_Count_Correct_V1 if {
# 2 super admins
PolicyId := "GWS.COMMONCONTROLS.6.2v0.3"
PolicyId := CommonControlsId6_2
Output := tests with input as {
"super_admins": [
{
@@ -58,7 +58,7 @@ test_Count_Correct_V1 if {
test_Count_Correct_V2 if {
# 3 super admins
PolicyId := "GWS.COMMONCONTROLS.6.2v0.3"
PolicyId := CommonControlsId6_2
Output := tests with input as {
"super_admins": [
{
@@ -91,7 +91,7 @@ test_Count_Correct_V2 if {
test_Count_Correct_V3 if {
# 8 super admins
PolicyId := "GWS.COMMONCONTROLS.6.2v0.3"
PolicyId := CommonControlsId6_2
Output := tests with input as {
"super_admins": [
{
@@ -144,7 +144,7 @@ test_Count_Correct_V3 if {
test_Count_Incorrect_V1 if {
# 9 super admins
PolicyId := "GWS.COMMONCONTROLS.6.2v0.3"
PolicyId := CommonControlsId6_2
Output := tests with input as {
"super_admins": [
{
@@ -201,7 +201,7 @@ test_Count_Incorrect_V1 if {
test_Count_Incorrect_V2 if {
# 1 super admins
PolicyId := "GWS.COMMONCONTROLS.6.2v0.3"
PolicyId := CommonControlsId6_2
Output := tests with input as {
"super_admins": [
{
@@ -222,4 +222,4 @@ test_Count_Incorrect_V2 if {
"though we are not able to account for this automatically.</i>"
])
}
#--
#--

View File

@@ -2,11 +2,11 @@ package commoncontrols
import future.keywords
#
# GWS.COMMONCONTROLS.7.1v0.3
# GWS.COMMONCONTROLS.7.1
#--
test_Conflicting_Correct_V1 if {
# Test not implemented
PolicyId := "GWS.COMMONCONTROLS.7.1v0.3"
PolicyId := CommonControlsId7_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
@@ -22,4 +22,4 @@ test_Conflicting_Correct_V1 if {
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Currently not able to be tested automatically; please manually check."
}
#--
#--

View File

@@ -1,12 +1,17 @@
package commoncontrols
import future.keywords
import data.utils.FailTestNoEvent
import data.utils.FailTestGroupNonCompliant
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
#
# GWS.COMMONCONTROLS.8.1v0.3
# GWS.COMMONCONTROLS.8.1
#--
test_SelfRecovery_Correct_V1 if {
# Test 1 event
PolicyId := "GWS.COMMONCONTROLS.8.1v0.3"
PolicyId := CommonControlsId8_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -29,16 +34,12 @@ test_SelfRecovery_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_SelfRecovery_Correct_V2 if {
# Test 1 event
PolicyId := "GWS.COMMONCONTROLS.8.1v0.3"
PolicyId := CommonControlsId8_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -75,16 +76,12 @@ test_SelfRecovery_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_SelfRecovery_Correct_V3 if {
# Test inheritance
PolicyId := "GWS.COMMONCONTROLS.8.1v0.3"
PolicyId := CommonControlsId8_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -135,16 +132,12 @@ test_SelfRecovery_Correct_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_SelfRecovery_Incorrect_V1 if {
# Test 1 event
PolicyId := "GWS.COMMONCONTROLS.8.1v0.3"
PolicyId := CommonControlsId8_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -167,20 +160,14 @@ test_SelfRecovery_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Allow super admins to recover their account is ON</li>",
"</ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": "Allow super admins to recover their account is ON"}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_SelfRecovery_Incorrect_V2 if {
# Test multiple events
PolicyId := "GWS.COMMONCONTROLS.8.1v0.3"
PolicyId := CommonControlsId8_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -217,20 +204,14 @@ test_SelfRecovery_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Allow super admins to recover their account is ON</li>",
"</ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": "Allow super admins to recover their account is ON"}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_SelfRecovery_Incorrect_V3 if {
# Test no relevant events
PolicyId := "GWS.COMMONCONTROLS.8.1v0.3"
PolicyId := CommonControlsId8_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
@@ -240,20 +221,12 @@ test_SelfRecovery_Incorrect_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, ",
"Test Top-Level OU. While we are unable ",
"to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])}
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
test_SelfRecovery_Incorrect_V4 if {
# Test no relevant events in the top-level OU
PolicyId := "GWS.COMMONCONTROLS.8.1v0.3"
PolicyId := CommonControlsId8_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -276,20 +249,12 @@ test_SelfRecovery_Incorrect_V4 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, ",
"Test Top-Level OU. While we are unable ",
"to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])}
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
test_SelfRecovery_Incorrect_V5 if {
# Test multiple OUs
PolicyId := "GWS.COMMONCONTROLS.8.1v0.3"
PolicyId := CommonControlsId8_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -326,21 +291,16 @@ test_SelfRecovery_Incorrect_V5 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Second-Level OU: Allow super admins to recover their account is ON</li>",
"<li>Test Top-Level OU: Allow super admins to recover their account is ON</li>",
"</ul>"
])
failedOU := [{"Name": "Test Second-Level OU",
"Value": "Allow super admins to recover their account is ON"},
{"Name": "Test Top-Level OU",
"Value": "Allow super admins to recover their account is ON"}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_SelfRecovery_Incorrect_V6 if {
# Test group
PolicyId := "GWS.COMMONCONTROLS.8.1v0.3"
PolicyId := CommonControlsId8_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -378,14 +338,8 @@ test_SelfRecovery_Incorrect_V6 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following groups are non-compliant:<ul>",
"<li>test@test: Allow super admins to recover their account is ON</li>",
"</ul>"
])
failedOU := [{"Name": "test@test",
"Value": "Allow super admins to recover their account is ON"}]
FailTestGroupNonCompliant(PolicyId, Output, failedOU)
}
#--
#--

View File

@@ -2,11 +2,11 @@ package commoncontrols
import future.keywords
#
# GWS.COMMONCONTROLS.9.1v0.3
# GWS.COMMONCONTROLS.9.1
#--
test_HighlyPriv_Correct_V1 if {
# Test not implemented
PolicyId := "GWS.COMMONCONTROLS.9.1v0.3"
PolicyId := CommonControlsId9_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
@@ -25,11 +25,11 @@ test_HighlyPriv_Correct_V1 if {
#--
#
# GWS.COMMONCONTROLS.9.2v0.3
# GWS.COMMONCONTROLS.9.2
#--
test_Sensitive_Correct_V1 if {
# Test not implemented
PolicyId := "GWS.COMMONCONTROLS.9.2v0.3"
PolicyId := CommonControlsId9_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
@@ -45,4 +45,4 @@ test_Sensitive_Correct_V1 if {
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Currently not able to be tested automatically; please manually check."
}
#--
#--

View File

@@ -1,13 +1,17 @@
package commoncontrols
import future.keywords
import data.utils.FailTestNoEvent
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
#
# GWS.COMMONCONTROLS.10.1v0.3
# GWS.COMMONCONTROLS.10.1
#--
test_AccessControl_Correct_V1 if {
# Test restricted when there is no _HIGH_RISK event present
# (not all services have a risk version, just Drive and Gmail)
PolicyId := "GWS.COMMONCONTROLS.10.1v0.3"
PolicyId := CommonControlsId10_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -35,7 +39,7 @@ test_AccessControl_Correct_V1 if {
test_AccessControl_Correct_V2 if {
# Test allowed with not high risk allowed
PolicyId := "GWS.COMMONCONTROLS.10.1v0.3"
PolicyId := CommonControlsId10_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -73,7 +77,7 @@ test_AccessControl_Correct_V2 if {
test_AccessControl_Correct_V3 if {
# Test restricted with not high risk disallowed
PolicyId := "GWS.COMMONCONTROLS.10.1v0.3"
PolicyId := CommonControlsId10_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -111,7 +115,7 @@ test_AccessControl_Correct_V3 if {
test_AccessControl_Correct_V4 if {
# Test multiple services
PolicyId := "GWS.COMMONCONTROLS.10.1v0.3"
PolicyId := CommonControlsId10_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -159,7 +163,7 @@ test_AccessControl_Correct_V4 if {
test_AccessControl_Correct_V5 if {
# Test multiple services, multiple events
PolicyId := "GWS.COMMONCONTROLS.10.1v0.3"
PolicyId := CommonControlsId10_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -228,7 +232,7 @@ test_AccessControl_Correct_V5 if {
test_AccessControl_Incorrect_V1 if {
# Test unrestricted when there is no _HIGH_RISK event present
# (not all services have a risk version, just Drive and Gmail)
PolicyId := "GWS.COMMONCONTROLS.10.1v0.3"
PolicyId := CommonControlsId10_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -256,7 +260,7 @@ test_AccessControl_Incorrect_V1 if {
test_AccessControl_Incorrect_V2 if {
# Test unrestricted with not high risk disallowed
PolicyId := "GWS.COMMONCONTROLS.10.1v0.3"
PolicyId := CommonControlsId10_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -294,7 +298,7 @@ test_AccessControl_Incorrect_V2 if {
test_AccessControl_Incorrect_V3 if {
# Test unrestricted with no high risk version
PolicyId := "GWS.COMMONCONTROLS.10.1v0.3"
PolicyId := CommonControlsId10_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -322,7 +326,7 @@ test_AccessControl_Incorrect_V3 if {
test_AccessControl_Incorrect_V4 if {
# Test no events
PolicyId := "GWS.COMMONCONTROLS.10.1v0.3"
PolicyId := CommonControlsId10_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
@@ -345,11 +349,11 @@ test_AccessControl_Incorrect_V4 if {
#--
#
# GWS.COMMONCONTROLS.10.2v0.3
# GWS.COMMONCONTROLS.10.2
#--
test_Consent_Correct_V1 if {
# Test disallow with no high risk version
PolicyId := "GWS.COMMONCONTROLS.10.2v0.3"
PolicyId := CommonControlsId10_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -377,7 +381,7 @@ test_Consent_Correct_V1 if {
test_Consent_Correct_V2 if {
# Test disallow with high risk version
PolicyId := "GWS.COMMONCONTROLS.10.2v0.3"
PolicyId := CommonControlsId10_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -415,7 +419,7 @@ test_Consent_Correct_V2 if {
test_Consent_Incorrect_V1 if {
# Test allow with no high risk version
PolicyId := "GWS.COMMONCONTROLS.10.2v0.3"
PolicyId := CommonControlsId10_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -443,7 +447,7 @@ test_Consent_Incorrect_V1 if {
test_Consent_Incorrect_V2 if {
# Test allow with high risk version allowed
PolicyId := "GWS.COMMONCONTROLS.10.2v0.3"
PolicyId := CommonControlsId10_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -481,7 +485,7 @@ test_Consent_Incorrect_V2 if {
test_Consent_Incorrect_V3 if {
# Test allow with high risk version blocked
PolicyId := "GWS.COMMONCONTROLS.10.2v0.3"
PolicyId := CommonControlsId10_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -519,7 +523,7 @@ test_Consent_Incorrect_V3 if {
test_Consent_Incorrect_V4 if {
# Test no events
PolicyId := "GWS.COMMONCONTROLS.10.2v0.3"
PolicyId := CommonControlsId10_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
@@ -542,11 +546,11 @@ test_Consent_Incorrect_V4 if {
#--
#
# GWS.COMMONCONTROLS.10.3v0.3
# GWS.COMMONCONTROLS.10.3
#--
test_Internal_Correct_V1 if {
# Test basic
PolicyId := "GWS.COMMONCONTROLS.10.3v0.3"
PolicyId := CommonControlsId10_3
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -564,16 +568,12 @@ test_Internal_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Internal_Correct_V2 if {
# Test multiple events
PolicyId := "GWS.COMMONCONTROLS.10.3v0.3"
PolicyId := CommonControlsId10_3
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -600,16 +600,12 @@ test_Internal_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Internal_Incorrect_V1 if {
# Test basic
PolicyId := "GWS.COMMONCONTROLS.10.3v0.3"
PolicyId := CommonControlsId10_3
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -627,20 +623,14 @@ test_Internal_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Trust internal apps is ON</li>",
"</ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": "Trust internal apps is ON"}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Internal_Incorrect_V2 if {
# Test multiple events
PolicyId := "GWS.COMMONCONTROLS.10.3v0.3"
PolicyId := CommonControlsId10_3
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -667,20 +657,14 @@ test_Internal_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Trust internal apps is ON</li>",
"</ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": "Trust internal apps is ON"}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Internal_Incorrect_V3 if {
# Test no events
PolicyId := "GWS.COMMONCONTROLS.10.3v0.3"
PolicyId := CommonControlsId10_3
Output := tests with input as {
"commoncontrols_logs": {"items": [
@@ -690,24 +674,16 @@ test_Internal_Incorrect_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, ",
"Test Top-Level OU. While we are unable ",
"to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])}
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
#--
#
# GWS.COMMONCONTROLS.10.4v0.3
# GWS.COMMONCONTROLS.10.4
#--
test_Unconfigured_Correct_V1 if {
# Test basic
PolicyId := "GWS.COMMONCONTROLS.10.4v0.3"
PolicyId := CommonControlsId10_4
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -725,16 +701,12 @@ test_Unconfigured_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Unconfigured_Correct_V2 if {
# Test basic multiple events
PolicyId := "GWS.COMMONCONTROLS.10.4v0.3"
PolicyId := CommonControlsId10_4
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -761,16 +733,12 @@ test_Unconfigured_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Unconfigured_Incorrect_V1 if {
# Test unblock
PolicyId := "GWS.COMMONCONTROLS.10.4v0.3"
PolicyId := CommonControlsId10_4
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -788,21 +756,16 @@ test_Unconfigured_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Unconfigured third-party app access is set to ",
"Allow users to access any third-party apps</li>",
"</ul>"
])
msg := sprintf("Unconfigured third-party app access is set to %s",
["Allow users to access any third-party apps"])
failedOU := [{"Name": "Test Top-Level OU",
"Value": msg}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Unconfigured_Incorrect_V2 if {
# Test signin only
PolicyId := "GWS.COMMONCONTROLS.10.4v0.3"
PolicyId := CommonControlsId10_4
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -820,21 +783,17 @@ test_Unconfigured_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Unconfigured third-party app access is set to ",
"Allow users to access third-party apps that only request basic info needed for Sign in with Google.</li>",
"</ul>"
])
msg := sprintf("Unconfigured third-party app access is set to %s %s",
["Allow users to access third-party apps that only",
"request basic info needed for Sign in with Google."])
failedOU := [{"Name": "Test Top-Level OU",
"Value": msg}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Unconfigured_Incorrect_V3 if {
# Test no events
PolicyId := "GWS.COMMONCONTROLS.10.4v0.3"
PolicyId := CommonControlsId10_4
Output := tests with input as {
"commoncontrols_logs": {"items": [
@@ -844,25 +803,17 @@ test_Unconfigured_Incorrect_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, ",
"Test Top-Level OU. While we are unable ",
"to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])}
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
#--
#
# GWS.COMMONCONTROLS.10.5v0.3
# GWS.COMMONCONTROLS.10.5
#--
test_Access_Correct_V1 if {
# Test 1 event
PolicyId := "GWS.COMMONCONTROLS.10.5v0.3"
PolicyId := CommonControlsId10_5
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -881,16 +832,12 @@ test_Access_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Access_Correct_V2 if {
# Test multiple events
PolicyId := "GWS.COMMONCONTROLS.10.5v0.3"
PolicyId := CommonControlsId10_5
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -919,16 +866,12 @@ test_Access_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Access_Incorrect_V1 if {
# Test 1 event
PolicyId := "GWS.COMMONCONTROLS.10.5v0.3"
PolicyId := CommonControlsId10_5
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -947,20 +890,14 @@ test_Access_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Allow users to manage their access to less secure apps is ON</li>",
"</ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage10_5}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Access_Incorrect_V2 if {
# Test multiple events
PolicyId := "GWS.COMMONCONTROLS.10.5v0.3"
PolicyId := CommonControlsId10_5
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -989,20 +926,14 @@ test_Access_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Allow users to manage their access to less secure apps is ON</li>",
"</ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage10_5}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Access_Incorrect_V3 if {
# Test no relevant events
PolicyId := "GWS.COMMONCONTROLS.10.5v0.3"
PolicyId := CommonControlsId10_5
Output := tests with input as {
"commoncontrols_logs": {"items": [
@@ -1012,20 +943,12 @@ test_Access_Incorrect_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, ",
"Test Top-Level OU. While we are unable ",
"to determine the state from the logs, the default setting ",
"is compliant; manual check recommended."
])}
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}
test_Access_Incorrect_V4 if {
# Test no relevant events in top-level OU
PolicyId := "GWS.COMMONCONTROLS.10.5v0.3"
PolicyId := CommonControlsId10_5
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -1044,20 +967,12 @@ test_Access_Incorrect_V4 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, ",
"Test Top-Level OU. While we are unable ",
"to determine the state from the logs, the default setting ",
"is compliant; manual check recommended."
])}
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", true)
}
test_Access_Incorrect_V5 if {
# Test multiple OUs
PolicyId := "GWS.COMMONCONTROLS.10.5v0.3"
PolicyId := CommonControlsId10_5
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -1086,14 +1001,8 @@ test_Access_Incorrect_V5 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Second-Level OU: Allow users to manage their access to less secure apps is ON</li>",
"</ul>"
])
failedOU := [{"Name": "Test Second-Level OU",
"Value": NonComplianceMessage10_5}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
#--
#--

View File

@@ -1,13 +1,18 @@
package commoncontrols
import future.keywords
import future.keywords
import data.utils.FailTestNoEvent
import data.utils.FailTestGroupNonCompliant
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
#
# GWS.COMMONCONTROLS.11.1v0.3
# GWS.COMMONCONTROLS.11.1
#--
test_Installation_Correct_V1 if {
# Test 1 event
PolicyId := "GWS.COMMONCONTROLS.11.1v0.3"
PolicyId := CommonControlsId11_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -42,16 +47,12 @@ test_Installation_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Installation_Correct_V2 if {
# Test multiple events
PolicyId := "GWS.COMMONCONTROLS.11.1v0.3"
PolicyId := CommonControlsId11_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -95,16 +96,12 @@ test_Installation_Correct_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Installation_Correct_V3 if {
# Test inheritance
PolicyId := "GWS.COMMONCONTROLS.11.1v0.3"
PolicyId := CommonControlsId11_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -159,16 +156,12 @@ test_Installation_Correct_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Installation_Incorrect_V1 if {
# Test 1 event
PolicyId := "GWS.COMMONCONTROLS.11.1v0.3"
PolicyId := CommonControlsId11_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -201,20 +194,14 @@ test_Installation_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Users can install and run any app from the Marketplace</li>",
"</ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage11_1(true)}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Installation_Incorrect_V2 if {
# Test multiple events
PolicyId := "GWS.COMMONCONTROLS.11.1v0.3"
PolicyId := CommonControlsId11_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -258,20 +245,14 @@ test_Installation_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Users can install and run any app from the Marketplace</li>",
"</ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage11_1(true)}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Installation_Incorrect_V3 if {
# Test no relevant events
PolicyId := "GWS.COMMONCONTROLS.11.1v0.3"
PolicyId := CommonControlsId11_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
@@ -281,21 +262,12 @@ test_Installation_Incorrect_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, ",
"Test Top-Level OU. While we are unable ",
"to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
test_Installation_Incorrect_V4 if {
# Test no relevant events in top-level OU
PolicyId := "GWS.COMMONCONTROLS.11.1v0.3"
PolicyId := CommonControlsId11_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -315,21 +287,12 @@ test_Installation_Incorrect_V4 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, ",
"Test Top-Level OU. While we are unable ",
"to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])
FailTestNoEvent(PolicyId, Output, "Test Top-Level OU", false)
}
test_Installation_Incorrect_V5 if {
# Test multiple OUs
PolicyId := "GWS.COMMONCONTROLS.11.1v0.3"
PolicyId := CommonControlsId11_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -386,20 +349,14 @@ test_Installation_Incorrect_V5 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Second-Level OU: Users can install and run any app from the Marketplace</li>",
"</ul>"
])
failedOU := [{"Name": "Test Second-Level OU",
"Value": NonComplianceMessage11_1(true)}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Installation_Incorrect_V6 if {
# Test internal allowed
PolicyId := "GWS.COMMONCONTROLS.11.1v0.3"
PolicyId := CommonControlsId11_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -432,20 +389,14 @@ test_Installation_Incorrect_V6 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Users can install and run any internal app, even if it's not allowlisted</li>",
"</ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage11_1(false)}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Installation_Incorrect_V7 if {
# Test group
PolicyId := "GWS.COMMONCONTROLS.11.1v0.3"
PolicyId := CommonControlsId11_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -492,14 +443,8 @@ test_Installation_Incorrect_V7 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following groups are non-compliant:<ul>",
"<li>test@test: Users can install and run any internal app, even if it's not allowlisted</li>",
"</ul>"
])
failedGroup := [{"Name": "test@test",
"Value": NonComplianceMessage11_1(false)}]
FailTestGroupNonCompliant(PolicyId, Output, failedGroup)
}
#--
#--

View File

@@ -1,12 +1,17 @@
package commoncontrols
import future.keywords
import data.utils.FailTestGroupNonCompliant
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
#
# GWS.COMMONCONTROLS.12.1v0.3
# GWS.COMMONCONTROLS.12.1
#--
test_Takeout_Correct_V1 if {
# Test basic correct
PolicyId := "GWS.COMMONCONTROLS.12.1v0.3"
PolicyId := CommonControlsId12_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -37,16 +42,12 @@ test_Takeout_Correct_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
PassTestResult(PolicyId, Output)
}
test_Takeout_Incorrect_V1 if {
# Test specifc apps allowed, ou
PolicyId := "GWS.COMMONCONTROLS.12.1v0.3"
PolicyId := CommonControlsId12_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -88,21 +89,14 @@ test_Takeout_Incorrect_V1 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: The following apps with individual admin control have Takeout enabled: ",
"Blogger, Google Maps</li>",
"</ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage12_1(["Blogger", "Google Maps"])}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Takeout_Incorrect_V2 if {
# Test nonspecific apps allowed, ou
PolicyId := "GWS.COMMONCONTROLS.12.1v0.3"
PolicyId := CommonControlsId12_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -133,20 +127,14 @@ test_Takeout_Incorrect_V2 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Takeout is enabled for services without an individual admin control</li>",
"</ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage12_1a}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Takeout_Incorrect_V3 if {
# Test nonspecific apps and specific apps allowed, ou
PolicyId := "GWS.COMMONCONTROLS.12.1v0.3"
PolicyId := CommonControlsId12_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -177,21 +165,16 @@ test_Takeout_Incorrect_V3 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Takeout is enabled for services without an individual admin control</li>",
"<li>Test Top-Level OU: The following apps with individual admin control have Takeout enabled: Blogger</li>",
"</ul>"
])
failedOU := [{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage12_1a},
{"Name": "Test Top-Level OU",
"Value": NonComplianceMessage12_1(["Blogger"])}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_Takeout_Incorrect_V4 if {
# Test nonspecific apps allowed, group
PolicyId := "GWS.COMMONCONTROLS.12.1v0.3"
PolicyId := CommonControlsId12_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -234,14 +217,8 @@ test_Takeout_Incorrect_V4 if {
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following groups are non-compliant:<ul>",
"<li>test@test: Takeout is enabled for services without an individual admin control</li>",
"</ul>"
])
failedGroup := [{"Name": "test@test",
"Value": NonComplianceMessage12_1a}]
FailTestGroupNonCompliant(PolicyId, Output, failedGroup)
}
#--
#--

View File

@@ -2,11 +2,11 @@ package commoncontrols
import future.keywords
#
# GWS.COMMONCONTROLS.13.1v0.3
# GWS.COMMONCONTROLS.13.1
#--
test_Required_Correct_V1 if {
# Test not implemented
PolicyId := "GWS.COMMONCONTROLS.13.1v0.3"
PolicyId := CommonControlsId13_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
@@ -24,4 +24,4 @@ test_Required_Correct_V1 if {
"Results for GWS.COMMONCONTROLS.13 are listed in the ",
"<a href='../IndividualReports/RulesReport.html'>Rules Report</a>."])
}
#--
#--

View File

@@ -2,11 +2,11 @@ package commoncontrols
import future.keywords
#
# GWS.COMMONCONTROLS.14.1v0.3
# GWS.COMMONCONTROLS.14.1
#--
test_SEIM_Correct_V1 if {
# Test not implemented
PolicyId := "GWS.COMMONCONTROLS.14.1v0.3"
PolicyId := CommonControlsId14_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
@@ -25,11 +25,11 @@ test_SEIM_Correct_V1 if {
#--
#
# GWS.COMMONCONTROLS.14.2v0.3
# GWS.COMMONCONTROLS.14.2
#--
test_AccessControl_Correct_V1 if {
# Test not implemented
PolicyId := "GWS.COMMONCONTROLS.14.2v0.3"
PolicyId := CommonControlsId14_2
Output := tests with input as {
"commoncontrols_logs": {"items": [

View File

@@ -2,11 +2,11 @@ package commoncontrols
import future.keywords
#
# GWS.COMMONCONTROLS.15.1v0.3
# GWS.COMMONCONTROLS.15.1
#--
test_AccessControl_Correct_V1 if {
# Test not implemented
PolicyId := "GWS.COMMONCONTROLS.15.1v0.3"
PolicyId := CommonControlsId15_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
@@ -26,11 +26,11 @@ test_AccessControl_Correct_V1 if {
#
# GWS.COMMONCONTROLS.15.2v0.3
# GWS.COMMONCONTROLS.15.2
#--
test_DataProcessing_OUs_Correct_V1 if {
# Test 1 event
PolicyId := "GWS.COMMONCONTROLS.15.2v0.3"
PolicyId := CommonControlsId15_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -59,7 +59,7 @@ test_DataProcessing_OUs_Correct_V1 if {
test_DataProcessing_OUs_Correct_V2 if {
# Test inheritance with root and sub OUs
PolicyId := "GWS.COMMONCONTROLS.15.2v0.3"
PolicyId := CommonControlsId15_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -99,7 +99,7 @@ test_DataProcessing_OUs_Correct_V2 if {
test_DataProcessing_OUs_Incorrect_V1 if {
# Test incorrect root OU
PolicyId := "GWS.COMMONCONTROLS.15.2v0.3"
PolicyId := CommonControlsId15_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -132,7 +132,7 @@ test_DataProcessing_OUs_Incorrect_V1 if {
test_DataProcessing_OUs_Incorrect_V2 if {
# Test incorrect second-level OU
PolicyId := "GWS.COMMONCONTROLS.15.2v0.3"
PolicyId := CommonControlsId15_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -176,7 +176,7 @@ test_DataProcessing_OUs_Incorrect_V2 if {
test_DataProcessing_OUs_Groups_Incorrect_V1 if {
# Test for correct root OU but with an incorrect group event
PolicyId := "GWS.COMMONCONTROLS.15.2v0.3"
PolicyId := CommonControlsId15_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -220,7 +220,7 @@ test_DataProcessing_OUs_Groups_Incorrect_V1 if {
test_DataProcessing_OUs_Groups_Incorrect_V2 if {
# Test for correct root OU but with incorrect group events
PolicyId := "GWS.COMMONCONTROLS.15.2v0.3"
PolicyId := CommonControlsId15_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -276,7 +276,7 @@ test_DataProcessing_OUs_Groups_Incorrect_V2 if {
test_DataProcessing_OUs_Groups_Incorrect_V3 if {
# Test for both incorrect OUs and group events
PolicyId := "GWS.COMMONCONTROLS.15.2v0.3"
PolicyId := CommonControlsId15_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -336,11 +336,11 @@ test_DataProcessing_OUs_Groups_Incorrect_V3 if {
#
# GWS.COMMONCONTROLS.15.3v0.3
# GWS.COMMONCONTROLS.15.3
#--
test_Logs_Correct_V1 if {
# Test 1 event
PolicyId := "GWS.COMMONCONTROLS.15.3v0.3"
PolicyId := CommonControlsId15_3
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -368,7 +368,7 @@ test_Logs_Correct_V1 if {
test_Logs_Correct_V2 if {
# Test multiple events
PolicyId := "GWS.COMMONCONTROLS.15.3v0.3"
PolicyId := CommonControlsId15_3
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -406,7 +406,7 @@ test_Logs_Correct_V2 if {
test_Logs_Incorrect_V1 if {
# Test 1 event
PolicyId := "GWS.COMMONCONTROLS.15.3v0.3"
PolicyId := CommonControlsId15_3
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -438,7 +438,7 @@ test_Logs_Incorrect_V1 if {
test_Logs_Incorrect_V2 if {
# Test multiple events
PolicyId := "GWS.COMMONCONTROLS.15.3v0.3"
PolicyId := CommonControlsId15_3
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -480,7 +480,7 @@ test_Logs_Incorrect_V2 if {
test_Logs_Incorrect_V3 if {
# Test no relevent events
PolicyId := "GWS.COMMONCONTROLS.15.3v0.3"
PolicyId := CommonControlsId15_3
Output := tests with input as {
"commoncontrols_logs": {"items": [
@@ -504,7 +504,7 @@ test_Logs_Incorrect_V3 if {
test_Logs_Incorrect_V4 if {
# Test multiple ous
PolicyId := "GWS.COMMONCONTROLS.15.3v0.3"
PolicyId := CommonControlsId15_3
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -543,4 +543,4 @@ test_Logs_Incorrect_V4 if {
"</ul>"
])
}
#--
#--

View File

@@ -1,441 +1,441 @@
package commoncontrols
import future.keywords
#
# GWS.COMMONCONTROLS.16.1v0.3
#--
test_Unlisted_Correct_V1 if {
# Test 1 event
PolicyId := "GWS.COMMONCONTROLS.16.1v0.3"
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "DISABLE_UNLISTED_SERVICES"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
}
test_Unlisted_Correct_V2 if {
# Test inheritance
PolicyId := "GWS.COMMONCONTROLS.16.1v0.3"
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "DISABLE_UNLISTED_SERVICES"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
},
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "DISABLE_UNLISTED_SERVICES"},
{"name": "NEW_VALUE", "value": "INHERIT_FROM_PARENT"},
{"name": "ORG_UNIT_NAME", "value": "Test Second-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
}
test_Unlisted_Incorrect_V1 if {
PolicyId := "GWS.COMMONCONTROLS.16.1v0.3"
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "DISABLE_UNLISTED_SERVICES"},
{"name": "NEW_VALUE", "value": "false"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Access to additional services without individual control is turned on</li>",
"</ul>"
])
}
test_Unlisted_Incorrect_V2 if {
# Test no events
PolicyId := "GWS.COMMONCONTROLS.16.1v0.3"
Output := tests with input as {
"commoncontrols_logs": {"items": [
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. While we are unable ",
"to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])
}
#--
#
# GWS.COMMONCONTROLS.16.2v0.3
#--
test_EarlyAccessApps_OUs_Correct_V1 if {
# Test 1 correct event
PolicyId := "GWS.COMMONCONTROLS.16.2v0.3"
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2024-10-15T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "false"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
}
test_EarlyAccessApps_OUs_Correct_V2 if {
# Test inheritance with root and sub OUs
PolicyId := "GWS.COMMONCONTROLS.16.2v0.3"
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "false"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
},
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "INHERIT_FROM_PARENT"},
{"name": "ORG_UNIT_NAME", "value": "Test Second-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
}
test_EarlyAccessApps_OUs_Incorrect_V1 if {
# Test incorrect root OU
PolicyId := "GWS.COMMONCONTROLS.16.2v0.3"
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2024-05-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Service status is ON</li>",
"</ul>"
])
}
test_EarlyAccessApps_OUs_Incorrect_V2 if {
# Test incorrect second-level OU
PolicyId := "GWS.COMMONCONTROLS.16.2v0.3"
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "false"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
},
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "ORG_UNIT_NAME", "value": "Test Second-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Second-Level OU: Service status is ON</li>",
"</ul>"
])
}
test_EarlyAccessApps_OUs_Correct_Groups_Incorrect_V1 if {
# Test for correct root OU but with an incorrect group event
PolicyId := "GWS.COMMONCONTROLS.16.2v0.3"
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "false"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
},
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "GROUP_EMAIL", "value": "Test Group 1"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following groups are non-compliant:<ul>",
"<li>Test Group 1: Service status is ON</li>",
"</ul>"
])
}
test_EarlyAccessApps_OUs_Correct_Groups_Incorrect_V2 if {
# Test for correct root OU but with incorrect group events
PolicyId := "GWS.COMMONCONTROLS.16.2v0.3"
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "false"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
},
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "GROUP_EMAIL", "value": "Test Group 1"},
]
}]
},
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "GROUP_EMAIL", "value": "Test Group 2"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following groups are non-compliant:<ul>",
"<li>Test Group 1: Service status is ON</li>",
"<li>Test Group 2: Service status is ON</li>",
"</ul>"
])
}
test_EarlyAccessApps_OUs_Groups_Incorrect_V1 if {
# Test for both incorrect OUs and group events
PolicyId := "GWS.COMMONCONTROLS.16.2v0.3"
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
},
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "GROUP_EMAIL", "value": "Test Group 1"},
]
}]
},
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "GROUP_EMAIL", "value": "Test Group 2"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Service status is ON</li>",
"</ul><br>",
"The following groups are non-compliant:<ul>",
"<li>Test Group 1: Service status is ON</li>",
"<li>Test Group 2: Service status is ON</li>",
"</ul>"
])
}
#--
package commoncontrols
import future.keywords
#
# GWS.COMMONCONTROLS.16.1
#--
test_Unlisted_Correct_V1 if {
# Test 1 event
PolicyId := CommonControlsId16_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "DISABLE_UNLISTED_SERVICES"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
}
test_Unlisted_Correct_V2 if {
# Test inheritance
PolicyId := CommonControlsId16_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "DISABLE_UNLISTED_SERVICES"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
},
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "DISABLE_UNLISTED_SERVICES"},
{"name": "NEW_VALUE", "value": "INHERIT_FROM_PARENT"},
{"name": "ORG_UNIT_NAME", "value": "Test Second-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
}
test_Unlisted_Incorrect_V1 if {
PolicyId := CommonControlsId16_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "DISABLE_UNLISTED_SERVICES"},
{"name": "NEW_VALUE", "value": "false"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Access to additional services without individual control is turned on</li>",
"</ul>"
])
}
test_Unlisted_Incorrect_V2 if {
# Test no events
PolicyId := CommonControlsId16_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"No relevant event in the current logs for the top-level OU, Test Top-Level OU. While we are unable ",
"to determine the state from the logs, the default setting ",
"is non-compliant; manual check recommended."
])
}
#--
#
# GWS.COMMONCONTROLS.16.2
#--
test_EarlyAccessApps_OUs_Correct_V1 if {
# Test 1 correct event
PolicyId := CommonControlsId16_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2024-10-15T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "false"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
}
test_EarlyAccessApps_OUs_Correct_V2 if {
# Test inheritance with root and sub OUs
PolicyId := CommonControlsId16_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "false"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
},
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "INHERIT_FROM_PARENT"},
{"name": "ORG_UNIT_NAME", "value": "Test Second-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == "Requirement met in all OUs and groups."
}
test_EarlyAccessApps_OUs_Incorrect_V1 if {
# Test incorrect root OU
PolicyId := CommonControlsId16_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2024-05-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Service status is ON</li>",
"</ul>"
])
}
test_EarlyAccessApps_OUs_Incorrect_V2 if {
# Test incorrect second-level OU
PolicyId := CommonControlsId16_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "false"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
},
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "ORG_UNIT_NAME", "value": "Test Second-Level OU"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Second-Level OU: Service status is ON</li>",
"</ul>"
])
}
test_EarlyAccessApps_OUs_Correct_Groups_Incorrect_V1 if {
# Test for correct root OU but with an incorrect group event
PolicyId := CommonControlsId16_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "false"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
},
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "GROUP_EMAIL", "value": "Test Group 1"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following groups are non-compliant:<ul>",
"<li>Test Group 1: Service status is ON</li>",
"</ul>"
])
}
test_EarlyAccessApps_OUs_Correct_Groups_Incorrect_V2 if {
# Test for correct root OU but with incorrect group events
PolicyId := CommonControlsId16_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "false"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
},
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "GROUP_EMAIL", "value": "Test Group 1"},
]
}]
},
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "GROUP_EMAIL", "value": "Test Group 2"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following groups are non-compliant:<ul>",
"<li>Test Group 1: Service status is ON</li>",
"<li>Test Group 2: Service status is ON</li>",
"</ul>"
])
}
test_EarlyAccessApps_OUs_Groups_Incorrect_V1 if {
# Test for both incorrect OUs and group events
PolicyId := CommonControlsId16_2
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "ORG_UNIT_NAME", "value": "Test Top-Level OU"},
]
}]
},
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "GROUP_EMAIL", "value": "Test Group 1"},
]
}]
},
{
"id": {"time": "2022-12-20T00:02:28.672Z"},
"events": [{
"name": "TOGGLE_SERVICE_ENABLED",
"parameters": [
{"name": "SERVICE_NAME", "value": "Early Access Apps"},
{"name": "NEW_VALUE", "value": "true"},
{"name": "GROUP_EMAIL", "value": "Test Group 2"},
]
}]
}
]},
"tenant_info": {
"topLevelOU": "Test Top-Level OU"
}
}
RuleOutput := [Result | some Result in Output; Result.PolicyId == PolicyId]
count(RuleOutput) == 1
not RuleOutput[0].RequirementMet
not RuleOutput[0].NoSuchEvent
RuleOutput[0].ReportDetails == concat("", [
"The following OUs are non-compliant:<ul>",
"<li>Test Top-Level OU: Service status is ON</li>",
"</ul><br>",
"The following groups are non-compliant:<ul>",
"<li>Test Group 1: Service status is ON</li>",
"<li>Test Group 2: Service status is ON</li>",
"</ul>"
])
}
#--

View File

@@ -2,11 +2,11 @@ package commoncontrols
import future.keywords
#
# GWS.COMMONCONTROLS.17.1v0.3
# GWS.COMMONCONTROLS.17.1
#--
test_MPA_Correct_V1 if {
# Test 1 event
PolicyId := "GWS.COMMONCONTROLS.17.1v0.3"
PolicyId := CommonControlsId17_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -38,7 +38,7 @@ test_MPA_Correct_V1 if {
test_MPA_Incorrect_V1 if {
# Test 1 event
PolicyId := "GWS.COMMONCONTROLS.17.1v0.3"
PolicyId := CommonControlsId17_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
{
@@ -74,7 +74,7 @@ test_MPA_Incorrect_V1 if {
test_MPA_Incorrect_V2 if {
# Test no relevent events
PolicyId := "GWS.COMMONCONTROLS.17.1v0.3"
PolicyId := CommonControlsId17_1
Output := tests with input as {
"commoncontrols_logs": {"items": [
@@ -95,4 +95,4 @@ test_MPA_Incorrect_V2 if {
"is non-compliant; manual check recommended."
])
}
#--
#--

View File

@@ -0,0 +1,64 @@
package commoncontrols
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
GoodCaseInputApi04 := {
"policies": {
"topOU": {
"security_session_controls": {
"webSessionDuration": "43200s"
},
},
"nextOU": {
},
"thirdOU": {
"security_session_controls": {
"webSessionDuration": "700m"
},
},
"fourthOU": {
"security_session_controls": {
"webSessionDuration": "12H"
},
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
BaseCaseInputApi04 := {
"policies": {
"topOU": {
"security_session_controls": {
"webSessionDuration": "43200s"
},
},
"nextOU": {
"security_session_controls": {
"webSessionDuration": "800m"
},
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
test_CCAPI_ReAuth_Comply_1 if {
PolicyId := CommonControlsId4_1
Output := tests with input as GoodCaseInputApi04
PassTestResult(PolicyId, Output)
}
test_CCAPI_ReAuth_NonComply_1 if {
PolicyId := CommonControlsId4_1
Output := tests with input as BaseCaseInputApi04
failedOU := [{"Name": "nextOU",
"Value": NonComplianceMessage4_1(GetFriendlyValue4_1(800 * 60))}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}

View File

@@ -0,0 +1,160 @@
package commoncontrols
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
GoodCaseInputApi05 := {
"policies": {
"topOU": {
"security_password": {
"allowedStrength": "STRONG",
"minimumLength": 15,
"maximumLength": 100,
"enforceRequirementsAtLogin": true,
"allowReuse": false,
"expirationDuration": "0s"
}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
BadCaseInputApi05 := {
"policies": {
"topOU": {
"security_password": {
"allowedStrength": "WEAK",
"minimumLength": 6,
"maximumLength": 100,
"enforceRequirementsAtLogin": false,
"allowReuse": true,
"expirationDuration": "10h"
}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
BadCaseInputApi05a := {
"policies": {
"topOU": {
"security_password": {
"allowedStrength": "STRONG",
"minimumLength": 15,
"maximumLength": 100,
"enforceRequirementsAtLogin": true,
"allowReuse": false,
"expirationDuration": "0s"
}
},
"nextOU": {
"security_password": {
"minimumLength": 13,
}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
test_CCAPI_PwdStrength_Comply_1 if {
PolicyId := CommonControlsId5_1
Output := tests with input as GoodCaseInputApi05
PassTestResult(PolicyId, Output)
}
test_CCAPI_PwdStrength_NonComply_1 if {
PolicyId := CommonControlsId5_1
Output := tests with input as BadCaseInputApi05
failedOU := [{"Name": "topOU",
"Value": "Password strength is WEAK, not STRONG"}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_CCAPI_PwdLength_Comply_1 if {
PolicyId := CommonControlsId5_2
Output := tests with input as GoodCaseInputApi05
PassTestResult(PolicyId, Output)
}
test_CCAPI_PwdLength_NonComply_1 if {
PolicyId := CommonControlsId5_2
Output := tests with input as BadCaseInputApi05
failedOU := [{"Name": "topOU",
"Value": NonComplianceMessage5_2(6)}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_CCAPI_PwdSuggestLength_Comply_1 if {
PolicyId := CommonControlsId5_3
Output := tests with input as GoodCaseInputApi05
PassTestResult(PolicyId, Output)
}
test_CCAPI_PwdSuggestLength_NonComply_1 if {
PolicyId := CommonControlsId5_3
Output := tests with input as BadCaseInputApi05a
failedOU := [{"Name": "nextOU",
"Value": NonComplianceMessage5_3(13)}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_CCAPI_PwdNextLogin_Comply_1 if {
PolicyId := CommonControlsId5_4
Output := tests with input as GoodCaseInputApi05
PassTestResult(PolicyId, Output)
}
test_CCAPI_PwdNextLogin_NonComply_1 if {
PolicyId := CommonControlsId5_4
Output := tests with input as BadCaseInputApi05
failedOU := [{"Name": "topOU",
"Value": "Enforce password policy at next sign-in is OFF"}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_CCAPI_PwdReuse_Comply_1 if {
PolicyId := CommonControlsId5_5
Output := tests with input as GoodCaseInputApi05
PassTestResult(PolicyId, Output)
}
test_CCAPI_PwdReuse_NonComply_1 if {
PolicyId := CommonControlsId5_5
Output := tests with input as BadCaseInputApi05
failedOU := [{"Name": "topOU",
"Value": "Allow password reuse is ON"}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}
test_CCAPI_PwdResetFrequency_Comply_1 if {
PolicyId := CommonControlsId5_6
Output := tests with input as GoodCaseInputApi05
PassTestResult(PolicyId, Output)
}
test_CCAPI_PwdResetFrequency_NonComply_1 if {
PolicyId := CommonControlsId5_6
Output := tests with input as BadCaseInputApi05
failedOU := [{"Name": "topOU",
"Value": "Password reset frequency is 10h"}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}

View File

@@ -0,0 +1,47 @@
package commoncontrols
import future.keywords
import data.utils.FailTestOUNonCompliant
import data.utils.PassTestResult
GoodCaseInputApi08 := {
"policies": {
"topOU": {
"security_super_admin_account_recovery": {
"enableAccountRecovery": false
}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
BadCaseInputApi08 := {
"policies": {
"topOU": {
"security_super_admin_account_recovery": {
"enableAccountRecovery": true
}
}
},
"tenant_info": {
"topLevelOU": "topOU"
}
}
test_CCAPI_SAAcctRecovery_Comply_1 if {
PolicyId := CommonControlsId8_1
Output := tests with input as GoodCaseInputApi08
PassTestResult(PolicyId, Output)
}
test_CCAPI_SAAcctRecovery_NonComply_1 if {
PolicyId := CommonControlsId8_1
Output := tests with input as BadCaseInputApi08
failedOU := [{"Name": "topOU",
"Value": "Allow super admins to recover their account is ON"}]
FailTestOUNonCompliant(PolicyId, Output, failedOU)
}

Some files were not shown because too many files have changed in this diff Show More