Skip to content

Commit 2ad461c

Browse files
feat(sconify): add sconify workflow (#66)
1 parent 298adeb commit 2ad461c

File tree

2 files changed

+381
-0
lines changed

2 files changed

+381
-0
lines changed

.github/workflows/sconify.yml

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
name: Build, Test and Push Docker Image
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
docker-registry:
7+
description: "Docker registry of docker image to sconify"
8+
default: "docker.io"
9+
type: string
10+
docker-username:
11+
description: "Docker registry username"
12+
type: string
13+
required: true
14+
image-name:
15+
description: "Name of docker image to sconify"
16+
type: string
17+
required: true
18+
image-tag:
19+
description: "Tag of docker image to sconify"
20+
type: string
21+
required: true
22+
scontain-username:
23+
description: "Scontain registry username"
24+
type: string
25+
required: true
26+
sconify-version:
27+
description: "Version of the sconify image to use"
28+
type: string
29+
required: true
30+
binary:
31+
description: "Path of the binary to use"
32+
type: string
33+
required: true
34+
command:
35+
description: "Command to execute (default: ENTRYPOINT + CMD of native image)"
36+
type: string
37+
binary-fs:
38+
description: "Embed the file system into the binary via Scone binary file system (default: false)"
39+
type: boolean
40+
default: false
41+
fs-dir:
42+
description: "Path of directories to add to the binary file system (use multiline to add multiple directories)"
43+
type: string
44+
fs-file:
45+
description: "Path of files to add to the binary file system (use multiline to add multiple files)"
46+
type: string
47+
host-path:
48+
description: "Host path, served directly from the host file system (use multiline to add multiple path)"
49+
type: string
50+
heap:
51+
description: "Enclave heap size (default 1G)"
52+
type: string
53+
default: "1G"
54+
mprotect:
55+
description: "Scone mprotect mode (0:disable; 1:enable; default 0)"
56+
type: number
57+
default: 0
58+
dlopen:
59+
description: "Scone dlopen mode (0:disable; 1:enable; default 0)"
60+
type: number
61+
default: 0
62+
sconify-debug:
63+
description: "Create Scone debug image (default true)"
64+
type: boolean
65+
default: true
66+
sconify-prod:
67+
description: "Create Scone production image (default true)"
68+
type: boolean
69+
default: true
70+
runner:
71+
description: "Runner to use (overrides `runs-on`) ⚠️ the specified runner must feature Ubuntu OS and docker CE"
72+
type: string
73+
default: "ubuntu-latest"
74+
secrets:
75+
docker-password:
76+
description: "Docker Registry Password or Token"
77+
required: true
78+
scontain-password:
79+
description: "Scontain Registry Password or Token"
80+
required: true
81+
scone-signing-key:
82+
description: "Signing Key for Scone Production (not required with `sconify-prod: false`)"
83+
required: false
84+
outputs:
85+
debug-image:
86+
description: "Debug Sconified Image"
87+
value: ${{ jobs.build.outputs.debug-image }}
88+
debug-mrenclave:
89+
description: "Debug Sconified Image MrEnclave Fingerprint"
90+
value: ${{ jobs.build.outputs.debug-mrenclave }}
91+
debug-checksum:
92+
description: "Debug Sconified Image Checksum"
93+
value: ${{ jobs.build.outputs.debug-checksum }}
94+
prod-image:
95+
description: "Prod Sconified Image"
96+
value: ${{ jobs.build.outputs.prod-image }}
97+
prod-mrenclave:
98+
description: "Prod Sconified Image MrEnclave Fingerprint"
99+
value: ${{ jobs.build.outputs.prod-mrenclave }}
100+
prod-checksum:
101+
description: "Prod Sconified Image Checksum"
102+
value: ${{ jobs.build.outputs.prod-checksum }}
103+
104+
jobs:
105+
build:
106+
runs-on: ${{ inputs.runner }}
107+
outputs:
108+
debug-image: ${{ steps.push-debug.outputs.image }}
109+
debug-mrenclave: ${{ steps.push-debug.outputs.mrenclave }}
110+
debug-checksum: ${{ steps.push-debug.outputs.checksum }}
111+
prod-image: ${{ steps.push-prod.outputs.image }}
112+
prod-mrenclave: ${{ steps.push-prod.outputs.mrenclave }}
113+
prod-checksum: ${{ steps.push-prod.outputs.checksum }}
114+
steps:
115+
- name: Create Temporary Directory
116+
run: mkdir -p ${{github.workspace}}/tmp
117+
118+
- name: Prepare Sconify Command
119+
id: prepare-command
120+
run: |
121+
FROM_IMAGE=${{ inputs.docker-registry }}/${{ inputs.image-name }}:${{ inputs.image-tag }}
122+
DEBUG_IMAGE=$FROM_IMAGE-scone-debug-${{ inputs.sconify-version }}
123+
echo "debug-image=$DEBUG_IMAGE"
124+
echo "debug-image=$DEBUG_IMAGE" >> "$GITHUB_OUTPUT"
125+
PROD_IMAGE=$FROM_IMAGE-scone-prod-${{ inputs.sconify-version }}
126+
echo "prod-image=$PROD_IMAGE"
127+
echo "prod-image=$PROD_IMAGE" >> "$GITHUB_OUTPUT"
128+
SCONIFY_CMD="sconify_iexec"
129+
# REQUIRED:
130+
# --from
131+
SCONIFY_CMD+=" --from=$FROM_IMAGE"
132+
# --to will be added later on
133+
# --binary
134+
SCONIFY_CMD+=" --binary=${{ inputs.binary }}"
135+
# OPTIONAL:
136+
# --command option
137+
[[ -n '${{ inputs.command }}' ]] && SCONIFY_CMD+=" --command=${{ inputs.command }}"
138+
# --host-path variadic option
139+
while IFS= read -r line; do [[ -n "$line" ]] && SCONIFY_CMD+=" --host-path=$line" ; done <<< '${{ inputs.host-path }}'
140+
# BINARY FILE SYSTEM (binary fs):
141+
# --binary-fs option
142+
if ${{ inputs.binary-fs }}; then SCONIFY_CMD+=" --binary-fs"; fi
143+
# --fs-dir variadic option
144+
while IFS= read -r line; do [[ -n "$line" ]] && SCONIFY_CMD+=" --fs-dir=$line" ; done <<< '${{ inputs.fs-dir }}'
145+
# --fs-file variadic option
146+
while IFS= read -r line; do [[ -n "$line" ]] && SCONIFY_CMD+=" --file=$line" ; done <<< '${{ inputs.fs-file }}'
147+
# SCONE ENV VARS:
148+
# --heap option
149+
[[ -n '${{ inputs.heap }}' ]] && SCONIFY_CMD+=" --heap=${{ inputs.heap }}"
150+
# --dlopen option
151+
[[ -n '${{ inputs.dlopen }}' ]] && SCONIFY_CMD+=" --dlopen=${{ inputs.dlopen }}"
152+
# --mprotect option
153+
[[ -n '${{ inputs.mprotect }}' ]] && SCONIFY_CMD+=" --mprotect=${{ inputs.mprotect }}"
154+
# DEBUG
155+
# --verbose --no-color options
156+
SCONIFY_CMD+=" --verbose --no-color"
157+
echo "sconify-base-command=$SCONIFY_CMD"
158+
echo "sconify-base-command=$SCONIFY_CMD" >> "$GITHUB_OUTPUT"
159+
160+
- name: Login to Docker Registry
161+
uses: docker/login-action@v3
162+
with:
163+
registry: ${{ inputs.docker-registry }}
164+
username: ${{ inputs.docker-username }}
165+
password: ${{ secrets.docker-password }}
166+
167+
- name: Login to Scontain Docker Registry
168+
uses: docker/login-action@v3
169+
with:
170+
registry: "registry.scontain.com"
171+
username: ${{ inputs.scontain-username }}
172+
password: ${{ secrets.scontain-password }}
173+
174+
- name: Pull Image to Sconify
175+
run: docker pull ${{ inputs.docker-registry }}/${{ inputs.image-name }}:${{ inputs.image-tag }}
176+
177+
- name: Pull Sconify Image
178+
run: docker pull registry.scontain.com/scone-production/iexec-sconify-image:${{ inputs.sconify-version }}
179+
180+
- name: Sconify Image Debug
181+
if: ${{ inputs.sconify-debug }}
182+
run: |
183+
docker run \
184+
--rm \
185+
-v /var/run/docker.sock:/var/run/docker.sock \
186+
registry.scontain.com/scone-production/iexec-sconify-image:${{ inputs.sconify-version }} \
187+
${{ steps.prepare-command.outputs.sconify-base-command }} \
188+
--to=${{ steps.prepare-command.outputs.debug-image }}
189+
190+
- name: Push Debug Image
191+
if: ${{ inputs.sconify-debug }}
192+
id: push-debug
193+
run: |
194+
docker push ${{ steps.prepare-command.outputs.debug-image }}
195+
echo "image=${{ steps.prepare-command.outputs.debug-image }}" >> "$GITHUB_OUTPUT"
196+
echo "checksum=0x$(docker image inspect ${{ steps.prepare-command.outputs.debug-image }} | jq .[0].RepoDigests[0] | sed 's/"//g' | awk -F '@sha256:' '{print $2}')" >> "$GITHUB_OUTPUT"
197+
echo "mrenclave=$(docker run --rm -e SCONE_HASH=1 ${{ steps.prepare-command.outputs.debug-image }})" >> "$GITHUB_OUTPUT"
198+
199+
- name: Sconify Image Prod
200+
if: ${{ inputs.sconify-prod }}
201+
run: |
202+
mkdir -p ${{github.workspace}}/tmp/sig
203+
echo "${{ secrets.scone-signing-key }}" > ${{github.workspace}}/tmp/sig/enclave-key.pem
204+
docker run \
205+
--rm \
206+
-v /var/run/docker.sock:/var/run/docker.sock \
207+
-v ${{github.workspace}}/tmp/sig/enclave-key.pem:/sig/enclave-key.pem \
208+
registry.scontain.com/scone-production/iexec-sconify-image:${{ inputs.sconify-version }} \
209+
${{ steps.prepare-command.outputs.sconify-base-command }} \
210+
--to=${{ steps.prepare-command.outputs.prod-image }} \
211+
--scone-signer=/sig/enclave-key.pem
212+
213+
- name: Push Prod Image
214+
if: ${{ inputs.sconify-prod }}
215+
id: push-prod
216+
run: |
217+
docker push ${{ steps.prepare-command.outputs.prod-image }}
218+
echo "image=${{ steps.prepare-command.outputs.prod-image }}" >> "$GITHUB_OUTPUT"
219+
echo "checksum=0x$(docker image inspect ${{ steps.prepare-command.outputs.prod-image }} | jq .[0].RepoDigests[0] | sed 's/"//g' | awk -F '@sha256:' '{print $2}')" >> "$GITHUB_OUTPUT"
220+
echo "mrenclave=$(docker run --rm -e SCONE_HASH=1 ${{ steps.prepare-command.outputs.prod-image }})" >> "$GITHUB_OUTPUT"
221+
222+
- name: Clean Temporary Directory
223+
if: always()
224+
run: rm -rf ${{github.workspace}}/tmp

sconify/README.md

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# Sconify - Reusable Workflow Documentation 🚀
2+
3+
## Overview 🌟
4+
5+
This reusable GitHub Actions workflow automates the process of sconifying a Docker image. It is configurable via inputs for the Sconification options and secrets for docker registries credentials and production enclave signing key.
6+
7+
The workflow performs the following actions:
8+
9+
- **Create Temporary Directory**
10+
- **Prepare Sconify Command** and args
11+
- **Login to Docker Registry**
12+
- **Login to Scontain Docker Registry**
13+
- **Pull Image to Sconify** from Docker Registry
14+
- **Pull Sconify Image** from Scontain Docker Registry
15+
- [unless input `sconify-debug: false`]
16+
- **Sconify Image Debug**
17+
- **Push Debug Image** to Docker Registry and prepare outputs (`debug-image`,`debug-mrenclave`,`debug-checksum`)
18+
- [unless input `sconify-prod: false`]
19+
- **Sconify Image Prod** using scone-signing-key stored in the Temporary Directory
20+
- **Push Prod Image** to Docker Registry and prepare outputs (`prod-image`,`prod-mrenclave`,`prod-checksum`)
21+
- **Clean Temporary Directory** always
22+
23+
## Workflow Inputs 🛠️
24+
25+
| **Input** | **Description** | **Required** | **Default** |
26+
| --------------------- | -------------------------------------------------------------------------------------------------------- | ------------ | -------------------------------- |
27+
| **docker-registry** | Docker registry of docker image to sconify | No | docker.io |
28+
| **docker-username** | Docker registry username | Yes | - |
29+
| **image-name** | Name of docker image to sconify | Yes | - |
30+
| **image-tag** | Tag of docker image to sconify | Yes | - |
31+
| **scontain-username** | Scontain registry username | Yes | - |
32+
| **sconify-version** | Version of the sconify image to use | Yes | - |
33+
| **binary** | [SCONE] Path of the binary to use | Yes | - |
34+
| **command** | [SCONE] Command to execute | No | ENTRYPOINT + CMD of native image |
35+
| **binary-fs** | [SCONE] Embed the file system into the binary via Scone binary file system | No | false |
36+
| **fs-dir** | [SCONE] Path of directories to add to the binary file system (use multiline to add multiple directories) | No | - |
37+
| **fs-file** | [SCONE] Path of files to add to the binary file system (use multiline to add multiple files) | No | - |
38+
| **host-path** | [SCONE] Host path, served directly from the host file system (use multiline to add multiple path) | No | - |
39+
| **heap** | [SCONE] Enclave heap size | No | 1G |
40+
| **dlopen** | [SCONE] Scone dlopen mode (0:disable; 1:enable) | No | 0 |
41+
| **mprotect** | [SCONE] Scone mprotect mode (0:disable; 1:enable) | No | 0 |
42+
43+
| **sconify-debug** | Create Scone debug image | No | true |
44+
| **sconify-prod** | Create Scone production image | No | true |
45+
| **runner** | Runner to use (overrides `runs-on`) ⚠️ the specified runner must feature Ubuntu OS and docker CE | No | ubuntu-latest |
46+
47+
> ℹ️ for more details about [SCONE] options see [Scone's documentation](https://sconedocs.github.io/ee_sconify_image/#all-supported-options)
48+
49+
### Secrets 🔐
50+
51+
| **Secret** | **Description** | **Required** |
52+
| --------------------- | ----------------------------------------------- | --------------------------------------- |
53+
| **docker-password** | Docker Registry Password or Token | Yes |
54+
| **scontain-password** | Scontain Registry Password or Token | Yes |
55+
| **scone-signing-key** | Signing Key for Scone Production (PEM RSA-3072) | Yes unless `inputs.sconify-prod: false` |
56+
57+
### Outputs 📤
58+
59+
| **Output** | **Description** |
60+
| ------------------- | ---------------------------------------------------------------------------------- |
61+
| **debug-image** | Debug Sconified Image (unless `inputs.sconify-debug: false`) |
62+
| **debug-mrenclave** | Debug Sconified Image MrEnclave Fingerprint (unless `inputs.sconify-debug: false`) |
63+
| **debug-checksum** | Debug Sconified Image Checksum (unless `inputs.sconify-debug: false`) |
64+
| **prod-image** | Prod Sconified Image (unless `inputs.sconify-prod: false`) |
65+
| **prod-mrenclave** | Prod Sconified Image MrEnclave Fingerprint (unless `inputs.sconify-prod: false`) |
66+
| **prod-checksum** | Prod Sconified Image Checksum (unless `inputs.sconify-prod: false`) |
67+
68+
## How to Use This Reusable Workflow 🔄
69+
70+
1. **Save the Workflow File**
71+
This workflow is already saved as `.github/workflows/sconify.yml` in the repository. 💾
72+
73+
2. **Call the Reusable Workflow**
74+
In another workflow file (e.g., triggered manually or by a release), invoke this reusable workflow like so:
75+
76+
```yaml
77+
name: Sconify iApp
78+
79+
on:
80+
workflow_dispatch:
81+
inputs:
82+
image-name:
83+
required: true
84+
type: string
85+
image-tag:
86+
required: true
87+
type: string
88+
sconify-debug:
89+
type: boolean
90+
default: true
91+
sconify-prod:
92+
type: boolean
93+
default: true
94+
95+
jobs:
96+
sconify:
97+
uses: iExecBlockchainComputing/github-actions-workflows/.github/workflows/sconify.yml@feat/sconify
98+
with:
99+
# runner: your-runner-here ⚠️ control the runner used in the workflow to match your requirements
100+
image-name: ${{ inputs.image-name }}
101+
image-tag: ${{ inputs.image-tag }}
102+
sconify-debug: ${{ inputs.sconify-debug }}
103+
sconify-prod: ${{ inputs.sconify-prod }}
104+
docker-registry: docker.io
105+
sconify-version: 5.9.0-v15
106+
binary: /usr/local/bin/node
107+
command: node /app/src/app.js
108+
host-path: |
109+
/etc/hosts
110+
/etc/resolv.conf
111+
binary-fs: true
112+
fs-dir: /app
113+
heap: 1G
114+
dlopen: 1
115+
mprotect: 1
116+
docker-username: ${{ vars.DOCKER_USERNAME }}
117+
scontain-username: ${{ vars.SCONTAIN_USERNAME }}
118+
secrets:
119+
docker-password: ${{ secrets.DOCKER_TOKEN }}
120+
scontain-password: ${{ secrets.SCONTAIN_TOKEN }}
121+
scone-signing-key: ${{ secrets.SCONE_SIGNING_KEY }}
122+
123+
use-sconify-output:
124+
# usually you want to deploy the sconified image as an iExec app using the sconify job outputs
125+
runs-on: ubuntu-latest
126+
needs: sconify
127+
steps:
128+
- run: |
129+
echo "DEBUG IMAGE INFO: image=${{ needs.sconify.outputs.debug-image }} | checksum=${{ needs.sconify.outputs.debug-checksum }} | mrenclave=${{ needs.sconify.outputs.debug-mrenclave }}"
130+
echo "PROD IMAGE INFO: image=${{ needs.sconify.outputs.prod-image }} | checksum=${{ needs.sconify.outputs.prod-checksum }} | mrenclave=${{ needs.sconify.outputs.prod-mrenclave }}"
131+
```
132+
133+
3. **Configure Variables**
134+
Ensure that the following variables are added to your repository's settings:
135+
136+
- `DOCKER_USERNAME`: Your Docker Registry username
137+
- `SCONTAIN_USERNAME`: Your Scontain username
138+
139+
NB: Beware if you choose to use secrets to store registries usernames;
140+
registries usernames can appear in sconified image names outputted as `outputs.debug-image` and `outputs.prod-image`, in such a case GitHub Actions blanks the outputs with this waring:
141+
142+
> Skip output 'prod-image' since it may contain secret.
143+
144+
> Skip output 'debug-image' since it may contain secret.
145+
146+
4. **Configure Secrets**
147+
Ensure that the following secrets are added to your repository's settings:
148+
- `DOCKER_PASSWORD`: Your Docker Registry password or access token
149+
- `SCONTAIN_PASSWORD`: Your Scontain password or access token
150+
- `SCONE_SIGNING_KEY`: The key to use for signing Scone Prod applications
151+
152+
## Prerequisites 📋
153+
154+
1. **Read/Write access to the image to sconify**
155+
156+
2. **Read access to Scontain's `iexec-sconify-image` image**:
157+
- You must have a Scontain account with access to the `scone-production/iexec-sconify-image` image.

0 commit comments

Comments
 (0)