Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
185 changes: 185 additions & 0 deletions .github/workflows/sconify.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
name: Build, Test and Push Docker Image

on:
workflow_call:
inputs:
image-name:
description: "Name of Docker Image to Sconify"
type: string
required: true
image-tag:
description: "Tag of Docker Image to Sconify"
type: string
required: true
docker-registry:
description: "Docker Registry of Docker Image to Sconify"
default: "docker.io"
type: string
sconify-version:
description: "Version of the Sconify Image to use"
type: string
required: true
fs-dir:
type: string
description: "File System Directory to Protect"
required: true
binary:
type: string
description: "Path to the Binary to Protect"
required: true
command:
type: string
description: "Command to Protect"
required: true
heap:
type: string
default: "1G"
description: "Enclave Heap size (default 1G)"
dlopen:
type: number
default: 1
description: "dlopen mode (default 1)"
sconify-debug:
description: "Create Scone Debug image (default true)"
default: true
type: boolean
sconify-prod:
description: "Create Scone Production image (default true)"
default: true
type: boolean
docker-username:
type: string
description: "Docker Registry Username"
required: true
scontain-username:
type: string
description: "Scontain Registry Username"
required: true
secrets:
docker-password:
description: "Docker Registry Password or Token"
required: true
scontain-password:
description: "Scontain Registry Password or Token"
required: true
scone-signing-key:
description: "Signing Key for Scone Production (not required with `sconify-prod: false`)"
required: false
outputs:
debug-image:
description: "Debug Sconified Image"
value: ${{ jobs.build.outputs.debug-image }}
debug-mrenclave:
description: "Debug Sconified Image MrEnclave Fingerprint"
value: ${{ jobs.build.outputs.debug-mrenclave }}
debug-checksum:
description: "Debug Sconified Image Checksum"
value: ${{ jobs.build.outputs.debug-checksum }}
prod-image:
description: "Prod Sconified Image"
value: ${{ jobs.build.outputs.prod-image }}
prod-mrenclave:
description: "Prod Sconified Image MrEnclave Fingerprint"
value: ${{ jobs.build.outputs.prod-mrenclave }}
prod-checksum:
description: "Prod Sconified Image Checksum"
value: ${{ jobs.build.outputs.prod-checksum }}

jobs:
build:
runs-on: ubuntu-latest
env:
FROM_IMAGE: ${{ inputs.docker-registry }}/${{ inputs.image-name }}:${{ inputs.image-tag }}
DEBUG_IMAGE: ${{ inputs.docker-registry }}/${{ inputs.image-name }}:${{ inputs.image-tag }}-scone-debug-${{ inputs.sconify-version }}
PROD_IMAGE: ${{ inputs.docker-registry }}/${{ inputs.image-name }}:${{ inputs.image-tag }}-scone-prod-${{ inputs.sconify-version }}
outputs:
debug-image: ${{ steps.push-debug.outputs.image }}
debug-mrenclave: ${{ steps.push-debug.outputs.mrenclave }}
debug-checksum: ${{ steps.push-debug.outputs.checksum }}
prod-image: ${{ steps.push-prod.outputs.image }}
prod-mrenclave: ${{ steps.push-prod.outputs.mrenclave }}
prod-checksum: ${{ steps.push-prod.outputs.checksum }}
steps:
- name: Login to Docker Registry
uses: docker/login-action@v3
with:
registry: ${{ inputs.docker-registry }}
username: ${{ inputs.docker-username }}
password: ${{ secrets.docker-password }}

- name: Login to Scontain Docker Registry
uses: docker/login-action@v3
with:
registry: "registry.scontain.com"
username: ${{ inputs.scontain-username }}
password: ${{ secrets.scontain-password }}

- name: Pull Image to Sconify
run: docker pull ${{ inputs.docker-registry }}/${{ inputs.image-name }}:${{ inputs.image-tag }}

- name: Pull Sconify Image
run: docker pull registry.scontain.com/scone-production/iexec-sconify-image:${{ inputs.sconify-version }}

- name: Sconify Image Debug
if: ${{ inputs.sconify-debug }}
run: |
docker run \
--rm \
-v /var/run/docker.sock:/var/run/docker.sock \
registry.scontain.com/scone-production/iexec-sconify-image:${{ inputs.sconify-version }} \
sconify_iexec \
--from=$FROM_IMAGE \
--to=$DEBUG_IMAGE \
--binary-fs \
--fs-dir=${{ inputs.fs-dir }} \
--host-path=/etc/hosts \
--host-path=/etc/resolv.conf \
--binary=${{ inputs.binary }} \
--heap=${{ inputs.heap }} \
--dlopen=${{ inputs.dlopen }} \
--no-color \
--verbose \
--command="${{ inputs.command }}"

Choose a reason for hiding this comment

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

shouldn't we use a script that would be more cleaner for code readability ?

Suggested change
docker run \
--rm \
-v /var/run/docker.sock:/var/run/docker.sock \
registry.scontain.com/scone-production/iexec-sconify-image:${{ inputs.sconify-version }} \
sconify_iexec \
--from=$FROM_IMAGE \
--to=$DEBUG_IMAGE \
--binary-fs \
--fs-dir=${{ inputs.fs-dir }} \
--host-path=/etc/hosts \
--host-path=/etc/resolv.conf \
--binary=${{ inputs.binary }} \
--heap=${{ inputs.heap }} \
--dlopen=${{ inputs.dlopen }} \
--no-color \
--verbose \
--command="${{ inputs.command }}"
./sconify.sh arg1 arg2 arg3

Copy link
Member Author

Choose a reason for hiding this comment

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

We need to pass a lot of input to the command. IMO, moving the command in a script would add extra complexity and no better readability.

Copy link
Member Author

Choose a reason for hiding this comment

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

the command is now prepared in a previous step (still in this file)


- name: Push Debug Image
if: ${{ inputs.sconify-debug }}
id: push-debug
run: |
docker push $DEBUG_IMAGE
echo "image=$DEBUG_IMAGE" >> "$GITHUB_OUTPUT"
echo "checksum=0x$(docker image inspect $DEBUG_IMAGE | jq .[0].RepoDigests[0] | sed 's/"//g' | awk -F '@sha256:' '{print $2}')" >> "$GITHUB_OUTPUT"
echo "mrenclave=$(docker run --rm -e SCONE_HASH=1 $DEBUG_IMAGE)" >> "$GITHUB_OUTPUT"

- name: Sconify Image Prod
if: ${{ inputs.sconify-prod }}
run: |
mkdir -p $HOME/sig
echo "${{ secrets.scone-signing-key }}" > $HOME/sig/enclave-key.pem
docker run \
--rm \
-v /var/run/docker.sock:/var/run/docker.sock \
-v $HOME/sig/enclave-key.pem:/sig/enclave-key.pem \
registry.scontain.com/scone-production/iexec-sconify-image:${{ inputs.sconify-version }} \
sconify_iexec \
--from=$FROM_IMAGE \
--to=$PROD_IMAGE \
--binary-fs \
--fs-dir=${{ inputs.fs-dir }} \
--host-path=/etc/hosts \
--host-path=/etc/resolv.conf \
--binary=${{ inputs.binary }} \
--heap=${{ inputs.heap }} \
--dlopen=${{ inputs.dlopen }} \
--no-color \
--verbose \
--command="${{ inputs.command }}" \
--scone-signer=/sig/enclave-key.pem

- name: Push Prod Image
if: ${{ inputs.sconify-prod }}
id: push-prod
run: |
docker push $PROD_IMAGE
echo "image=$PROD_IMAGE" >> "$GITHUB_OUTPUT"
echo "checksum=0x$(docker image inspect $PROD_IMAGE | jq .[0].RepoDigests[0] | sed 's/"//g' | awk -F '@sha256:' '{print $2}')" >> "$GITHUB_OUTPUT"
echo "mrenclave=$(docker run --rm -e SCONE_HASH=1 $PROD_IMAGE)" >> "$GITHUB_OUTPUT"
140 changes: 140 additions & 0 deletions sconify/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# Sconify - Reusable Workflow Documentation 🚀

## Overview 🌟

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.

The workflow performs the following actions:

- **Login to Docker Registry**
- **Login to Scontain Docker Registry**
- **Pull Image to Sconify** from Docker Registry
- **Pull Sconify Image** from Scontain Docker Registry
- [unless input `sconify-debug: false`]
- **Sconify Image Debug**
- **Push Debug Image** to Docker Registry and prepare outputs (`debug-image`,`debug-mrenclave`,`debug-checksum`)
- [unless input `sconify-prod: false`]
- **Sconify Image Prod**
- **Push Prod Image** to Docker Registry and prepare outputs (`prod-image`,`prod-mrenclave`,`prod-checksum`)

## Workflow Inputs 🛠️

| **Input** | **Description** | **Required** | **Default** |
| --------------------- | ------------------------------------------ | ------------ | ----------- |
| **docker-username** | Docker Registry Username | Yes | - |
| **scontain-username** | Scontain Registry Username | Yes | - |
| **image-name** | Name of Docker Image to Sconify | Yes | - |
| **image-tag** | Tag of Docker Image to Sconify | Yes | - |
| **docker-registry** | Docker Registry of Docker Image to Sconify | No | docker.io |
| **sconify-version** | Version of the Sconify Image to use | Yes | - |
| **fs-dir** | File System Directory to Protect | Yes | - |
| **binary** | Path to the Binary to Protect | Yes | - |
| **command** | Command to Protect | Yes | - |
| **heap** | Enclave Heap size | No | 1G |
| **dlopen** | dlopen mode | No | 1 |
| **sconify-debug** | Create Scone Debug image | No | true |
| **sconify-prod** | Create Scone Production image | No | true |

### Secrets 🔐

| **Secret** | **Description** | **Required** |
| --------------------- | ----------------------------------------------- | --------------------------------------- |
| **docker-password** | Docker Registry Password or Token | Yes |
| **scontain-password** | Scontain Registry Password or Token | Yes |
| **scone-signing-key** | Signing Key for Scone Production (PEM RSA-3072) | Yes unless `inputs.sconify-prod: false` |

### Outputs 📤

| **Output** | **Description** |
| ------------------- | ---------------------------------------------------------------------------------- |
| **debug-image** | Debug Sconified Image (unless `inputs.sconify-debug: false`) |
| **debug-mrenclave** | Debug Sconified Image MrEnclave Fingerprint (unless `inputs.sconify-debug: false`) |
| **debug-checksum** | Debug Sconified Image Checksum (unless `inputs.sconify-debug: false`) |
| **prod-image** | Prod Sconified Image (unless `inputs.sconify-prod: false`) |
| **prod-mrenclave** | Prod Sconified Image MrEnclave Fingerprint (unless `inputs.sconify-prod: false`) |
| **prod-checksum** | Prod Sconified Image Checksum (unless `inputs.sconify-prod: false`) |

## How to Use This Reusable Workflow 🔄

1. **Save the Workflow File**
This workflow is already saved as `.github/workflows/sconify.yml` in the repository. 💾

2. **Call the Reusable Workflow**
In another workflow file (e.g., triggered manually or by a release), invoke this reusable workflow like so:

```yaml
name: Sconify iApp

on:
workflow_dispatch:
inputs:
image-name:
required: true
type: string
image-tag:
required: true
type: string
sconify-debug:
type: boolean
default: true
sconify-prod:
type: boolean
default: true

jobs:
sconify:
uses: iExecBlockchainComputing/github-actions-workflows/.github/workflows/[email protected]
Copy link
Member Author

Choose a reason for hiding this comment

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

NB: sconify-v1.0.0 tag does not exist yet, use feat/sconify instead to test from this branch

with:
image-name: ${{ inputs.image-name }}
image-tag: ${{ inputs.image-tag }}
sconify-debug: ${{ inputs.sconify-debug }}
sconify-prod: ${{ inputs.sconify-prod }}
docker-registry: docker.io
sconify-version: 5.9.0-v15
fs-dir: /app
binary: /usr/local/bin/node
command: node /app/src/app.js
heap: 1G
dlopen: 1
docker-username: ${{ vars.DOCKER_USERNAME }}
scontain-username: ${{ vars.SCONTAIN_USERNAME }}
secrets:
docker-password: ${{ secrets.DOCKER_TOKEN }}
scontain-password: ${{ secrets.SCONTAIN_TOKEN }}
scone-signing-key: ${{ secrets.SCONE_SIGNING_KEY }}

use-sconify-output:
# usually you want to deploy the sconified image as an iExec app using the sconify job outputs
runs-on: ubuntu-latest
needs: sconify
steps:
- run: |
echo "DEBUG IMAGE INFO: image=${{ needs.sconify.outputs.debug-image }} | checksum=${{ needs.sconify.outputs.debug-checksum }} | mrenclave=${{ needs.sconify.outputs.debug-mrenclave }}"
echo "PROD IMAGE INFO: image=${{ needs.sconify.outputs.prod-image }} | checksum=${{ needs.sconify.outputs.prod-checksum }} | mrenclave=${{ needs.sconify.outputs.prod-mrenclave }}"
```

3. **Configure Variables**
Ensure that the following variables are added to your repository's settings:

- `DOCKER_USERNAME`: Your Docker Registry username
- `SCONTAIN_USERNAME`: Your Scontain username

NB: Beware if you choose to use secrets to store registries usernames;
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:

> Skip output 'prod-image' since it may contain secret.

> Skip output 'debug-image' since it may contain secret.

4. **Configure Secrets**
Ensure that the following secrets are added to your repository's settings:
- `DOCKER_PASSWORD`: Your Docker Registry password or access token
- `SCONTAIN_PASSWORD`: Your Scontain password or access token
- `SCONE_SIGNING_KEY`: The key to use for signing Scone Prod applications

## Prerequisites 📋

1. **Read/Write access to the image to sconify**

2. **Read access to Scontain's `iexec-sconify-image` image**:
- You must have a Scontain account with access to the `scone-production/iexec-sconify-image` image.