Metadata-Version: 2.1
Name: c7n-left
Version: 0.1.11
Summary: Custodian policies for IAAC definitions
Home-page: https://cloudcustodian.io
License: Apache-2
Author: Cloud Custodian Project
Requires-Python: >=3.8,<4.0
Classifier: License :: OSI Approved :: Apache Software License
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Topic :: System :: Distributed Computing
Classifier: Topic :: System :: Systems Administration
Requires-Dist: c7n (==0.9.30) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: click (==8.1.6) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: rich (==13.5.2) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: tfparse (==0.5.0) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: argcomplete (==3.1.1) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: boto3 (==1.28.25) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: docutils (==0.18.1) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: importlib-metadata (==5.2.0) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: jsonschema (==4.19.0) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: python-dateutil (==2.8.2) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: pyyaml (==6.0.1) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: tabulate (==0.9.0) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: urllib3 (==1.26.16) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: colorama (==0.4.6) ; python_version >= "3.8" and python_version < "4.0" and platform_system == "Windows"
Requires-Dist: markdown-it-py (==2.2.0) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: pygments (==2.16.1) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: typing-extensions (==4.7.1) ; python_version >= "3.8" and python_version < "3.9"
Requires-Dist: cffi (==1.15.1) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: botocore (==1.31.25) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: jmespath (==1.0.1) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: s3transfer (==0.6.1) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: zipp (==3.16.2) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: attrs (==23.1.0) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: importlib-resources (==6.0.1) ; python_version >= "3.8" and python_version < "3.9"
Requires-Dist: jsonschema-specifications (==2023.7.1) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: pkgutil-resolve-name (==1.3.10) ; python_version >= "3.8" and python_version < "3.9"
Requires-Dist: referencing (==0.30.2) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: rpds-py (==0.9.2) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: six (==1.16.0) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: mdurl (==0.1.2) ; python_version >= "3.8" and python_version < "4.0"
Requires-Dist: pycparser (==2.21) ; python_version >= "3.8" and python_version < "4.0"
Project-URL: Documentation, https://cloudcustodian.io/docs/
Project-URL: Repository, https://github.com/cloud-custodian/cloud-custodian
Description-Content-Type: text/markdown

# Custodian policies for Infrastructure Code


This package allows cloud custodian to evaluate policies directly
against infrastructure as code source assets.

It also provides a separate cli for better command line ux for
source asset evaluation.

## Install

We currently only support python > 3.10 on mac and linux, to run on windows
we recommend using our docker images.

```shell
pip install c7n_left
```

We also provide signed docker images. These images are built on top of chainguard's [wolfi linux
distribution](https://www.chainguard.dev/unchained/introducing-wolfi-the-first-linux-un-distro) which
is designed to be minimal, auditable, and secure.

```shell
docker pull cloudcustodian/c7n_left:dev
```

Images signatures can be verified using [cosign](https://github.com/sigstore/cosign)

```
export IMAGE=$(docker image inspect cloudcustodian/c7n-left:dev -f '{{index .RepoDigests 0}}')
cosign verify $IMAGE \
   --certificate-identity 'https://github.com/cloud-custodian/cloud-custodian/.github/workflows/docker.yml@refs/heads/main' \
   --certificate-oidc-issuer 'https://token.actions.githubusercontent.com'
```


## Usage

```shell
❯ c7n-left run --help

Usage: c7n-left run [OPTIONS]

  evaluate policies against IaC sources.

  c7n-left -p policy_dir -d terraform_root --filters "severity=HIGH"

  WARNING - CLI interface subject to change.

Options:
  --format TEXT
  --filters TEXT                  filter policies or resources as k=v pairs
                                  with globbing
  -p, --policy-dir PATH
  -d, --directory PATH
  -o, --output [cli|github|json]
  --output-file FILENAME
  --output-query TEXT
  --summary [policy|resource]
  --help                          Show this message and exit.
```


We'll create an empty directory with a policy in it

```yaml
policies:
  - name: test
    resource: terraform.aws_s3_bucket
    metadata:
      severity: medium
    filters:
      - server_side_encryption_configuration: absent
```

And now we can use it to evaluate a terraform root module

```shell

❯ c7n-left run -p policies -d module
Running 1 policies on 1 resources
test - terraform.aws_s3_bucket
  Failed
  File: s3.tf:1-8
  1 resource "aws_s3_bucket" "example" {                                                                                
  2   bucket = "my-custodian-test-bucket"                                                                               
  3   acl    = "private"                                                                                                
  4                                                                                                                     
  5   tags = {                                                                                                          
  6     original-tag = "original-value"                                                                                 
  7   }                                                                                                                 
  8 }                                                                                                                   

Evaluation complete 0.00 seconds -> 1 Failures
           Summary - By Policy           
┏━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓
┃ Severity ┃ Policy ┃ Result            ┃
┡━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩
│ medium   │ test   │ 1 failed 0 passed │
└──────────┴────────┴───────────────────┘
0 compliant of 1 total, 1 resource has 1 policy violation
```

For running in docker, you'll need to use volume mounts to provide access to 
the policy directory and terraform root module.

```shell
docker run -ti --rm -v $(pwd)/policies:/policies -v $(pwd)/root-module:/module \
       cloudcustodian/c7n-left:dev run -p /policies -d /module
```

If the terraform root module has other remote module dependencies, you'll need to fetch those first using terraform
before running c7n-left.

```shell
terraform get -update
```

## CLI Filters

Which policies and which resources are evaluated can be controlled via
command line via `--filters` option.

Available filters

- `name` - policy name
- `category` - policy category
- `severity` - minimum policy severity (unknown, low, medium, high, critical)
- `type` - resource type, ie. aws_security_group
- `id` - resource id  ie. aws_vpc.example 

Multiple values for a given filter can be specified as comma separate values, and all filters
except severity support globbing.

Examples
```
# run all encryption policies on ebs volumes and sqs queues
c7n-left run -p policy_dir -d terraform --filters="category=encryption type=aws_ebs_volume,aws_sqs_queue"

# run all medium and higher level policies cost policies
c7n-left run -p policy_dir -d terraform --filters="severity=medium category=cost"
```

policy values for severity and category are specified in its metadata section. ie

```yaml

policies:
  - name: check-encryption
    resource: [aws_ebs_volume, aws_sqs_queue]
    metadata:
      category: [encryption, security]
      severity: high
    filters:
       - kms_master_key_id: absent
```       


## Outputs

if your using this in github actions, we have special output mode
for reporting annotations directly into pull requests with `--output github`

We also display a summary output after displaying resource matches, there are
two summary displays available, the default policy summary, and a resource summary
which can be enabled via `--summary resource`.


## Policy Language

Policies for c7n-left support a few additional capabilities beyond what's common for custodian policies.

Policies can be specified against multiple resource types either as an array or glob.

```yaml
policies:
  - name: check-encryption
    resource: [aws_ebs_volume, aws_sqs_queue]
```

A `traverse` filter is available that allows for multi-hop graph traversal from a resource
to any related resource.

ie, here's a policy against an aws ec2 instance, that checks if any of the security
groups attached to the instance, have a permission defined that allows access from
0.0.0.0/0 

```yaml
policies:
 - name: check-security-group-open-cidr
   resource: terraform.aws_instance
   description: "EC2 should not be open to world on ssh"
   filters:
     - type: traverse
       resources:
         - aws_security_group
         - aws_security_ingress_permission
       attrs:
         - Ipv4: 0.0.0.0/0
```


## Policy Testing

c7n-left supports writing and running tests for policies.

To create a test for a policy, create a tests directory next to your policy files.

Within that tests directory, create a sub directory with the policy name.

Next add terraform files to this sub directory. Typically you would add 
both terraform files that would match the policy and those that should not.

Finally you add assertions in a `left.plan[.yaml|.json]` file. The
format of the file is an array of dictionaries. The dictionaries are
used to match against the policy findings. The data its matching
against is what is found by using `c7n-left run --output json`. Each
key/value pair in the dictionary is matched against the finding.

So putting it all together, we've setup our tests as follows

```shell
❯ tree policy-dir-a/
policy-dir-a/
├── alb.yaml
└── tests
    └── alb-deletion-protection-disabled
        ├── left.plan.yaml
        ├── negative1.tf
        └── positive1.tf

3 directories, 4 files

❯ cat policy-dir-a/alb.yaml 
policies:
  - name: alb-deletion-protection-disabled
    resource: [terraform.aws_lb, terraform.aws_alb]
    description: |
      Application Load Balancer should have deletion protection enabled
    metadata:
      severity: low
      category: "Insecure Configurations"
    filters:
      - enable_deletion_protection: empty

❯ cat policy-dir-a/tests/alb-deletion-protection-disabled/left.plan.yaml 
- "resource.__tfmeta.filename": "positive1.tf"

```

and now we can run a test

```shell
❯ c7n-left test -p policy-dir-a/
Discovered 1 Tests
Failure alb-deletion-protection-disabled [{'resource.__tfmeta.filename': 
'positive1.tf'}] checks not used

1 Test Complete (0.05s) 1 Failure
```

A test fails if either an assertion in the plan file does not match one policy finding, or if a policy finding is not matched by an assertion.

