Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate a single SCP #19

Merged
merged 3 commits into from
Apr 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

## Overview

This project provides a python module to aid in Service Control Policy management in AWS accounts. See our release [blog](https://blog.aquia.us/blog/) for additional details.
This project provides a python module to aid in Service Control Policy management in AWS accounts.

SCPs have a current limit of 5 total per entity, and a size limit on each of 5120 bytes. This tool will merge selected SCPs into the fewest amount of policies, and optionally remove whitespace characters as they count toward the byte limit.

Expand Down
5 changes: 3 additions & 2 deletions scpkit/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
Options:
-h --help Show this screen.
--version Show version.
--sourcefiles sourcefiles Directory path to SCP files in json format
--sourcefiles sourcefiles Directory path to SCP files in json format or a single SCP file
--outdir outdir Directory to write new SCP files [Default: ./]
--profile profile AWS profile name
--validate-after-merge Validate the policies after merging them
--readable Leave indentation and some whitespace to make the SCPs readable
"""
from docopt import docopt
from .src.validate import validate_policies
from .src.merge import scp_merge, get_files_in_dir
from .src.merge import scp_merge
from .src.util import get_files_in_dir

def main():
arguments = {
Expand Down
15 changes: 1 addition & 14 deletions scpkit/src/merge.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .util import write_json, find_key_in_json, load_json, make_actions_and_resources_lists, dump_json
from .util import write_json, find_key_in_json, load_json, make_actions_and_resources_lists, dump_json, get_files_in_dir
from copy import deepcopy
from pathlib import Path
from .model import SCP
Expand Down Expand Up @@ -86,19 +86,6 @@ def scp_merge(**kwargs):
validate_policies(scps, kwargs['profile'], kwargs['outdir'])


def get_files_in_dir(folder):
"""Loads all JSON files from a directory
Args:
folder (str): Folder that contains JSON files
Returns:
[list]: list of JSON content from all files
"""

p = Path(folder)
all_content = [ SCP(name=file.name, content=load_json(file)) for file in list(p.glob('**/*.json')) ]
return all_content


def combine_similar_sids(content):
"""Combines SIDs that have the same Resource, Effect, and Condition (if exists)

Expand Down
24 changes: 18 additions & 6 deletions scpkit/src/util.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
from pathlib import Path
from .model import SCP


def load_json(filepath):
Expand Down Expand Up @@ -49,16 +50,27 @@ def dump_json(content, readable=False):
return json.dumps(content)


def get_filepaths_in_dir(folder):
"""Loads all JSON filepaths from a directory
def get_files_in_dir(filepath):
"""Loads all JSON files from a directory
Args:
folder (str): Folder that contains JSON files
filepath (str): Folder that contains JSON files or an individual json file
Returns:
[list]: list of JSON files in a directory
[list]: list of JSON content from all files
"""

p = Path(folder)
all_content = [ file for file in list(p.glob('**/*.json')) ]
p = Path(filepath)

if not p.exists():
raise FileNotFoundError(f"The file {p} does not exist.")

if p.is_dir():
p = list(p.glob('**/*.json'))
elif p.is_file():
p = [p]
else:
raise Exception

all_content = [ SCP(name=file.name, content=load_json(file)) for file in p ]
return all_content


Expand Down
11 changes: 10 additions & 1 deletion tests/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import pytest #pylint: disable=import-errors

from scpkit.src.util import find_key_in_json
from scpkit.src.util import find_key_in_json, get_files_in_dir, load_json
from scpkit.src.merge import sort_list_of_dicts, merge_json, combine_similar_sids


Expand Down Expand Up @@ -154,3 +154,12 @@ def test_combine_similar_sids():
]
scps = combine_similar_sids(test_data)
assert result == scps


def test_get_files_in_dir():
f = get_files_in_dir("./tests/testfiles")
assert len(f) == 2

def test_get_file_in_dir():
f = get_files_in_dir("./tests/testfiles/test-scp-1.json")
assert len(f) == 1
13 changes: 13 additions & 0 deletions tests/testfiles/test-scp-1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": [
"account:DisableRegion",
"account:EnableRegion"
],
"Resource": "*"
}
]
}
15 changes: 15 additions & 0 deletions tests/testfiles/test-scp-2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"StringNotEquals": {
"ec2:MetadataHttpTokens": "required"
}
}
}
]
}