-
Notifications
You must be signed in to change notification settings - Fork 68
Expand file tree
/
Copy pathaction.yml
More file actions
123 lines (108 loc) · 5.28 KB
/
action.yml
File metadata and controls
123 lines (108 loc) · 5.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
name: Upload Artifacts to Firebase previews
author: 'Angular'
description: |
Action that downloads a named artifact from a GitHub workflow and uploads
it to a Firebase preview channel. The deployment to Firebase happens through
a separate upload artifact workflow to avoid executing build processes in
privileged environments.
Following best-practices from:
https://securitylab.github.com/research/github-actions-preventing-pwn-requests
# NOTE: There are two categories of input data to this action:
#
# - TRUSTED: Values for such inputs should not be changeable by third-parties.
# This is information usually hard-coded in the privileged job running from `main`.
#
# - RISK: These inputs are considered unsafe and values may be abused by third-parties.
# This is usually information coming directly from the build job portion.
inputs:
github-token:
required: true
description: |
TRUSTED: GitHub Token used for creating the comment and fetching
the artifact.
workflow-artifact-name:
required: true
description: |
TRUSTED: Name of the artifact that should be deployed. A workflow may contain
multiple artifacts but only a single one can be picked for deployment.
firebase-config-dir:
default: './'
description: |
TRUSTED: Project-relative path to the directory containing the `firebase.json` file.
firebase-public-dir:
required: true
description: |
TRUSTED: Project-relative path to the directory where artifacts should be put into.
firebase-project-id:
required: true
description: |
TRUSTED: ID of the Firebase project used for deployment.
firebase-service-key:
required: true
description: |
TRUSTED: Contents of a Firebase service key authorizing the deployment.
outputs:
url:
description: 'The base url of the preview deployed to firebase'
value: ${{ steps.deploy.outputs.details_url }}
runs:
using: composite
steps:
- name: 'Download artifact from build job'
shell: bash
run: |
node ${{github.action_path}}/fetch-workflow-artifact.js \
'${{github.event.workflow_run.id}}' '${{inputs.workflow-artifact-name}}' > unsafe-artifact.zip
env:
GITHUB_TOKEN: '${{inputs.github-token}}'
# RISK: The downloaded `unsafe-artifact` is of input category `RISK`.
- name: Extracting workflow artifact into Firebase public directory.
shell: bash
run: |
set -euo pipefail
extractDir="$RUNNER_TEMP/artifact-unpack"
publicDir='${{inputs.firebase-public-dir}}'
mkdir -p "$publicDir"
mkdir -p "$extractDir"
unzip unsafe-artifact.zip -d "$extractDir"
tar -xvzf "$extractDir/deploy-artifact.tar.gz" -C "$publicDir"
# Defense-in-depth: fail the deploy if the extracted artifact contains
# symlinks. The artifact is attacker-influenced (PR-supplied build
# output); a symlink such as `public/leak -> /proc/self/environ` or
# `public/leak -> ~/.config/gcloud/application_default_credentials.json`
# would otherwise be followed by downstream tooling that walks
# `firebase-public-dir` and reads each entry, ending up on the
# public Firebase Hosting CDN. There is no legitimate reason for a
# `public` artifact destined for static hosting to contain
# symlinks, so refusing them outright is the safest default.
# See https://securitylab.github.com/research/github-actions-preventing-pwn-requests/.
symlinks=$(find "$publicDir" -type l 2>/dev/null || true)
if [ -n "$symlinks" ]; then
echo "::error title=Symlinks rejected in artifact::The deploy artifact contains symlinks, which are not permitted in a Hosting public directory for security reasons (a symlink can leak the contents of files outside the source tree onto the public Firebase Hosting CDN)."
echo "Symlinks found:"
echo "$symlinks"
exit 1
fi
- name: Extracting artifact metadata
id: artifact-info
shell: bash
run: node ${{github.action_path}}/extract-artifact-metadata.js '${{inputs.firebase-public-dir}}'
- uses: FirebaseExtended/action-hosting-deploy@e2eda2e106cfa35cdbcf4ac9ddaf6c4756df2c8c # v0
id: deploy
with:
# Note: No token used here as the action otherwise may attempt to post a
# comment. We use our own sticky non-spam comments below.
repoToken: ''
firebaseServiceAccount: '${{inputs.firebase-service-key}}'
expires: 10d
projectId: '${{inputs.firebase-project-id}}'
entryPoint: '${{inputs.firebase-config-dir}}'
channelId: pr-${{github.repository}}-${{steps.artifact-info.outputs.unsafe-pull-number}}-${{inputs.workflow-artifact-name}}
- uses: marocchino/sticky-pull-request-comment@0ea0beb66eb9baf113663a64ec522f60e49231c0 # v3.0.4
with:
header: ${{inputs.workflow-artifact-name}}
message: |
Deployed ${{inputs.workflow-artifact-name}} for ${{steps.artifact-info.outputs.unsafe-build-revision}} to: ${{steps.deploy.outputs.details_url}}
_**Note**: As new commits are pushed to this pull request, this link is updated after the preview is rebuilt._
number: ${{steps.artifact-info.outputs.unsafe-pull-number}}
GITHUB_TOKEN: '${{inputs.github-token}}'