Skip to content

Commit

Permalink
feat: improve CLI and CI/CD integration in GitHub Actions and Drone CI
Browse files Browse the repository at this point in the history
  • Loading branch information
pandatix committed Apr 15, 2024
1 parent f272ed9 commit 73c110d
Show file tree
Hide file tree
Showing 10 changed files with 481 additions and 197 deletions.
82 changes: 82 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,85 @@
<a href="https://github.com/ctfer-io/ctfd-setup/actions/workflows/codeql-analysis.yaml"><img src="https://img.shields.io/github/actions/workflow/status/ctfer-io/ctfd-setup/codeql-analysis.yaml?style=for-the-badge&label=CodeQL" alt="CodeQL"></a>
<a href="https://securityscorecards.dev/viewer/?uri=github.com/ctfer-io/ctfd-setup"><img src="https://img.shields.io/ossf-scorecard/github.com/ctfer-io/ctfd-setup?label=openssf%20scorecard&style=for-the-badge" alt="OpenSSF Scoreboard"></a>
</div>

CTFd does not have the concept of **configuration file**, leading to **deployment complications** and the **impossibility to version configurations**.
This is problematic for reproducibility or sharing configuration for debugging or replicating a CTF infrastructure.

Moreover, the setup API does not exist, so we had to map it to what the frontend calls in [go-ctfd](https://github.com/ctfer-io/go-ctfd/blob/main/api/setup.go).

To fit those gaps, we built `ctfd-setup` on top of the CTFd API. This utility helps setup a CTFd instance from a YAML configuration file, CLI flags and environment variables.
Thanks to this, you can integrate it using **GitHub Actions**, **Drone CI** or even as part of your **IaC provisionning**.

<!--TODO improve CI + CD support description-->

## How to use

<div align="center">
<img src="res/how-to-use.excalidraw.png" alt="ctfd-setup utility used in GitHub Actions, Drone CI and Docker and Kubernetes initial container" width="800px">
</div>

For the CLI configuration, please refer to the binary's specific API through `ctfd-setup --help`.
In use of IaC provisionning scenario, the corresponding environment variables are also mapped to the output, so please refer to it.

### GitHub Actions

To improve our own workflows and share knownledges and tooling, we built a GitHub Action: `ctfer-io/ctfd-setup`.
You can use it given the following example.

```yaml
name: 'My workflow'

on:
push:
branches:
- 'main'

jobs:
my-job:
runs-on: 'ubuntu-latest'
steps:
- name: 'Setup CTFd'
uses: 'ctfer-io/ctfd-setup@v0'
with:
url: ${{ secrets.CTFD_URL }}
global_name: 'My CTF'
global_description: 'My CTF description'
admin_name: ${{ secrets.ADMIN_USERNAME }}
admin_email: ${{ secrets.ADMIN_EMAIL }}
admin_password: ${{ secrets.ADMIN_PASSWORD }}
# ... and so on (non-mandatory attributes)
```

### Drone CI

This could also be used as part of a Drone CI use `ctferio/ctfd-setup`.

```yaml
kind: pipeline
type: docker
name: 'My pipeline'

trigger:
branch:
- main
event:
- push

steps:
# ...

- name: 'Setup CTFd'
image: 'ctferio/ctfd-setup@v0'
settings:
url:
from_secret: CTFD_URL
global_name: 'My CTF'
global_description: 'My CTF description'
admin_name:
from_secret: ADMIN_USERNAME
admin_email:
from_secret: ADMIN_EMAIL
admin_password:
from_secret: ADMIN_PASSWORD
# ... and so on (non-mandatory attributes)
```
64 changes: 61 additions & 3 deletions action.yaml
Original file line number Diff line number Diff line change
@@ -1,18 +1,76 @@
name: 'CTFd-Setup'
author: 'ctfer-io'
description: 'Setup a CTFd from a versionned configuration file'
description: 'Setup a CTFd from a versionned configuration file.'

inputs:
file:
description: 'Configuration file to use for setting up CTFd. If let empty, will default the values and look for secrets in expected environment variables. For more info, refers to the documentation.'
required: false
default: '.ctfd.yaml'
url:
description: 'URL to reach the CTFd instance.'
required: true
admin_email:
description: 'The administrator email address.'
required: true
admin_name:
description: 'The administrator name.'
required: true
admin_password:
description: 'The administrator password.'
required: true
front_banner:
description: 'The frontend banner. Provide a path to a locally-accessible file.'
front_logo:
description: 'The frontend logo. Provide a path to a locally-accessible file.'
front_small_icon:
description: 'The frontend small icon. Provide a path to a locally-accessible file.'
front_theme:
description: 'The frontend theme name.'
default: 'core'
front_theme_color:
description: 'The frontend theme color.'
global_description:
description: 'The description of your CTF, displayed as is.'
global_mode:
description: 'The mode of your CTFd, either users or teams.'
default: 'users'
global_name:
description: 'The name of your CTF, displayed as is.'
required: true
global_team_size:
description: 'The team size you want to enforce. Works only if global_mode is "teams".'
visibilities_account:
description: 'The visibility for the accounts. Please refer to CTFd documentation (https://docs.ctfd.io/docs/settings/visibility-settings/).'
default: 'public'
visibilities_challenge:
description: 'The visibility for the challenges. Please refer to CTFd documentation (https://docs.ctfd.io/docs/settings/visibility-settings/).'
default: 'public'
visibilities_registration:
description: 'The visibility for the registration. Please refer to CTFd documentation (https://docs.ctfd.io/docs/settings/visibility-settings/).'
default: 'public'
visibilities_score:
description: 'The visibility for the scoreboard. Please refer to CTFd documentation (https://docs.ctfd.io/docs/settings/visibility-settings/).'
default: 'public'

runs:
using: 'docker'
image: 'Dockerfile'
env:
FILE: ${{ inputs.file }}
CTFD_URL: ${{ inputs.url }}
URL: ${{ inputs.url }}
ADMIN_EMAIL: ${{ inputs.admin_email }}
ADMIN_NAME: ${{ inputs.admin_name }}
ADMIN_PASSWORD: ${{ inputs.admin_password }}
FRONT_BANNER: ${{ inputs.front_banner }}
FRONT_LOGO: ${{ inputs.front_logo }}
FRONT_SMALL_ICON: ${{ inputs.front_small_icon }}
FRONT_THEME: ${{ inputs.front_theme }}
FRONT_THEME_COLOR: ${{ inputs.front_theme_color }}
GLOBAL_DESCRIPTION: ${{ inputs.global_description }}
GLOBAL_MODE: ${{ inputs.global_mode }}
GLOBAL_NAME: ${{ inputs.global_name }}
GLOBAL_TEAM_SIZE: ${{ inputs.global_team_size }}
VISIBILITIES_ACCOUNT: ${{ inputs.visibilities_account }}
VISIBILITIES_CHALLENGE: ${{ inputs.visibilities_challenge }}
VISIBILITIES_REGISTRATION: ${{ inputs.visibilities_registration }}
VISIBILITIES_SCORE: ${{ inputs.visibilities_score }}
Loading

0 comments on commit 73c110d

Please sign in to comment.