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

feat: revise parameters, improve error handling and checks #51

Merged
merged 30 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
b548132
Juggle inputs
DerekRoberts Sep 19, 2023
c6579f8
Name param
DerekRoberts Sep 19, 2023
ec52760
Force deploys
DerekRoberts Sep 19, 2023
d5cb1a6
Send token
DerekRoberts Sep 20, 2023
335ae6a
Fix token permissions
DerekRoberts Sep 20, 2023
2a24fb2
Pass token to ZAP action
DerekRoberts Sep 20, 2023
cf50c07
Reorder clone before ZAP
DerekRoberts Sep 20, 2023
8bec6f0
Test
DerekRoberts Sep 20, 2023
df97432
Make ubuntu versions consistent
DerekRoberts Sep 20, 2023
1eac6d1
Trigger deploys
DerekRoberts Sep 20, 2023
1e1cc84
Enable issue writing
DerekRoberts Sep 20, 2023
d9383cb
Enable issue writing
DerekRoberts Sep 20, 2023
270058a
Enable issue writing
DerekRoberts Sep 20, 2023
4a1e917
Start deprecating penetration_test_artifact and _issue
DerekRoberts Sep 20, 2023
8e10db8
Notify and exit on deprecated params
DerekRoberts Sep 20, 2023
15dc801
Bracket spacing
DerekRoberts Sep 20, 2023
edd095b
Stop on error
DerekRoberts Sep 20, 2023
2dea5d3
Testing
DerekRoberts Sep 20, 2023
d6dcf46
Conditional for URL_HOST_PATH
DerekRoberts Sep 20, 2023
b7d15e7
Conditional for URL_HOST_PATH
DerekRoberts Sep 20, 2023
3f79616
Clean up URL handling
DerekRoberts Sep 20, 2023
d731a7f
Clean up URL handling
DerekRoberts Sep 20, 2023
513b495
Allow disabling of ZAP issues
DerekRoberts Sep 20, 2023
80ef889
Improve conditionals
DerekRoberts Sep 20, 2023
8eddb07
Change equals
DerekRoberts Sep 20, 2023
239602b
Still tweaking
DerekRoberts Sep 20, 2023
f4c62fc
Triggers
DerekRoberts Sep 20, 2023
b599a3f
Less specific permissions
DerekRoberts Sep 21, 2023
fcbcffd
Cleanup
DerekRoberts Sep 21, 2023
28d1f58
Readme
DerekRoberts Sep 21, 2023
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 .github/workflows/pr-closed.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
# Clean up OpenShift when PR closed, no conditions
cleanup-openshift:
name: Cleanup OpenShift
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- name: Remove OpenShift artifacts
run: |
Expand Down
10 changes: 4 additions & 6 deletions .github/workflows/pr-open.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ jobs:
deploys:
name: Deploys
runs-on: ubuntu-latest
permissions:
packages: read
strategy:
matrix:
name: [database, backend, frontend]
Expand All @@ -27,20 +25,20 @@ jobs:
file: backend/openshift.deploy.yml
overwrite: true
parameters: -p MIN_REPLICAS=1 -p MAX_REPLICAS=2
triggers: ('backend/')
verification_path: /
penetration_test: true
verification_path: /api
- name: frontend
file: frontend/openshift.deploy.yml
overwrite: true
parameters: -p MIN_REPLICAS=1 -p MAX_REPLICAS=2
penetration_test: true
triggers: ('frontend/')
penetration_test: false
steps:
- uses: actions/checkout@v4
- name: Deploys
uses: ./
with:
file: ${{ matrix.file }}
name: ${{ matrix.name }}
oc_namespace: ${{ secrets.OC_NAMESPACE }}
oc_server: ${{ secrets.OC_SERVER }}
oc_token: ${{ secrets.OC_TOKEN }}
Expand Down
40 changes: 25 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,28 +36,21 @@ Testing has only been done with public containers on ghcr.io (GitHub Container R

# Overwrite objects using `oc apply` or only create with `oc create`
# Expected errors from `oc create` are handled with `set +o pipefail`
overwrite: true
overwrite: "true"


### Typical / recommended

# Name for any penetration test issues or artifacts
name: "frontend"

# Template parameters/variables to pass
parameters: -p PR_NO=${{ github.event.number }}
parameters: -p ZONE=${{ github.event.number }}

# Run a ZAProxy penetration test against any routes? [true/false]
# Requires `name` to be set if enabled/true
penetration_test: false

# Allow ZAProxy alerts to fail the workflow? [true/false]
penetration_test_fail: false

# Provide a name for ZAProxy workflow artifacts; e.g. frontend, backend
# Without this multiple package artifact names can collide
penetration_test_artifact: frontend

# Provide a name to enable ZAProxy issue creation; e.g. frontend, backend
# If the issue exists, it adds new comments to the existing issue.
penetration_test_issue: frontend

# Timeout seconds, only affects the OpenShift deployment (apply/create)
# Default = "15m"
timeout: "15m"
Expand Down Expand Up @@ -87,9 +80,26 @@ Testing has only been done with public containers on ghcr.io (GitHub Container R
# Useful for consuming other repos, defaults to the current one
repository: ${{ github.repository }}

# Create an issue for penetration test results? [true|false]
# Default = "true"
penetration_test_create_issue: "true"

# Allow ZAProxy alerts to fail the workflow? [true/false]
# Warning: annoying!
penetration_test_fail: false

# Specify GITHUB_TOKEN or Personal Access Token (PAT) for issue writing
# Defaults to inheriting from the calling workflow
penetration_test_token: ${{ github.token }}


### Deprecated / will fail and provide directions

# Replaced by `name` param
penetration_test_artifact: frontend

# # Replaced by `name` param
penetration_test_issue: frontend
```

# Example, Single Template
Expand Down Expand Up @@ -149,6 +159,7 @@ steps:
- name: Deploys
uses: bcgov-nr/action-deployer-openshift.yml@main
with:
name: ${{ matrix.name }}
file: ${{ matrix.file }}
oc_namespace: ${{ secrets.OC_NAMESPACE }}
oc_server: ${{ secrets.OC_SERVER }}
Expand All @@ -158,7 +169,6 @@ steps:
-p COMMON_TEMPLATE_VAR=whatever-${{ github.event.number }}
${{ matrix.parameters }}
penetration_test: true
penetration_test_issue: ${{ matrix.name }}
triggers: ${{ matrix.triggers }}
```

Expand All @@ -180,11 +190,11 @@ deploys:
oc_server: ${{ secrets.OC_SERVER }}
oc_token: ${{ secrets.OC_TOKEN }}
overwrite: true
verification_url: health
parameters:
-p MIN_REPLICAS=1 -p MAX_REPLICAS=2
-p PR_NUMBER=${{ github.event.number }}
triggers: ${{ matrix.triggers }}
verification_url: health
```

# Route Verification vs Penetration Testing
Expand Down
83 changes: 51 additions & 32 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,17 @@ inputs:
required: true

### Typical / recommended
name:
description: Name for any penetration test issues or artifacts; e.g. frontend
default: "name_unset"
parameters:
description: Template parameters/variables to pass (e.g. -p ZONE=...)
penetration_test:
description: Run a ZAProxy penetration test against any routes? [true|false]
default: "false"
penetration_test_fail:
description: Allow ZAProxy alerts to fail the workflow? [true|false]
default: "false"
penetration_test_artifact:
description: Provide a name to attach ZAProxy scan artifacts to workflows; e.g. frontend, backend
default: "unnamed"
penetration_test_issue:
description: Provide a name to enable ZAProxy issue creation; e.g. frontend, backend
default: ""
timeout:
description: Timeout for deployment. [default=15m]
default: "15m"
Expand All @@ -44,12 +42,6 @@ inputs:
verification_path:
description: Sets the health endpoint to be used during check stage, does not require the '/' at the begining
default: ""
verification_retry_attempts:
description: Number of times to attempt deployment verification
default: "3"
verification_retry_seconds:
description: Seconds to wait between deployment verification attempts
default: "10"

### Usually a bad idea / not recommended
diff_branch:
Expand All @@ -58,9 +50,24 @@ inputs:
repository:
description: Optionally, specify a different repo to clone
default: ${{ github.repository }}
penetration_test_create_issue:
description: Create an issue with penetration test results? [true|false]
default: "true"
penetration_test_token:
description: Specify token (GH or PAT), instead of inheriting one from the calling workflow
default: ${{ github.token }}
verification_retry_attempts:
description: Number of times to attempt deployment verification
default: "3"
verification_retry_seconds:
description: Seconds to wait between deployment verification attempts
default: "10"

### Deprecated
penetration_test_artifact:
description: Provide a name to attach ZAProxy scan artifacts to workflows; e.g. frontend, backend
penetration_test_issue:
description: Provide a name to enable ZAProxy issue creation; e.g. frontend, backend

runs:
using: composite
Expand All @@ -74,6 +81,7 @@ runs:
shell: bash
run: |
# Expand for inputs and variables
set -eu

# Bug mitigation - OpenShift hates images with capitals in org/repo names
REPO=${{ inputs.repository }}
Expand All @@ -83,27 +91,34 @@ runs:
exit 1
fi

# Deprecation notices
if [ ! -z ${{ inputs.penetration_test_artifact }} ]||[ ! -z ${{ inputs.penetration_test_issue }} ]; then
echo -e "Params penetration_test_artifact and penetration_test_issue have been deprecated. \n"
echo -e "Please use param: name instead. Exiting.\n"
exit 1
fi

# Process template, consuming variables/parameters
TEMPLATE="$(oc process -f ${{ inputs.file }} ${{ inputs.parameters }} --local)"

# ImageStream, DeploymentConfig and Route Host from template
DC=$(jq -rn "${TEMPLATE} | .items[] | select(.kind==\"DeploymentConfig\").metadata.name //empty")
IS=$(jq -rn "${TEMPLATE} | .items[] | select(.kind==\"ImageStream\").metadata.name //empty")
ROUTE_HOST=$(jq -rn "${TEMPLATE} | .items[] | select(.kind==\"Route\").spec.host //empty")

# Route path from inputs or template (inputs.verification_path takes priority)
ROUTE_PATH=${{ inputs.verification_path }}
[ ! -z "${ROUTE_PATH}" ]|| \
ROUTE_PATH=$(jq -rn "${TEMPLATE} | .items[] | select(.kind==\"Route\").spec.path //empty")

# Build URL from route and path, but only if ROUTE_HOST is populated
[ -z "${ROUTE_HOST}" ]|| URL_HOST_PATH="${ROUTE_HOST}/${ROUTE_PATH}"

echo imageStream=${IS} >> $GITHUB_OUTPUT
echo deploymentConfig=${DC} >> $GITHUB_OUTPUT

# Removes any double slashles, e.g. inputs.verification_path
echo url=${URL_HOST_PATH} | sed 's // / g' >> $GITHUB_OUTPUT
# Output URL (host + path), but only if ROUTE_HOST is populated
ROUTE_HOST=$(jq -rn "${TEMPLATE} | .items[] | select(.kind==\"Route\").spec.host //empty")
if [ ! -z ${ROUTE_HOST} ]; then
# Path from inputs takes priority over template
ROUTE_PATH=${{ inputs.verification_path }}
[ ! -z ${ROUTE_PATH} ]|| \
ROUTE_PATH=$(jq -rn "${TEMPLATE} | .items[] | select(.kind==\"Route\").spec.path //empty")

# Removes any duplicate slashes and pass to GITHUB_OUTPUT
URL_HOST_PATH="${ROUTE_HOST}/${ROUTE_PATH}"
echo url=${URL_HOST_PATH} | sed 's // / g' >> $GITHUB_OUTPUT
fi

# Triggers
TRIGGERS=${{ inputs.triggers }}
Expand All @@ -127,7 +142,7 @@ runs:
echo "Triggers not matched, deployment skipped"

- name: Deploy
if: steps.vars.outputs.triggered
if: steps.vars.outputs.triggered == 'true'
shell: bash
run: |
# Expand for deployment steps
Expand Down Expand Up @@ -160,7 +175,9 @@ runs:
[ -z "${DC}" ]|| oc rollout status dc/${DC} -w

- name: Route Verification
if: steps.vars.outputs.url && steps.vars.outputs.triggered &&( inputs.penetration_test != 'true' )
if: steps.vars.outputs.url &&
( steps.vars.outputs.triggered == 'true' )&&
( inputs.penetration_test != 'true' )
shell: bash
run: |
# Expand for route verification
Expand Down Expand Up @@ -189,16 +206,18 @@ runs:
exit 1

- name: Penetration Test
if: steps.vars.outputs.url && steps.vars.outputs.triggered &&( inputs.penetration_test == 'true' )
if: steps.vars.outputs.url &&
( steps.vars.outputs.triggered == 'true' )&&
( inputs.penetration_test == 'true' )
uses: zaproxy/[email protected]
with:
target: https://${{ steps.vars.outputs.url }}
allow_issue_writing: "${{ inputs.penetration_test_create_issue }}"
artifact_name: "zap_${{ inputs.name }}"
cmd_options: "-a"
fail_action: "${{ inputs.penetration_test_fail }}"
# allow_... is purposefully obscured - if a title is provided, then = true
allow_issue_writing: "${{ inputs.penetration_test_issue && true || false }}"
artifact_name: "zap_${{ inputs.penetration_test_artifact }}"
issue_title: "ZAP: ${{ inputs.penetration_test_issue }}"
issue_title: "ZAP: ${{ inputs.name }}"
target: https://${{ steps.vars.outputs.url }}
token: "${{ inputs.penetration_test_token }}"

# Action repo needs to be present for cleanup/tests
- name: Checkout to make sure action.yml is present (tests)
Expand Down