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

Adding adhoc GitHub script #56

Merged
merged 7 commits into from
Mar 27, 2020
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 @@ -28,7 +28,7 @@ Therefore, `detect-secrets-server` accomplishes several things:
### Quick Start

```
$ pip install detect-secrets-server
$ pip install detect-secrets-server[cron]
$ detect-secrets-server add git@github.com:yelp/detect-secrets
$ detect-secrets-server install cron
```
Expand Down
Empty file.
Empty file.
114 changes: 114 additions & 0 deletions detect_secrets_server/adhoc/github/webhook.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
"""
For organizations that integrate with Github, they have the ability to setup
a webhook to receive events for all repos under the entire organization. In
such cases, this script allows you to scan other fields in which secrets may
be leaked, rather than just focusing on secrets in code.
"""
import io
try:
from contextlib import redirect_stdout
except ImportError: # pragma: no cover
import sys
from contextlib import contextmanager

@contextmanager
def redirect_stdout(target):
original = sys.stdout
sys.stdout = target
yield
sys.stdout = original

from detect_secrets.main import main as run_detect_secrets


def scan_for_secrets(event_type, body):
"""
:type event_type: str
:param event_type: a full list can be found
https://developer.github.com/v3/activity/events/types/
:type body: Dict[str, Any]

:rtype: Optional[str]
:returns: link to field with leaked secret
"""
mapping = {
'commit_comment': _parse_comment,
'issue_comment': _parse_comment,
'pull_request_review_comment': _parse_comment,
'issues': _parse_issue,
'pull_request': _parse_pull_request,

# NOTE: We're currently ignoring `project*` events, because we don't use
# it. Pull requests welcome!
}
try:
payload, attribution_link = mapping[event_type](body)
except KeyError:
# Not an applicable event.
return None

f = io.StringIO()
with redirect_stdout(f):
run_detect_secrets([
'scan',
'--string', payload,
])

has_results = any([
line
for line in f.getvalue().splitlines()

# NOTE: Expected format: '<DetectorName>: [True/False]'
if 'True' in line.split(':')[1]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Could add # For e.g. 'SomeDetector : Bool' output

])

return attribution_link if has_results else None


def _parse_comment(body):
"""
:type body: Dict[str, Any]
:rtype: Tuple[str, str]
"""
if body.get('action', 'created') == 'deleted':
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could be wrong, but I don't think this does what you want it to.

'created' is the return value of .get if 'action' is not a present key.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's accurate. Some comments don't have action on them, and we want to scan the contents as default behavior.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess my feedback is since 'created' == 'deleted' will always be false, it feels weird, but not a strong opinion.

# This indicates that this is not an applicable event.
raise KeyError

return (
body['comment']['body'],
body['comment']['html_url'],
)


def _parse_issue(body):
"""
:type body: Dict[str, Any]
:rtype: Tuple[str, str]
"""
if body['action'] not in {'opened', 'edited', }:
# This indicates that this is not an applicable event.
raise KeyError

# NOTE: Explicitly ignoring the issue "title" here, because
# I trust developers enough (hopefully, not famous last words).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 😄

# I think a secret in the title falls under the same threat
# vector as a secret in the labels.
return (
body['issue']['body'],
body['issue']['html_url'],
)


def _parse_pull_request(body):
"""
:type body: Dict[str, Any]
:rtype: Tuple[str, str]
"""
if body['action'] not in {'opened', 'edited', }:
# This indicates that this is not an applicable event.
raise KeyError

return (
body['pull_request']['body'],
body['pull_request']['html_url'],
)
57 changes: 33 additions & 24 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
aspy.yaml==1.1.1
atomicwrites==1.2.1
attrs==18.2.0
cached-property==1.5.1
cfgv==1.1.0
coverage==4.5.2
detect-secrets==0.13.0
filelock==3.0.10
identify==1.1.8
importlib-metadata==0.8
importlib-resources==1.0.2
more-itertools==5.0.0
nodeenv==1.3.3
pathlib2==2.3.3
pbr==5.1.1
pluggy==0.8.0
pre-commit==1.13.0
py==1.7.0
pytest==4.0.2
PyYAML==5.1
six==1.12.0
appdirs==1.4.3
aspy.yaml==1.3.0
attrs==19.3.0
certifi==2019.11.28
cfgv==2.0.1
chardet==3.0.4
coverage==5.0.4
detect-secrets==0.13.1
distlib==0.3.0
filelock==3.0.12
identify==1.4.13
idna==2.9
importlib-metadata==1.5.2
importlib-resources==1.4.0
more-itertools==8.2.0
nodeenv==1.3.5
packaging==20.3
pathlib2==2.3.5
pluggy==0.13.1
pre-commit==1.21.0
py==1.8.1
pyparsing==2.4.6
pytest==5.4.1
python-crontab==2.4.1
python-dateutil==2.8.1
PyYAML==5.3.1
requests==2.23.0
six==1.14.0
toml==0.10.0
tox==3.6.1
tox==3.14.6
unidiff==0.5.5
virtualenv==16.2.0
zipp==0.3.3
urllib3==1.25.8
virtualenv==20.0.14
wcwidth==0.1.9
zipp==1.2.0
6 changes: 5 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@
'detect-secrets>=0.13.0',
'pyyaml',
'unidiff',
'python-crontab',
],
extras_require={
'cron': [
'python-crontab',
],
},
entry_points={
'console_scripts': [
'detect-secrets-server = detect_secrets_server.__main__:main',
Expand Down
8 changes: 6 additions & 2 deletions testing/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,22 @@ def metadata_factory(repo, json=False, **kwargs):
"base64_limit": 4.5,
},
"BasicAuthDetector": {},
"CloudantDetector": {},
"HexHighEntropyString": {
"hex_limit": 3,
},
"IbmCloudIamDetector": {},
"IbmCosHmacDetector": {},
"JwtTokenDetector": {},
"KeywordDetector": {
'keyword_exclude': None
},
"JwtTokenDetector": {},
"MailchimpDetector": {},
"PrivateKeyDetector": {},
"SlackDetector": {},
'SoftlayerDetector': {},
"SoftlayerDetector": {},
"StripeDetector": {},
"TwilioKeyDetector": {},
},
"repo": repo,
"sha": 'sha256-hash',
Expand Down
151 changes: 151 additions & 0 deletions testing/github/commit_comment.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
{
"action": "created",
"comment": {
"url": "https://api.github.com/repos/Codertocat/Hello-World/comments/33548674",
"html_url": "https://github.com/Codertocat/Hello-World/commit/6113728f27ae82c7b1a177c8d03f9e96e0adf246#commitcomment-33548674",
"id": 33548674,
"node_id": "MDEzOkNvbW1pdENvbW1lbnQzMzU0ODY3NA==",
"user": {
"login": "Codertocat",
"id": 21031067,
"node_id": "MDQ6VXNlcjIxMDMxMDY3",
"avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/Codertocat",
"html_url": "https://github.com/Codertocat",
"followers_url": "https://api.github.com/users/Codertocat/followers",
"following_url": "https://api.github.com/users/Codertocat/following{/other_user}",
"gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions",
"organizations_url": "https://api.github.com/users/Codertocat/orgs",
"repos_url": "https://api.github.com/users/Codertocat/repos",
"events_url": "https://api.github.com/users/Codertocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/Codertocat/received_events",
"type": "User",
"site_admin": false
},
"position": null,
"line": null,
"path": null,
"commit_id": "6113728f27ae82c7b1a177c8d03f9e96e0adf246",
"created_at": "2019-05-15T15:20:39Z",
"updated_at": "2019-05-15T15:20:39Z",
"author_association": "OWNER",
"body": "This is a really good change! :+1:"
},
"repository": {
"id": 186853002,
"node_id": "MDEwOlJlcG9zaXRvcnkxODY4NTMwMDI=",
"name": "Hello-World",
"full_name": "Codertocat/Hello-World",
"private": false,
"owner": {
"login": "Codertocat",
"id": 21031067,
"node_id": "MDQ6VXNlcjIxMDMxMDY3",
"avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/Codertocat",
"html_url": "https://github.com/Codertocat",
"followers_url": "https://api.github.com/users/Codertocat/followers",
"following_url": "https://api.github.com/users/Codertocat/following{/other_user}",
"gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions",
"organizations_url": "https://api.github.com/users/Codertocat/orgs",
"repos_url": "https://api.github.com/users/Codertocat/repos",
"events_url": "https://api.github.com/users/Codertocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/Codertocat/received_events",
"type": "User",
"site_admin": false
},
"html_url": "https://github.com/Codertocat/Hello-World",
"description": null,
"fork": false,
"url": "https://api.github.com/repos/Codertocat/Hello-World",
"forks_url": "https://api.github.com/repos/Codertocat/Hello-World/forks",
"keys_url": "https://api.github.com/repos/Codertocat/Hello-World/keys{/key_id}",
"collaborators_url": "https://api.github.com/repos/Codertocat/Hello-World/collaborators{/collaborator}",
"teams_url": "https://api.github.com/repos/Codertocat/Hello-World/teams",
"hooks_url": "https://api.github.com/repos/Codertocat/Hello-World/hooks",
"issue_events_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/events{/number}",
"events_url": "https://api.github.com/repos/Codertocat/Hello-World/events",
"assignees_url": "https://api.github.com/repos/Codertocat/Hello-World/assignees{/user}",
"branches_url": "https://api.github.com/repos/Codertocat/Hello-World/branches{/branch}",
"tags_url": "https://api.github.com/repos/Codertocat/Hello-World/tags",
"blobs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/blobs{/sha}",
"git_tags_url": "https://api.github.com/repos/Codertocat/Hello-World/git/tags{/sha}",
"git_refs_url": "https://api.github.com/repos/Codertocat/Hello-World/git/refs{/sha}",
"trees_url": "https://api.github.com/repos/Codertocat/Hello-World/git/trees{/sha}",
"statuses_url": "https://api.github.com/repos/Codertocat/Hello-World/statuses/{sha}",
"languages_url": "https://api.github.com/repos/Codertocat/Hello-World/languages",
"stargazers_url": "https://api.github.com/repos/Codertocat/Hello-World/stargazers",
"contributors_url": "https://api.github.com/repos/Codertocat/Hello-World/contributors",
"subscribers_url": "https://api.github.com/repos/Codertocat/Hello-World/subscribers",
"subscription_url": "https://api.github.com/repos/Codertocat/Hello-World/subscription",
"commits_url": "https://api.github.com/repos/Codertocat/Hello-World/commits{/sha}",
"git_commits_url": "https://api.github.com/repos/Codertocat/Hello-World/git/commits{/sha}",
"comments_url": "https://api.github.com/repos/Codertocat/Hello-World/comments{/number}",
"issue_comment_url": "https://api.github.com/repos/Codertocat/Hello-World/issues/comments{/number}",
"contents_url": "https://api.github.com/repos/Codertocat/Hello-World/contents/{+path}",
"compare_url": "https://api.github.com/repos/Codertocat/Hello-World/compare/{base}...{head}",
"merges_url": "https://api.github.com/repos/Codertocat/Hello-World/merges",
"archive_url": "https://api.github.com/repos/Codertocat/Hello-World/{archive_format}{/ref}",
"downloads_url": "https://api.github.com/repos/Codertocat/Hello-World/downloads",
"issues_url": "https://api.github.com/repos/Codertocat/Hello-World/issues{/number}",
"pulls_url": "https://api.github.com/repos/Codertocat/Hello-World/pulls{/number}",
"milestones_url": "https://api.github.com/repos/Codertocat/Hello-World/milestones{/number}",
"notifications_url": "https://api.github.com/repos/Codertocat/Hello-World/notifications{?since,all,participating}",
"labels_url": "https://api.github.com/repos/Codertocat/Hello-World/labels{/name}",
"releases_url": "https://api.github.com/repos/Codertocat/Hello-World/releases{/id}",
"deployments_url": "https://api.github.com/repos/Codertocat/Hello-World/deployments",
"created_at": "2019-05-15T15:19:25Z",
"updated_at": "2019-05-15T15:20:34Z",
"pushed_at": "2019-05-15T15:20:33Z",
"git_url": "git://github.com/Codertocat/Hello-World.git",
"ssh_url": "git@github.com:Codertocat/Hello-World.git",
"clone_url": "https://github.com/Codertocat/Hello-World.git",
"svn_url": "https://github.com/Codertocat/Hello-World",
"homepage": null,
"size": 0,
"stargazers_count": 0,
"watchers_count": 0,
"language": "Ruby",
"has_issues": true,
"has_projects": true,
"has_downloads": true,
"has_wiki": true,
"has_pages": true,
"forks_count": 0,
"mirror_url": null,
"archived": false,
"disabled": false,
"open_issues_count": 2,
"license": null,
"forks": 0,
"open_issues": 2,
"watchers": 0,
"default_branch": "master"
},
"sender": {
"login": "Codertocat",
"id": 21031067,
"node_id": "MDQ6VXNlcjIxMDMxMDY3",
"avatar_url": "https://avatars1.githubusercontent.com/u/21031067?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/Codertocat",
"html_url": "https://github.com/Codertocat",
"followers_url": "https://api.github.com/users/Codertocat/followers",
"following_url": "https://api.github.com/users/Codertocat/following{/other_user}",
"gists_url": "https://api.github.com/users/Codertocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/Codertocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/Codertocat/subscriptions",
"organizations_url": "https://api.github.com/users/Codertocat/orgs",
"repos_url": "https://api.github.com/users/Codertocat/repos",
"events_url": "https://api.github.com/users/Codertocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/Codertocat/received_events",
"type": "User",
"site_admin": false
}
}
Loading