Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ def index():
</form>
</body>
</html>
"""
"""
15 changes: 13 additions & 2 deletions ctf/new.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ def new(
typer.Option(
"--with-build",
help="If a build container is required.",
prompt="Is a build container required?",
),
] = False,
) -> None:
Expand All @@ -67,6 +66,9 @@ def new(
)
exit(code=1)

if template == Template.RUST_WEBSERVICE:
with_build_container = True

Comment on lines +69 to +71
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I guess this could be simplified by assuming true if a build.yaml.j2 file is present in the template dir. However it can be a bit awkward to check with the current codebase

if os.path.exists(
path=(
new_challenge_directory := os.path.join(
Expand Down Expand Up @@ -253,10 +255,19 @@ def new(
LOG.debug(msg=f"Wrote {p}.")

if with_build_container:
track_template = env.get_template(name=os.path.join("common", "build.yaml.j2"))
try:
track_template = env.get_template(
name=os.path.join(template, "build.yaml.j2")
)
except jinja2.TemplateNotFound:
track_template = env.get_template(
name=os.path.join("common", "build.yaml.j2")
)

render = track_template.render(
data={"name": name, "with_build": with_build_container}
)

with open(
file=(p := os.path.join(ansible_directory, "build.yaml")),
mode="w",
Expand Down
122 changes: 122 additions & 0 deletions ctf/templates/new/rust-webservice/build.yaml.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# This Ansible script is used to compile your challenge, create an archive and extract that archive on to the local host.
# This script builds a frontend using NPM and a Rust program. Change it as per your needs.
- name: "Build container"
hosts: "build-container"
vars_files:
- ../track.yaml
tasks:
- name: "Load flags"
loop: "{{ '{{ flags }}' }}"
vars:
key: "{{ '{{ (item.tags).discourse }}' }}"
value: "{{ '{{ item.flag }}' }}"
ansible.builtin.set_fact:
track_flags: "{{ '{{ track_flags | default({}) | combine({key: value}) }}' }}"

- name: Check if IPv4 address is set
ansible.builtin.debug:
msg: IPv4 address is set
when: ansible_all_ipv4_addresses | length > 0

- name: Initial System Upgrade
ansible.builtin.apt:
update_cache: true
install_recommends: false
upgrade: full

# Install the tools required to compile your code such as npm, nodejs, gcc...
- name: Install dependencies to build the track
ansible.builtin.apt:
name:
- npm
- curl
state: present

- name: Check if cargo is installed
ansible.builtin.stat:
path: /root/.cargo/bin/cargo
register: cargo_exists

- name: Download Cargo Installer
ansible.builtin.get_url:
url: https://sh.rustup.rs
dest: /tmp/sh.rustup.rs
mode: '0755'
force: true
when: not cargo_exists.stat.exists
tags:
- rust

- name: Install Cargo
when: not cargo_exists.stat.exists
ansible.builtin.command: /tmp/sh.rustup.rs -y
register: my_output
changed_when: my_output.rc != 0
tags:
- rust

- name: Copy the challenge sources
ansible.builtin.copy:
src: challenge/
dest: /tmp/{{ data.name }}
owner: root
group: root
mode: '0644'

- name: NPM install (if IPv4)
community.general.npm:
path: /tmp/{{ data.name }}/client/
environment:
NODE_OPTIONS: "--dns-result-order=ipv4first"
when: ansible_all_ipv4_addresses | length > 0

- name: NPM install (if IPv6)
community.general.npm:
path: /tmp/{{ data.name }}/client/
when: ansible_all_ipv4_addresses | length == 0

- name: Build
ansible.builtin.command:
cmd: /root/.cargo/bin/cargo build --release
chdir: /tmp/{{ data.name }}/
register: my_output
changed_when: my_output.rc != 0

- name: Create dist directory
ansible.builtin.file:
path: /tmp/dist/{{ data.name }}
state: directory
mode: '0755'

- name: Copy server binary
ansible.builtin.copy:
remote_src: true
src: /tmp/{{ data.name }}/target/release/{{ data.name }}
dest: /tmp/dist/{{ data.name }}/{{ data.name }}
owner: root
group: root
mode: '0744'

- name: Copy client
ansible.builtin.copy:
remote_src: true
src: /tmp/{{ data.name }}/dist
dest: /tmp/dist/{{ data.name }}/
owner: root
group: root
mode: '0644'

# Create a TAR archive with the compiled program
- name: Create archive of build
community.general.archive:
path: /tmp/dist/{{ data.name }}
dest: /tmp/build.tar
format: tar
mode: '0644'

# Extract the archive from the build container and save it on the local host
- name: Fetch archive
ansible.builtin.fetch:
src: /tmp/build.tar
dest: /tmp/nsec/{{ data.name }}.tar
flat: true
93 changes: 6 additions & 87 deletions ctf/templates/new/rust-webservice/deploy.yaml.j2
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This is the main ansible script to deploy the challenge.

# Example on how to run stuff on all hosts of the track
- name: "Install rust and npm"
- name: "Setup web server"
hosts: all{% if data.with_build %},!build{% endif %}
vars_files:
- ../track.yaml
Expand All @@ -23,77 +23,13 @@
install_recommends: false
upgrade: full

- name: Install build dependencies
ansible.builtin.apt:
name:
- npm
- curl
state: present

- name: Check if cargo is installed
ansible.builtin.stat:
path: /root/.cargo/bin/cargo
register: cargo_exists

- name: Download Cargo Installer
ansible.builtin.get_url:
url: https://sh.rustup.rs
dest: /tmp/sh.rustup.rs
mode: '0755'
force: true
when: not cargo_exists.stat.exists
tags:
- rust

- name: Install Cargo
when: not cargo_exists.stat.exists
ansible.builtin.command: /tmp/sh.rustup.rs -y
register: my_output
changed_when: my_output.rc != 0
tags:
- rust

- name: Copy the challenge sources
ansible.builtin.copy:
src: challenge/
dest: /tmp/{{ data.name }}
owner: root
group: root
mode: '0644'

- name: NPM install
community.general.npm:
path: /tmp/slot-machine/client/
environment:
NODE_OPTIONS: "--dns-result-order=ipv4first"

- name: Build
ansible.builtin.command:
cmd: /root/.cargo/bin/cargo build --release
chdir: /tmp/{{ data.name }}/
register: my_output
changed_when: my_output.rc != 0

- name: Copy server binary
ansible.builtin.copy:
src: /tmp/{{ data.name }}/target/release/{{ data.name }}
dest: /opt/{{ data.name }}/{{ data.name }}
owner: root
group: root
mode: '0744'

- name: Copy client
ansible.builtin.copy:
src: /tmp/{{ data.name }}/dist
dest: /opt/{{ data.name }}/dist
- name: Unarchive the content of the build
ansible.builtin.unarchive:
src: /tmp/nsec/{{ data.name }}.tar
dest: /opt/
owner: root
group: root
mode: '0644'

- name: Remove Build
ansible.builtin.file:
path: /tmp/{{ data.name }}/
state: absent
mode: '0755'

- name: Create systemd service
ansible.builtin.copy:
Expand All @@ -116,26 +52,9 @@
[Install]
WantedBy=default.target

- name: Remove curl and npm
ansible.builtin.apt:
name:
- npm
- curl
state: absent

- name: Start service
ansible.builtin.service:
name: {{ data.name }}.service
state: restarted
enabled: true
daemon_reload: true
{% if data.with_build %}
# When using a build container, the unarchive module can be used to install the content on the remote.
- name: Unarchive the content of the build
ansible.builtin.unarchive:
src: /tmp/build.tar
dest: /tmp/
owner: root
group: root
mode: '0755'
{% endif %}