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

Add initial GitHub integration #422

Open
wants to merge 71 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 66 commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
5dc6721
Make directory a package
hwine Jul 8, 2020
18ef0fa
working via pytest
hwine Jul 13, 2020
5cbdc18
convert to relative imports
hwine Jul 14, 2020
5057612
running fine against all data
hwine Jul 15, 2020
a81fb21
Clean up unneeded files
hwine Jul 16, 2020
fcbf23e
Clean up integration into frost
hwine Jul 21, 2020
8b5a16e
Refactored to github/{branches,orgs}
hwine Aug 5, 2020
b4fa324
Fix error reporting
hwine Aug 5, 2020
8815245
WIP: pre move stdname
hwine Aug 19, 2020
466084a
offline working, misc cleanup
hwine Aug 27, 2020
a451634
Add tox.ini to perform doctests and fixed 3.8
hwine Aug 27, 2020
85cc75c
Remove rg (ripgrep) as not used & fails on travis
hwine Aug 27, 2020
165f48e
wip before refactor
hwine Sep 10, 2020
66dca41
Temp crutch to ensure we have a cli at end
hwine Sep 11, 2020
ca2d495
Refactored for better cli behavior
hwine Sep 11, 2020
f325c35
wrapper.py no longer breaks `make doctest`
hwine Sep 15, 2020
7edca3e
Add action stubs
hwine Sep 15, 2020
1ea32d2
Add missing required criteria
hwine Sep 15, 2020
9b1bd13
Fix doctest bustage
hwine Sep 15, 2020
2720017
Provide valid connection under pytest
hwine Sep 17, 2020
dcac1cd
Add v3 & v4 ids for branch data
hwine Sep 19, 2020
e83483b
wip
hwine Sep 22, 2020
54ab974
wip
hwine Sep 23, 2020
9d58673
wip
hwine Sep 23, 2020
0738929
wip
hwine Sep 23, 2020
1023c67
wip
hwine Sep 24, 2020
c341d4e
Add pre-commit hooks
hwine Sep 24, 2020
9716ea9
Update code to py36 syntax
hwine Sep 24, 2020
7994767
Fix "no attribute" Exception
hwine Sep 24, 2020
8127155
Fix pre-commit versions to run on travis
hwine Sep 25, 2020
bac09e3
Move to py38
hwine Sep 25, 2020
4fa814a
Python version test now correct
hwine Sep 26, 2020
e5d455d
Update pre-commit, and require it
hwine Sep 26, 2020
b06ae74
Set default to no CSV headers
hwine Sep 26, 2020
2d099f1
Only support python 3.8+ now
hwine Sep 28, 2020
39f38db
Remove Heroku
hwine Oct 1, 2020
4284359
Add json output
hwine Oct 1, 2020
cfc77c4
Special case --doctest-modules for CI
hwine Oct 1, 2020
5fc005b
Rename, as we need to invoke during production run
hwine Oct 1, 2020
3e849a8
Add option to use production arguements
hwine Oct 2, 2020
33ec405
wip
hwine Oct 2, 2020
e817c25
Remove unneeded prints
hwine Oct 2, 2020
ed5f854
add collection date
hwine Oct 7, 2020
cde1f88
wip
hwine Oct 7, 2020
13990b1
Correct day-of-data-collection field name
hwine Oct 9, 2020
c2f51df
Add --all option for all orgs owned
hwine Oct 9, 2020
6d0335d
[GITHUB] rebased to HEAD
hwine Oct 13, 2020
ef9239a
Install frost in dev mode
hwine Oct 13, 2020
60c769f
wip-fix travis
hwine Oct 13, 2020
6881142
add frost
hwine Oct 14, 2020
495a154
pass CI
hwine Oct 14, 2020
fb0225f
missing files for successful CI run
hwine Oct 14, 2020
3dd150c
Missed changes from master
hwine Oct 23, 2020
35ef8ff
METADATA_KEYS can be a set
hwine Oct 26, 2020
e778e92
Change parameterization to return dict
hwine Oct 26, 2020
a0d59c8
remove unused code
hwine Oct 26, 2020
1e5ff7b
Various cleanup, prior to merging master
hwine Nov 30, 2020
6e65f23
Merge branch 'master' into merge_master_branch_check
hwine Nov 30, 2020
115c9d1
Relocate 'Criteria' to helpers.py
hwine Dec 3, 2020
c12b8d6
Fix bustage
hwine Dec 3, 2020
bf55b62
Merge branch 'master' into branch_check
hwine Dec 3, 2020
e092802
Don't run code that isn't ready to run
hwine Dec 3, 2020
b7deb35
Remove false positives in deleted files
hwine Dec 3, 2020
3994281
Address review comments
hwine Dec 4, 2020
7bd547f
Address more review comments
hwine Dec 7, 2020
550a76a
Fix doctest
hwine Dec 7, 2020
8925ad3
More review comments addressed.
hwine Dec 7, 2020
3df42d2
Debug which token is being used :/
hwine Aug 26, 2022
6c52188
More debug
hwine Aug 26, 2022
3a7f315
debug
hwine Aug 26, 2022
c7b0164
Debug
hwine Aug 26, 2022
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
46 changes: 46 additions & 0 deletions .bandit_baseline.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"errors": [],
"generated_at": "2020-12-03T19:42:28Z",
"metrics": {
"_totals": {
"CONFIDENCE.HIGH": 1.0,
"CONFIDENCE.LOW": 0.0,
"CONFIDENCE.MEDIUM": 0.0,
"CONFIDENCE.UNDEFINED": 0.0,
"SEVERITY.HIGH": 0.0,
"SEVERITY.LOW": 0.0,
"SEVERITY.MEDIUM": 1.0,
"SEVERITY.UNDEFINED": 0.0,
"loc": 303,
"nosec": 0
},
"aws/client.py": {
"CONFIDENCE.HIGH": 1.0,
"CONFIDENCE.LOW": 0.0,
"CONFIDENCE.MEDIUM": 0.0,
"CONFIDENCE.UNDEFINED": 0.0,
"SEVERITY.HIGH": 0.0,
"SEVERITY.LOW": 0.0,
"SEVERITY.MEDIUM": 1.0,
"SEVERITY.UNDEFINED": 0.0,
"loc": 303,
"nosec": 0
}
},
"results": [
{
"code": "149 \n150 filename = md5(str.encode(arguments)).hexdigest() + \".json\"\n151 \n",
"filename": "aws/client.py",
"issue_confidence": "HIGH",
"issue_severity": "MEDIUM",
"issue_text": "Use of insecure MD2, MD4, MD5, or SHA1 hash function.",
"line_number": 150,
"line_range": [
150
],
"more_info": "https://bandit.readthedocs.io/en/latest/blacklists/blacklist_calls.html#b303-md5",
"test_id": "B303",
"test_name": "blacklist"
}
]
}
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# Frost specific files
.all_python_files.tmp

# IDE files
.vscode/

# lots of caches fit this pattern (pytest, mypy, ...)
*cache/

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
58 changes: 58 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,61 @@ repos:
rev: 19.10b0
hooks:
- id: black
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-ast
- id: check-yaml
- id: check-added-large-files
- id: check-case-conflict
- id: check-docstring-first
- id: check-merge-conflict
- id: check-toml

## ## - repo: https://github.com/asottile/pyupgrade
## ## rev: v2.7.2
## ## hooks:
## ## - id: pyupgrade
## ## args: ["--py38-plus"]

## ## - repo: https://github.com/jumanjihouse/pre-commit-hooks
## ## rev: master # or specific git tag
## ## hooks:
## ## - id: forbid-binary
## ## ## TODO - disable for docs/_build/html
## ## - id: markdownlint # Configure in .mdlrc
## ## # TODO - disable MD012 (consecutive blank lines)
## ## # disable MD013 (line length)
## ## # fix MD031 (fenced code needs blank lines) README.md
## ## - id: shellcheck

## ## - repo: https://github.com/IamTheFij/docker-pre-commit
## ## rev: v2.0.0
## ## hooks:
## ## - id: docker-compose-check
## ## - id: hadolint
## ## # TODO - disable DL3005 (apt upgrade)
## ## # disable DL3008 (unpinned packages)
## ## # disable DL3009 (left apt-get lists around)

- repo: https://github.com/PyCQA/bandit
rev: 1.6.2
hooks:
- id: bandit
args:
- "--skip"
- "B101" # use of assert
- "--baseline"
- ".bandit_baseline.json" # use of md5 for local filename
- "--quiet"

- repo: https://github.com/Yelp/detect-secrets
rev: v0.14.2
hooks:
- id: detect-secrets
args: ['--baseline', '.secrets.baseline']
exclude: ".*/tests/.*|docs/_build/html/.buildinfo"
67 changes: 67 additions & 0 deletions .secrets.baseline
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"custom_plugin_paths": [],
"exclude": {
"files": null,
"lines": null
},
"generated_at": "2020-12-03T20:08:48Z",
"plugins_used": [
{
"name": "AWSKeyDetector"
},
{
"name": "ArtifactoryDetector"
},
{
"base64_limit": 4.5,
"name": "Base64HighEntropyString"
},
{
"name": "BasicAuthDetector"
},
{
"name": "CloudantDetector"
},
{
"hex_limit": 3,
"name": "HexHighEntropyString"
},
{
"name": "IbmCloudIamDetector"
},
{
"name": "IbmCosHmacDetector"
},
{
"name": "JwtTokenDetector"
},
{
"keyword_exclude": null,
"name": "KeywordDetector"
},
{
"name": "MailchimpDetector"
},
{
"name": "PrivateKeyDetector"
},
{
"name": "SlackDetector"
},
{
"name": "SoftlayerDetector"
},
{
"name": "StripeDetector"
},
{
"name": "TwilioKeyDetector"
}
],
"results": {},
"version": "0.14.2",
"word_list": {
"file": null,
"hash": null
}
}
20 changes: 14 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
SHELL := bash -o pipefail

TODAY := $(shell date '+%Y-%m-%d')

Expand Down Expand Up @@ -45,7 +46,7 @@ doc-build: check_venv
@# we regen the api docs every time -- they are not checked in.
rm -rf docs/source
sphinx-apidoc --no-toc -o docs/source .
@# TODO: Add new service modules below also in docs/Source.rst
@# Add new service modules below also in docs/Source.rst
for module in frost aws gcp gsuite; do \
sphinx-apidoc -f -o docs/source/$$module $$module ; \
done
Expand All @@ -55,17 +56,23 @@ doc-preview: check_venv
@#sphinx-autobuild "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
sphinx-autobuild $(AUTOBUILD_OPTS) "docs/" "docs/_build/html/" $(SPHINXOPTS) $(O)

doctest: check_venv
frost test -vv --doctest-modules --doctest-glob='*.py' -s --offline --debug-calls $(shell find . -type f -name '*.py' | grep -v venv | grep -v .pyenv | grep -v setup.py) \
--doctest-modules -s --offline --debug-calls
# We need the list of all python file in several places, so only compute
# it once.
.all_python_files.tmp:
find . -type d \( -name venv -o -name .??\* \) -prune \
-o -not -name setup.py -name \*.py -print \
> $@

coverage: check_venv
doctest: check_venv .all_python_files.tmp
frost test -vv --doctest-modules -s --offline --debug-calls $$(cat .all_python_files.tmp)

coverage: check_venv .all_python_files.tmp
frost test --cov-config .coveragerc --cov=. \
--aws-profiles example-account \
-o python_files=meta_test*.py \
-o cache_dir=./example_cache/ \
--offline \
$(shell find . -type f -name '*.py' | grep -v venv | grep -v .pyenv | grep -v setup.py)
$$(cat .all_python_files.tmp)
coverage report -m
coverage html

Expand Down Expand Up @@ -96,6 +103,7 @@ build-image:
docker build -t localhost/frost:latest .

.PHONY: \
.all_python_files.tmp \
all \
awsci \
black \
Expand Down
4 changes: 2 additions & 2 deletions aws/ec2/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,15 +366,15 @@ def ec2_instance_missing_tag_names(ec2_instance, required_tag_names):
frozenset({'Name'})
"""
tags = ec2_instance.get("Tags", [])
instance_tag_names = set(tag["Key"] for tag in tags if "Key" in tag)
instance_tag_names = {tag["Key"] for tag in tags if "Key" in tag}
return required_tag_names - instance_tag_names


def ebs_volume_attached_to_instance(ebs, volume_created_days_ago=90):
"""
Check an ebs volume is attached to an instance. The "volume_created_days_ago"
parameter allows checking for volumes that were created that many days ago.

>>> from datetime import datetime
>>> from datetime import timezone

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ def test_rds_db_instance_not_publicly_accessible_by_vpc_security_group(
if not ec2_security_groups:
assert not rds_db_instance["VpcSecurityGroups"]
else:
assert set(sg["GroupId"] for sg in ec2_security_groups) == set(
assert {sg["GroupId"] for sg in ec2_security_groups} == {
sg["VpcSecurityGroupId"] for sg in rds_db_instance["VpcSecurityGroups"]
)
}

assert not any(
does_vpc_security_group_grant_public_access(sg)
Expand Down
10 changes: 4 additions & 6 deletions cache.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
"""
Patch for pytest cache to serialize datetime.datetime
"""
"""Patch for pytest cache to serialize datetime.datetime."""

import datetime
import functools
Expand Down Expand Up @@ -53,12 +51,12 @@ def datetime_encode_set(
path = self._getvaluepath(key)
try:
path.parent.mkdir(exist_ok=True, parents=True)
except (IOError, OSError):
hwine marked this conversation as resolved.
Show resolved Hide resolved
except OSError:
self.warn("could not create cache path {path}", path=path)
return
try:
f = path.open("w")
except (IOError, OSError):
except OSError:
self.warn("cache could not write path {path}", path=path)
else:
with f:
Expand All @@ -82,7 +80,7 @@ def datetime_encode_get(
try:
with path.open("r") as f:
return json.load(f, object_hook=json_iso_datetime_string_to_datetime)
except (ValueError, IOError, OSError):
except (ValueError, OSError):
return default


Expand Down
38 changes: 33 additions & 5 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import argparse
import datetime
from typing import Any

import pytest

Expand All @@ -9,14 +10,24 @@
from aws.client import BotocoreClient
from gcp.client import GCPClient
from gsuite.client import GsuiteClient
from github.client import GitHubClient

import custom_config

botocore_client = None
gcp_client = None
gsuite_client = None
github_client = None
custom_config_global = None

# globals in conftest.py are hard to import from several levels down, so provide access function
def get_client(client_name: str) -> Any:
# restrict to variables with defined suffix
suffix = "_client"
if client_name.endswith(suffix):
client_name = client_name[: -len(suffix)]
return globals()[f"{client_name}_client"]


def pytest_addoption(parser):
frost_parser = parser.getgroup("Frost", "Frost's custom arguments")
Expand Down Expand Up @@ -77,6 +88,7 @@ def pytest_configure(config):
global botocore_client
global gcp_client
global gsuite_client
global github_client
global custom_config_global

# run with -p 'no:cacheprovider'
Expand Down Expand Up @@ -119,6 +131,11 @@ def pytest_configure(config):
offline=config.getoption("--offline"),
)

github_client = GitHubClient(
debug_calls=config.getoption("--debug-calls"),
offline=config.getoption("--offline"),
)

custom_config_global = custom_config.CustomConfig(config.getoption("--config"))
config.custom_config = custom_config_global

Expand Down Expand Up @@ -215,7 +232,7 @@ def update(self, values):
error_values.add(value)
if error_values:
# we want the non-duplicate values added
super().update(values - error_values)
super().update(set(values))
raise DuplicateKeyError(
"Value(s) {!r} already present".format(error_values)
)
Expand Down Expand Up @@ -276,17 +293,28 @@ def serialize_datetimes(obj):


def extract_metadata(resource):
return {
metadata_key: resource[metadata_key]
# In some cases, `resource` will "have a dict" rather than "be a
# dict". (e.g. DataClasses instances). We do require that
# those non-dict classes have a "real" dict as the value of their
# __dict__ instance variable. (Runtime exception if not.)
if isinstance(resource, (dict,)):
ajvb marked this conversation as resolved.
Show resolved Hide resolved
# resource is (or inherits from) dict
target = resource
else:
# resource has an embedded dict that should be used
target = resource.__dict__
x = {
metadata_key: target[metadata_key]
for metadata_key in METADATA_KEYS
if metadata_key in resource
if metadata_key in target
}
return x


def get_metadata_from_funcargs(funcargs):
metadata = {}
for k in funcargs:
if isinstance(funcargs[k], dict):
if isinstance(funcargs[k], dict) or hasattr(funcargs[k], "__dict__"):
metadata = {**metadata, **extract_metadata(funcargs[k])}
return metadata

Expand Down
Loading