Skip to content

Commit 40fb27a

Browse files
authored
Merge pull request #415 from pyupio/develop
Safety 2.3.0 patch
2 parents d41e98c + 679cd54 commit 40fb27a

15 files changed

+1049
-4
lines changed

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ RUN cd /app && python3 -m pip install poetry==1.1.13 pipenv==2022.6.7
1010

1111
# Install this project dependencies
1212
COPY . /app
13-
RUN cd /app && python3 -m pip install -e .
13+
RUN cd /app && python3 -m pip install -e .[github]
1414

1515
ENV LC_ALL=C.UTF-8
1616
ENV LANG=C.UTF-8

action.yml

+14
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ inputs:
66
description: 'PyUp.io API key'
77
required: false
88
default: ''
9+
create-pr:
10+
description: 'Create a PR if Safety finds any vulnerabilities. Only the `file` scan mode is currently supported - combine with Cron based actions to get automatic notifications of new vulnerabilities.'
11+
required: false
12+
default: ''
13+
create-issue:
14+
description: 'Create an issue if Safety finds any vulnerabilities. Only the `file` scan mode is currently supported - combine with Cron based actions to get automatic notifications of new vulnerabilities.'
15+
required: false
16+
default: ''
917
scan:
1018
description: 'Scan mode to use. One of auto / docker / env / file (defaults to auto)'
1119
required: false
@@ -30,6 +38,9 @@ inputs:
3038
description: '[Advanced] Any additional arguments to pass to Safety'
3139
required: false
3240
default: ''
41+
repo-token:
42+
required: false
43+
default: ''
3344

3445
outputs:
3546
cli-output:
@@ -43,13 +54,16 @@ runs:
4354
env:
4455
SAFETY_API_KEY: ${{ inputs.api-key }}
4556
SAFETY_ACTION: true
57+
SAFETY_ACTION_CREATE_PR: ${{ inputs.create-pr }}
58+
SAFETY_ACTION_CREATE_ISSUE: ${{ inputs.create-issue }}
4659
SAFETY_ACTION_SCAN: ${{ inputs.scan }}
4760
SAFETY_ACTION_DOCKER_IMAGE: ${{ inputs.docker-image }}
4861
SAFETY_ACTION_REQUIREMENTS: ${{ inputs.requirements }}
4962
SAFETY_ACTION_CONTINUE_ON_ERROR: ${{ inputs.continue-on-error }}
5063
SAFETY_ACTION_OUTPUT_FORMAT: ${{ inputs.output-format }}
5164
SAFETY_ACTION_ARGS: ${{ inputs.args }}
5265
SAFETY_ACTION_FORMAT: true
66+
GITHUB_TOKEN: ${{ inputs.repo-token }}
5367
COLUMNS: 120
5468

5569
branding:

entrypoint.sh

+37
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,43 @@ if [ "${SAFETY_ACTION_SCAN}" = "auto" ]; then
6565
fi
6666
fi
6767

68+
# remediation mode
69+
if [ "${SAFETY_ACTION_CREATE_PR}" = "true" ] && [ "${SAFETY_ACTION_CREATE_ISSUE}" = "true" ]; then
70+
echo "[Safety Action] Can only create issues or PRs, not both."
71+
exit 1
72+
fi
73+
74+
if [ "${SAFETY_ACTION_CREATE_PR}" = "true" ] || [ "${SAFETY_ACTION_CREATE_ISSUE}" = "true" ]; then
75+
if [ "${SAFETY_ACTION_SCAN}" != "file" ]; then
76+
echo "[Safety Action] Creating PRs / issues is only supported when scanning a requirements file."
77+
exit 1
78+
fi
79+
80+
# TODO: Add info to env vars for telemetry...
81+
82+
# Build up a list of requirements files, or use SAFETY_ACTION_REQUIREMENTS if that's set.
83+
# This will be moved into Safety proper in the future.
84+
requirement_files=()
85+
if [ -z "${SAFETY_ACTION_REQUIREMENTS}" ]; then
86+
readarray -d '' matches < <(find . -type f -name requirements.txt -print0)
87+
for match in ${matches[@]}; do
88+
requirement_files+=("-r" "${match}")
89+
done
90+
else
91+
requirement_files=("-r" "${SAFETY_ACTION_REQUIREMENTS}")
92+
fi
93+
94+
alert_action="github-pr"
95+
if [ "${SAFETY_ACTION_CREATE_ISSUE}" = "true" ]; then
96+
alert_action="github-issue"
97+
fi
98+
99+
# Continue on error is set because we're using Safety's output here for further processing.
100+
python -m safety check "${requirement_files[@]}" --continue-on-error --output=json ${SAFETY_ACTION_ARGS} | python -m safety alert "${alert_action}" --repo "${GITHUB_REPOSITORY}" --token "${GITHUB_TOKEN}" --base-url "${GITHUB_API_URL}"
101+
102+
exit 0
103+
fi
104+
68105
if [ "${SAFETY_ACTION_SCAN}" = "docker" ]; then
69106
if [[ "${SAFETY_ACTION_DOCKER_IMAGE}" == "" ]]; then
70107
SAFETY_OS_DESCRIPTION="${SAFETY_OS_DESCRIPTION} docker_image_scan"

safety/alerts/__init__.py

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import sys
2+
import json
3+
from typing import Any
4+
import click
5+
6+
from dataclasses import dataclass
7+
8+
from . import github
9+
from safety.util import SafetyPolicyFile
10+
11+
@dataclass
12+
class Alert:
13+
report: Any
14+
key: str
15+
policy: Any = None
16+
requirements_files: Any = None
17+
18+
@click.group(help="Send alerts based on the results of a Safety scan.")
19+
@click.option('--check-report', help='JSON output of Safety Check to work with.', type=click.File('r'), default=sys.stdin)
20+
@click.option("--policy-file", type=SafetyPolicyFile(), default='.safety-policy.yml',
21+
help="Define the policy file to be used")
22+
@click.option("--key", envvar="SAFETY_API_KEY",
23+
help="API Key for pyup.io's vulnerability database. Can be set as SAFETY_API_KEY "
24+
"environment variable.", required=True)
25+
@click.pass_context
26+
def alert(ctx, check_report, policy_file, key):
27+
with check_report:
28+
# TODO: This breaks --help for subcommands
29+
try:
30+
safety_report = json.load(check_report)
31+
except json.decoder.JSONDecodeError as e:
32+
click.secho("Error decoding input JSON: {}".format(e.msg), fg='red')
33+
sys.exit(1)
34+
35+
if not 'report_meta' in safety_report:
36+
click.secho("You must pass in a valid Safety Check JSON report", fg='red')
37+
sys.exit(1)
38+
39+
ctx.obj = Alert(report=safety_report, policy=policy_file if policy_file else {}, key=key)
40+
41+
alert.add_command(github.github_pr)
42+
alert.add_command(github.github_issue)

0 commit comments

Comments
 (0)