Skip to main content

Policy Development

Introduction

The Compliance Engine is designed to store all entities as files. To maintain a proper development process, these files and directories are stored in a Git repository.

Cloudaware maintains a public Compliance Engine repository containing all up-to-date policies, which is used by default when subscribing to the Compliance Engine service.

It is also possible to host your own private repository and connect it to Cloudaware for developing and hosting custom policies and other customizations. See Private Repository documentation.

This document outlines the structure of the policy repository and provides best practices for developing effective and maintainable Compliance Engine policies. Remember that policy development is not just about writing "code"; it's about declaratively defining compliance rules in a clear, understandable, and maintainable way.

Repository Structure

You can host any files in your repository, not just Compliance Engine entities. When developing policies, we encourage storing supplementary materials like screenshots, internal notes, and downloaded external documentation to provide context and intent for future maintenance and updates.

Key root-level directories include:

  • /ce: Root folder for all policies, containing subfolders:
    • /ce/ca: Stores Cloudaware's public policies
    • /ce/unit-test: Contains unit tests for Compliance Engine operations
    • (Create custom folders here for internal policies)
  • /frameworks: Root directory for compliance frameworks (subdirectories represent individual frameworks)
  • /schema: Local copies of JSON schemas for .yaml files (used for IDE validation/autocomplete). See command repo-manager schema to update the schema
  • /types: Local copies of SObject type definitions (see repo-manager types)
  • /export: Default output directory for repo-manager export
  • /lists: Contains tagged entity lists generated by repo-manager docs (useful for tracking WIP policies, policies missing documentation, tests, etc.)
  • /.ca: Stores repo-manager configuration and authorization data
  • /.docusaurus: Contains Docusaurus configuration for generating static documentation
  • /.obsidian: Default configuration for Obsidian documentation viewing
  • /.vscode: Preconfigured settings for VSCode recommended extensions (see VSCode Configuration)

Path Notation Guidelines:

  • Compliance Engine uses Linux-style paths (/) regardless of OS
  • Root directory is referenced as /
  • Absolute paths are preferred (e.g., /ce/ca/aws/ec2)
  • Relative paths are used in some cases (e.g. test-data.json)
  • Folder paths omit trailing slashes (e.g., /ce/ca/aws/ec2 instead of /ce/ca/aws/ec2/)

Folder

Folders organize policies and subfolders within the /ce folder.

Directory vs Folder:

  • Directory: Physical filesystem container, used when we refer to the directory where folder.yaml, policy.yaml or section.yaml is stored.
  • Folder: Refers to folder as entity, a directory containing a folder.yaml descriptor file, a logical container for policies

All /ce subfolders must contain either folder.yaml or policy.yaml.

Folder ID: Absolute path to directory containing folder.yaml (e.g., for descriptor /ce/ca/aws/ec2/folder.yaml, Folder ID is /ce/ca/aws/ec2)

folder.yaml Structure:

  • names: Contains display names:
    • contextual: Name shown in hierarchical contexts
    • full: Name shown in isolation

Example Hierarchy:

PathContextual NameFull Name
/ceCompliance EngineCompliance Engine
/ce/caCloudAwareCloudAware
/ce/ca/awsAWSAWS
/ce/ca/aws/ec2AWS EC2EC2

Policy

A policy in the Compliance Engine represents a specific rule or idea you want to test against your cloud environment. Think of a policy as a declarative description of a compliance requirement, not imperative code. It embodies an idea, while logic is the implementation of that idea.

A policy is not the same as logic. A policy embodies an idea, while logic is the implementation of that idea. Some policies can have multiple logic implementations, one of which can be accepted as production logic. Some policies might not have any logic implemented, either because they are not yet implemented or because they are fundamentally unimplementable due to API limitations, for example. These policies are marked with an impossible: true flag. However, it's important to keep these policies in the repository as they capture all the research done, which could be beneficial if the policy becomes implementable in the future. You might also have non-technical methods to check for compliance; in such cases, you can reference the Policy ID in external systems to combine Compliance Engine violations with external data for a complete compliance picture.

Policies serve as collaboration points between teams. For example:

  • Security team can define compliance requirements through policy documentation
  • Engineering team can develop corresponding logic implementations
  • Cross-functional teams can reference Policy IDs in external systems for holistic compliance tracking

In this scenario, security team does not need knowledge of Cloudaware CMDB, Compliance Engine, or any other Cloudaware-specific knowledge.

Policy ID: Absolute path to directory containing policy.yaml (e.g., for descriptor /ce/ca/aws/account/config-in-all-regions/policy.yaml, Policy ID is /ce/ca/aws/account/config-in-all-regions)

Each policy directory contains these key files:

  • policy.yaml (Required): Descriptor file with these notable properties:
    • names: Display names (full for standalone contexts, contextual for hierarchical views)
    • description: Concise summary (1-2 sentences without formatting)
    • impossible: Flag for technically unenforceable policies
    • type: Policy classification (COMPLIANCE_POLICY/BEST_PRACTICE). Refer to PolicyType in the schema
    • categories: Compliance dimensions (SECURITY, RELIABILITY, PERFORMANCE, COST). Refer to PolicyCategory in the schema
    • frameworkMappings: List of framework section IDs that this policy directly maps to
    • frameworkIgnoreMappings: List of framework section IDs to be ignored if the policy maps to them indirectly through similarPolicies
    • similarPolicies: Cross-references to external vendors like AWS Trusted Advisor, AWS Security Hub, etc.
    • tags: An arbitrary list of string for custom classification
  • description.md: Detailed technical specification typically containing:
    • Rationale: Business/security justification
    • Impact: Potential risks of non-compliance
    • Audit: Manual verification procedures (Console/CLI)
    • References: Supporting documentation
  • remediation.md: Mitigation guidance with:
    • Step-by-step resolution procedures
    • Console/CLI remediation paths
    • Configuration best practices
  • todo.md: Implementation roadmap/tasks, listed in /lists
  • internal.md: Developer notes (algorithms, edge cases, debug info), listed in /lists
  • {name}.logic.yaml Logic implementations. {name} can be any string, some reserved names have special behaviors:
    • prod.logic.yaml: Production logic executed by Compliance Engine (see Logic). This logic should be thoroughly tested and validated.
    • wip.logic.yaml: Development-stage logic, listed in /lists
    • unit-test.logic.yaml: Unit tests for Compliance Engine
    • example.logic.yaml: Reference implementations

Best practices:

  1. Store supporting materials (screenshots, API docs) locally with policies
  2. Maintain complete implementation context within the repository
  3. Use standardized documentation sections for maintainability
  4. Preserve historical research through impossible policies
  5. Rethink, don't just rewrite policies: Critically evaluate existing policies. Ensure they are relevant, make sense, and fully utilize all possible statuses (COMPLIANT, INCOMPLIANT, INAPPLICABLE, UNDETERMINED).
  6. Write comprehensive comments: Document the policy's purpose, implementation details, research findings, and any important notes for future developers. Aim for a high ratio of comments to policy logic.

Logic

A logic file ({name}.logic.yaml) contains the actual instructions for the Compliance Engine on how to validate input objects and assign appropriate compliance statuses. Remember, logic is declarative, describing how to determine status, not procedurally what to do.

Logic ID: The absolute path to the {name}.logic.yaml file (e.g., /ce/ca/aws/account/config-in-all-regions/prod.logic.yaml).

The {name}.logic.yaml file contains these key properties:

  • inputType: (Required) Specifies the API name of the object in the Cloudaware CMDB that this logic will evaluate, such as CA10__CaAwsInstance__c.
  • recordTypes: (Optional) Filters evaluation to specific Record Types when the inputType supports multiple types.
  • testData: (Optional) Path to test data files (e.g., local test-data.json, relative ../test-data.json, or absolute paths). Used for validation during testing.
  • importExtracts: (Optional) References to reusable data extraction rules. See Extracts section for details.
  • conditions: (Required) Ordered list of validation checks. The first condition's check returning true determines the object's status. Design conditions to be small and focused for better readability and maintainability.
  • otherwise: (Required) Fallback status assigned if no conditions match.
  • relatedLists: (Optional) Nested validations for related objects via CMDB relationships. See Related Lists for details.

Conditions

Each condition represents a discrete check that assigns a status if its evaluation returns true. Conditions are evaluated sequentially until a match occurs.

Best practices:

  • Prioritize specific conditions first to enable early exits
  • Use targeted operations like NOT_EQUAL instead of nested operations like NOT with IS_EQUAL or RELATED_LIST_HAS instead of GREATER_THAN with RELATED_LIST_COUNT
  • Leverage IDE validation through JSON schemas (Ctrl/Cmd+Space in VSCode)
  • Break down complex checks into smaller, more manageable conditions. This improves readability, maintainability, and allows for more precise status and remediation messages.
  • Use code suggestion (Ctrl+Space) while writing the policy. Schema is always up-to-date with available functionality.

Condition structure:

  • status: Compliance status to assign (DISAPPEARED, INAPPLICABLE, COMPLIANT, INCOMPLIANT, or UNDETERMINED). Refer to Status in the schema
  • currentStateMessage: Brief description of the object's state (1 sentence, no formatting recommended). Write clear and concise messages that are specific to the condition.
  • remediationMessage: Actionable guidance for INCOMPLIANT status or reference to remediation.md (omit for other statuses). Keep remediation messages brief and reference detailed instructions in remediation.md.
  • check: Boolean operation defining the check. Choose the most appropriate operation for the task. Consult the schema and use code completion in your IDE to explore available operations.

Status definitions:

  • DISAPPEARED: Automatically assigned to objects removed at the source but still in CMDB (detected via non-empty "Deleted from ..."/CA10__disappearanceTime__c fields)
  • INAPPLICABLE: Indicates the policy doesn't apply to this object variant (e.g., non-root IAM users in account-level policies)
  • COMPLIANT: Confirmed adherence to policy requirements
  • INCOMPLIANT: Verified policy violation
  • UNDETERMINED: Insufficient data for conclusive evaluation. Use UNDETERMINED when data might be missing due to permissions, API limits, or data inconsistencies. Aim to minimize false positives/negatives by explicitly handling these scenarios.

The Compliance Engine prioritizes minimizing false positives/negatives. Built-in policies account for common data inconsistencies caused by:

  • Limited collector permissions
  • Outdated credential configurations
  • Retained decommissioned accounts
  • API throttling limitations
  • Partial data collection due to polling constraints

When fields required for evaluation might be unpopulated, policies should explicitly handle these scenarios by returning UNDETERMINED.

Related lists enable multi-level validation through object relationships. Key differences from root logic:

  • Uses relationshipName instead of inputType (supports relationship chains like CA10__vpcSubnet__r.CA10__routeTableAssociations__r)
  • Excludes testData support. Related objects are tested with their parent object
  • Maintains identical structure for conditions, otherwise, and nested relatedLists

Related list evaluations produce aggregated results usable in parent logic through operations like:

  • RELATED_LIST_HAS
  • RELATED_LIST_HAS_NO
  • RELATED_LIST_COUNT
  • etc., see Operations list for details. Choose the appropriate aggregate operation based on your validation needs.

Extracts

Extracts help reduce clutter and code repetition in policies by providing validated, reusable pieces of information extracted from input objects. Prioritize using EXTRACT over direct FIELD operations in production policies for abstraction, reusability, and maintainability. While FIELD may be used during development for convenience, production policies should never contain FIELD references. This is because using EXTRACT provides several benefits, including:

  • Abstraction: isolating logic from direct field names, making policies more resilient to CMDB changes
  • Reusability: extracts can be shared across policies
  • Maintainability: centralizing field access logic in extract definitions

Extract definitions are stored in /types/{type}/{name}.extracts.yaml files. To use an extract in logic:

  1. Add an importExtracts reference in your logic file
  2. Reference the extract using EXTRACT: "{extractName}"

Naming conventions:

  • Field wrappers: When enhancing existing fields with additional checks, name the extract file /types/{type}/object.extracts.yaml and match the extract name to the original field name. Example:

    • File: /types/CA10__CaAwsInstance__c/object.extracts.yaml
    • Usage: EXTRACT: "CA10__monitoringState__c"
  • Cross-object consistency: Use identical extract names for equivalent data across different objects. Example:

    • File: /types/CA10__CaAwsInstance__c/breeze.extracts.yaml. Extract name: CA10__breezeLastUpdate__c
    • File: /types/CA10__CaAzureVirtualMachine__c/breeze.extracts.yaml. Extract name: CA10__breezeLastUpdate__c
  • JSON field handling: When extracting multiple values from a JSON field, create a dedicated {name}.extracts.yaml file containing all related extracts.

Cloudaware maintains comprehensive extracts for all managed CMDB objects. If your policy requires an extract that doesn't exist, contact your Technical Account Manager to request its creation.

Test Data

Test data consists of JSON files (typically named test-data.json) used by the repo-manager policies test command to validate policy logic implementations. This command produces {logicName}.test-results.yaml files that store test results in the repository for later documentation generation.

Test Data ID: The absolute path to the test data file (e.g., /ce/ca/aws/account/config-in-all-regions/test-data.json).

These JSON files are typically captured after completing policy logic development to prevent regression errors. The standard workflow involves:

  1. Using repo-manager policies generate CAPTURE_TEST_DATA to create SQL queries
  2. Executing generated SQL through the "BigQuery Runner" VSCode plugin (see VSCode Configuration)
  3. Saving query results in JSON format

While manual creation of test data files is possible, we recommend capturing real-world data first and then modifying the JSON to:

  • Add synthetic test objects
  • Cover all logic conditions
  • Simulate edge cases

Test data files are typically stored in the policy directory alongside policy.yaml and referenced in logic files via relative path (test-data.json). Alternative storage locations require absolute or relative path references in the testData property.

File structure:

[
{
"expectedResult": {
"status": "INAPPLICABLE",
"conditionIndex": "199",
"conditionText": "extract('CA10__stateName__c') != 'running'",
"runtimeError": null
},
"context": {
"snapshotTime": "2024-11-20T19:21:48Z"
},
"Id": "test2",
"CA10__disappearanceTime__c": null,
"CA10__stateName__c": "stopped",
"CA10__monitoringState__c": "disabled"
}
]

Key components:

  • expectedResult: Defines validation criteria
    • status: Required compliance status
    • conditionIndex: Index of matching condition group. The condition from your logic.yaml file will have an index ending in 99. Indexes ending in 01, 02, etc., represent implicit conditions.
    • conditionText: Human-readable condition logic
    • runtimeError: Runtime error (e.g., when testing invalid JSON) or null
  • context: Execution parameters
    • snapshotTime: Simulation timestamp for time-sensitive validations
  • Field values: Object properties required for logic evaluation (only includes fields referenced in policy conditions)

Section

A Section represents an individual numbered or named component within a compliance framework. The root section of a framework is itself considered a section.

Frameworks are stored in the /frameworks directory. Each directory represents the root node of a framework, and each subdirectory corresponds to a section within that framework.

All sections, including the framework root itself, must contain a descriptor file named section.yaml.

Section ID: Absolute path to the directory containing section.yaml (e.g., for descriptor /frameworks/nist-sp-800-53-r5/ac/01/section.yaml, the Section ID is /frameworks/nist-sp-800-53-r5/ac/01).

section.yaml Structure:

  • name: Full section name (equivalent to policy's names.full property). For root framework sections, this should match the framework name.
  • description: Official section description from framework documentation
  • singlePolicyOnly: Set to true if repo-manager should flag sections with multiple attached policies in /lists. Useful for frameworks requiring strict 1:1 policy-to-section mappings like CIS Foundations benchmarks.
  • similar: Cross-references to equivalent sections in other frameworks:
    • sections: List of Section IDs from this repository
    • internal: Cloudaware internal mappings
    • awsSecurityHub: AWS Security Hub mappings
      • controlUrl: Control reference by URL

Sections inherit all policies from referenced similar sections. This mechanism is particularly useful for mapping equivalent requirements across different frameworks or framework versions.

Type

Directories within the /types directory are named after the API names of SObjects in the Cloudaware CMDB (e.g., CA10__CaAwsInstance__c).

Type ID: The absolute path to the directory containing type.json or *.extracts.yaml files (e.g., /types/CA10__CaAwsInstance__c).

Type directories serve several purposes:

  • Storing extract files
  • Providing local references for available fields, lookups, relationships, etc. through generated documentation
  • Serving as reference points for other repository entities in generated documentation

Each type directory contains the following files:

  • /types/{type}/type.json: Object definition downloaded from your Cloudaware CMDB using the repo-manager types import command. This file should not be manually created or edited by the user.
  • /types/{type}/{name}.extracts.yaml: Extract definitions available for this object type. See the Extracts section for details.

Naming Conventions

The Compliance Engine enforces structured naming conventions to ensure consistency, discoverability, and interoperability across policies, frameworks, and related artifacts.

These conventions enable automated documentation generation, cross-policy references, and compatibility with Cloudaware's validation toolchain. Adherence ensures proper functioning of the repo-manager utilities and CI/CD integration.

Directory & File Naming

Policy Repository Structure

  • Root directories: Use predefined names with specific purposes:

    • /ce: Contains all policy hierarchies
    • /frameworks: Stores compliance framework definitions
    • /types: Houses CMDB object type definitions
    • /schema, /export, /lists: Follow exact naming for tooling compatibility
  • Policy paths: Use lowercase letters with hyphens to separate words in directory names:

    /ce/ca/aws/ec2/instance-detailed-monitoring
  • Special directories: Reserved names with specific behaviors:

    • /ce/unit-test: Contains policy validation tests
    • /.ca, /.docusaurus, /.obsidian, /.vscode: Configuration directories

Descriptor Files

File TypeNaming PatternRequirement
Folder descriptorfolder.yamlMandatory
Policy descriptorpolicy.yamlMandatory
Section descriptorsection.yamlMandatory
Type definitiontype.jsonAuto-generated
Extract definition{purpose}.extracts.yamlContext-dependent

Policy Components

Logic Implementations

Use reserved names for special logic files:

  • prod.logic.yaml: Production-grade implementation
  • wip.logic.yaml: Work-in-progress logic
  • unit-test.logic.yaml: Validation tests
  • example.logic.yaml: Reference implementations

prod.logic.yaml - Production Logic

The prod.logic.yaml file represents the production-grade logic implementation for a policy. This is the logic that will be executed by the Compliance Engine in a production environment. Ensure prod.logic.yaml is thoroughly tested and validated for accuracy and reliability before deployment. See Logic for details on logic file structure.

Display Names

Define dual naming in YAML descriptors:

names:
full: AWS EC2 Instance Detailed Monitoring is not enabled
contextual: Instance Detailed Monitoring is not enabled
  • Full: Standalone display name
  • Contextual: Shown in hierarchical displays

Framework Organization

  • Root directory: Matches framework's official abbreviation:

    /frameworks/nist-sp-800-53-r5
  • Section paths: Follow framework's section numbering/naming scheme:

    /frameworks/cis-aws-foundations-benchmark/01/01
    • Always use leading zeroes to maintain 2-digit numbering (e.g., 01 instead of 1)
    • For frameworks with over 100 subsections, use 3-digit numbering (e.g., 001)

CMDB Object Types

  • Type directories: Exact API names with namespace:

    /types/CA10__CaAwsInstance__c
  • Extract files: Context-specific naming patterns:

    • Field wrappers: object.extracts.yaml
    • Cross-object consistency: breeze.extracts.yaml
    • JSON processing: {field-name}.extracts.yaml

Test Data

  • Primary test data: test-data.json (stored in policy directory)
  • Alternate locations: Reference via absolute path (e.g., /ce/my-company/tagging/test-data.json) or relative path (e.g., ../shared-test-data.json)

ID Construction

All entities use absolute Linux-style paths as unique identifiers:

Entity TypeID Example
Folder/ce/ca/aws/ec2
Policy/ce/ca/aws/ec2/instance-detailed-monitoring
Logic/ce/ca/aws/ec2/instance-detailed-monitoring/prod.logic.yaml
Section/frameworks/nist-sp-800-53-r5/ac/01
Type/types/CA10__CaAwsInstance__c

Documentation Generation

While the files in the repository are human-readable, they lack functionality for developers to easily navigate between different entities. Tasks such as:

  • Finding other policies that evaluate the same object
  • Locating policies linked to framework sections
  • Reviewing test results
  • Identifying incomplete policies requiring updates
  • And more

are nearly impossible without generated documentation.

The primary command for documentation generation is repo-manager docs generate. This command analyzes the entire repository and produces *.gen.md files in the same directories as descriptor files and other entities. Documentation is generated for both permanent files (like policy.yaml) and temporary files (excluded via default /.gitignore, such as {logicName}.test-results.yaml).

repo-manager docs generate also creates a /lists directory containing flagged entities for repository management and continuous improvement, including:

  • /lists/logic-without-test-data.gen.md - Logic files lacking test data
  • /lists/logic-test-results-missing.gen.md - Logic files with missing test results (typically indicating policy failures after running repo-manager policies test all)
  • /lists/policy-with-todo.md.gen.md - Policies containing TODO files
  • /lists/policy-without-description.md.gen - Policies missing description files
  • /lists/policy-without-remediation.md.gen - Policies missing remediation guidance
  • And numerous other classifications

Key index files include:

  • /index.gen.md - Main repository index with links to all entities
  • /frameworks/index.gen.md - Compliance framework directory
  • /types/index.gen.md - CMDB type references
  • /lists/index.gen.md - Management lists overview

All entities feature clickable links to related objects and associated lists. For example:

  • Folders display contained policies
  • Policies show linked framework sections
  • Types list all logic files using them as inputType

For active development sessions, use repo-manager docs generate --watch to enable real-time documentation updates when files change. (Warning: This feature remains in alpha)

Before pulling upstream changes, clean generated documentation with:

repo-manager docs cleanup

If you notice significant discrepancies between generated documentation and repository contents, use:

repo-manager docs cleanup
repo-manager policies test all
repo-manager docs generate

For CI/CD integration and static site generation, refer to Private repository documentation.

VSCode Configuration

Tools for policy development and repository management are IDE-agnostic and can be used with any preferred IDE such as VSCode, JetBrains IDEs (IntelliJ IDEA, WebStorm, PyCharm), etc.

The most common choice is VS Code, and this repository comes pre-configured with recommended extensions for policy development.

The VSCode configuration file is located at /.vscode/settings.json in this repository.

The following extensions are recommended for optimal development experience:

.yaml file support

  • YAML Pre-configured for schema mapping. Utilize schema validation and autocompletion (Ctrl+Space) for accurate policy writing.

    To install and verify YAML support:

    1. Open the Extensions panel (left sidebar) in VS Code.
    2. Search for "YAML" and install the extension by Red Hat.
    3. Verify schema validation: Open a policy.yaml file and ensure schema validation and autocompletion are working (Ctrl/Cmd+Space).

.md file support

BigQuery integration

  • SQL (BigQuery)
  • BigQuery Runner
    1. Open the Extensions panel
    2. Search for "BigQuery Runner" and install
    3. Configure authentication:
      • Select "Authentication -> Gcloud Credential (Recommended)"
      • Follow the instructions provided
        Note: Google Cloud CLI installation might take significant time
    4. Restart VS Code
    5. Verify BigQuery Runner functionality in the left panel

General utilities

Policy Development

Executing and Debugging Policy

Any policy can be executed, and the results retrieved from your local IDE.

Prerequisites:

  • repo-manager must have an active authorization profile (see repo-manager auth).
  • BigQuery Runner (or an alternative method for executing BigQuery queries) must be installed and configured (see VSCode Configuration).
  • The policy's logic file you intend to execute must be syntactically correct.

To compile a policy into a query, execute the following command:

repo-manager policies generate DEBUG /ce/ca/aws/ec2/instance-detailed-monitoring/prod.logic.yaml

The output of this command should resemble the following:

profiles.json found in {pathToRepo}/.ca/profiles.json
Requested generation for *.logic.yaml: /ce/ca/aws/ec2/instance-detailed-monitoring/prod.logic.yaml
Generation bundle:
- /ce/ca/aws/ec2/instance-detailed-monitoring/policy.yaml
- /ce/ca/aws/ec2/instance-detailed-monitoring/prod.logic.yaml
- /types/CA10__CaAwsInstance__c/object.extracts.yaml
- /ce/ca/aws/ec2/instance-detailed-monitoring/test-data.json
Script written to '/ce/ca/aws/ec2/instance-detailed-monitoring/.generated/debug.sql'

This command informs you that the generated query is available in the file /ce/ca/aws/ec2/instance-detailed-monitoring/.generated/debug.sql. Navigate to this file.

The file contains a script with several queries:

  • The main query, which produces raw results in a table named ResultsDetailed.
  • Pre-generated debug queries for common debugging scenarios, such as:
    • The number of objects triggering each specific condition.
    • For fields used in each condition, the distinct values present in those fields. This is useful for determining values for fields representing different types, such as Instance Type, Database Engines, Encryption Types, etc.
    • Other helpful queries, depending on the complexity of the logic.

These queries are intended as templates and examples for you to explore the data and understand how your policy functions with the available data. Feel free to modify the provided queries or create new ones. Ensure you save any queries you wish to keep outside the .generated directory, as this is a temporary directory that is deleted by repo-manager docs cleanup or by running repo-manager policies generate DEBUG.

The main query is useful for analyzing the general flow of the evaluation logic and provides the following columns:

  • scope - The scope of the conditions. 0: {objectType} for the logic itself, 1: {relationshipName} for the first related list, and so on.
  • status - The status returned by the condition.
  • conditionIndex - The index of the condition evaluated. Each condition group in the logic is assigned a block of 100 indexes. The condition from your logic.yaml file will have an index ending in 99. Indexes ending in 01, 02, etc., represent implicit conditions, such as checks for data availability or conditions that lead to an UNDETERMINED status.
  • conditionText - A human-readable representation of the condition logic.
  • currentStateMessage - The message provided in the logic for this condition.
  • runtimeError - A runtime error message, if one occurred; otherwise, null.
  • objectCount - The number of objects for which this condition evaluated to true.

Writing New Policy

Developing a policy involves defining its purpose, documenting its rationale, and creating the necessary files within the repository. Here's a breakdown of the process:

  1. Define the Policy Idea: Clearly articulate the rule or idea you want to enforce or monitor in your cloud environment. Consider the business or security justification, potential impact of non-compliance, and whether it's technically feasible to implement.

  2. Create Policy Folder: Follow the directory naming conventions to create a new directory under /ce for your policy. For example, if you are creating a policy for AWS EC2 instances related to security, you might create a directory like /ce/my-company/aws/ec2/instance-security-baseline. Make sure all directories up to the policy directory have folder.yaml descriptors.

  3. Create Policy Files:

    • policy.yaml: This is the core descriptor file. Define the policy's names, description, type, categories, frameworkMappings, tags, and other relevant properties as described in the policy.yaml Structure section of this document.
    • description.md: Write a detailed technical specification. Include sections for:
      • Rationale: Explain the business or security reasons behind the policy.
      • Impact: Describe the potential risks and consequences of non-compliance.
      • Audit: Outline manual procedures to verify compliance using the cloud console or CLI.
      • References: Link to relevant external documentation, standards, or internal policies.
    • remediation.md: Provide clear and actionable steps for resolving non-compliant findings. Include:
      • Step-by-step remediation procedures.
      • Console/CLI commands for remediation.
      • Configuration best practices to prevent future violations.
    • Optional Documentation: Consider creating todo.md for implementation tasks and internal.md for developer notes as needed.
  4. Implement Logic:

    • Create a logic file (e.g., prod.logic.yaml) to automate policy evaluation. Refer to the Logic section for the structure and properties of logic files.
    • Start with wip.logic.yaml for development and testing, and rename to prod.logic.yaml when the logic is production-ready.
    • Define inputType, conditions, otherwise, and relatedLists as needed to implement your policy logic.
    • Leverage Extracts to improve logic clarity and reusability.
  5. Add Supporting Materials: Store any relevant screenshots, external documentation, API references, or internal notes within the policy directory to provide context and aid future maintenance.

  6. Consider impossible Policies: If a policy is valuable for documentation or research purposes but cannot be technically enforced due to API limitations, mark it with impossible: true in policy.yaml. This preserves valuable research and intent.

  7. Follow Naming Conventions: Strictly adhere to the Naming Conventions outlined in this document to ensure consistency and proper functioning of repository tools.

  8. Test Your Logic Thoroughly: Use repo-manager policies test and Test Data to validate your logic.

  9. Comment Your Policy Extensively: Add comments to policy.yaml, logic files, and documentation. Explain the policy's purpose, implementation details, and any important considerations for future developers. Aim for a high comment-to-code ratio. Comments are invaluable for maintainability and understanding, especially for complex policies.