Skip to content

Commit 9d01a0d

Browse files
authored
Merge pull request #17 from nsec/initialize-repository-16
Implemented the CTF folder initialize command.
2 parents 19edcd6 + 431f886 commit 9d01a0d

File tree

9 files changed

+225
-10
lines changed

9 files changed

+225
-10
lines changed

.deploy/track.yaml

Lines changed: 0 additions & 1 deletion
This file was deleted.

ctf/__init__.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ def find_ctf_root_directory() -> str:
7171
while path != (path := os.path.dirname(p=path)):
7272
dir = os.listdir(path=path)
7373

74-
if ".git" not in dir:
75-
continue
7674
if ".deploy" not in dir:
7775
continue
7876
if "challenges" not in dir:
@@ -82,7 +80,7 @@ def find_ctf_root_directory() -> str:
8280
if path == "/":
8381
if "CTF_ROOT_DIR" not in os.environ:
8482
LOG.critical(
85-
msg='Could not automatically find the root directory nor the "CTF_ROOT_DIR" environment variable.'
83+
msg='Could not automatically find the root directory nor the "CTF_ROOT_DIR" environment variable. To initialize a new root directory, use `ctf init [path]`'
8684
)
8785
exit(1)
8886
return os.environ.get("CTF_ROOT_DIR", default=".")
@@ -91,4 +89,7 @@ def find_ctf_root_directory() -> str:
9189
return path
9290

9391

94-
CTF_ROOT_DIRECTORY = find_ctf_root_directory()
92+
if len(sys.argv) > 1 and sys.argv[1] == "init":
93+
CTF_ROOT_DIRECTORY = os.path.join(os.getcwd(), ".")
94+
else:
95+
CTF_ROOT_DIRECTORY = find_ctf_root_directory()

ctf/__main__.py

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,31 @@ def terraform_binary() -> str:
9292
return path
9393

9494

95+
def init(args: argparse.Namespace) -> None:
96+
if os.path.isdir(os.path.join(args.path, "challenges")) or os.path.isdir(
97+
os.path.join(args.path, ".deploy")
98+
):
99+
LOG.error(f"Directory {args.path} is already initialized.")
100+
exit(code=1)
101+
102+
challenge_dir = os.path.join(args.path, "challenges")
103+
deploy_dir = os.path.join(args.path, ".deploy")
104+
105+
try:
106+
os.mkdir(challenge_dir)
107+
LOG.info(f"Created {challenge_dir}")
108+
shutil.copytree(os.path.join(TEMPLATES_ROOT_DIRECTORY, ".deploy"), deploy_dir)
109+
LOG.info(f"Created {deploy_dir}")
110+
except Exception:
111+
import traceback
112+
113+
if os.path.isdir(challenge_dir):
114+
os.rmdir(challenge_dir)
115+
if os.path.isdir(deploy_dir):
116+
shutil.rmtree(deploy_dir)
117+
LOG.critical(traceback.format_exc())
118+
119+
95120
def new(args: argparse.Namespace) -> None:
96121
LOG.info(msg=f"Creating a new track: {args.name}")
97122
if not re.match(pattern=r"^[a-z][a-z0-9\-]{0,61}[a-z0-9]$", string=args.name):
@@ -1310,6 +1335,18 @@ def main():
13101335
help="Script version.",
13111336
)
13121337

1338+
parser_init = subparsers.add_parser(
1339+
"init",
1340+
help="Initialize a folder with the default CTF structure.",
1341+
)
1342+
parser_init.set_defaults(func=init)
1343+
parser_init.add_argument(
1344+
"path",
1345+
nargs="?",
1346+
default=CTF_ROOT_DIRECTORY,
1347+
help="Initialize the folder at the given path.",
1348+
)
1349+
13131350
parser_flags = subparsers.add_parser(
13141351
"flags",
13151352
help="Get flags from tracks",
@@ -1556,10 +1593,11 @@ def main():
15561593
ENV["INCUS_REMOTE"] = args.remote
15571594

15581595
if not os.path.isdir(s=(p := os.path.join(CTF_ROOT_DIRECTORY, "challenges"))):
1559-
LOG.error(
1560-
msg=f"Directory `{p}` not found. Make sure this script is ran from the root directory OR set the CTF_ROOT_DIR environment variable to the root directory."
1561-
)
1562-
exit(code=1)
1596+
if args.func.__name__ != "init":
1597+
LOG.error(
1598+
msg=f"Directory `{p}` not found. Make sure this script is ran from the root directory OR set the CTF_ROOT_DIR environment variable to the root directory."
1599+
)
1600+
exit(code=1)
15631601

15641602
args.func(args=args)
15651603

ctf/templates/.deploy/cleanup.yaml

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
- name: Pre-deployment system cleanup
2+
hosts: all
3+
order: shuffle
4+
gather_facts: false
5+
any_errors_fatal: true
6+
7+
tasks:
8+
- name: Make network configuration static
9+
ansible.builtin.shell: |
10+
[ ! -e /run/systemd/resolve/resolv.conf ] && exit 0
11+
rm -f /etc/resolv.conf || true
12+
cat /run/systemd/resolve/resolv.conf > /etc/resolv.conf
13+
when: 'nsec_production | default(False)'
14+
changed_when: true
15+
16+
- name: Mask most systemd units
17+
ansible.builtin.shell: |
18+
for i in \
19+
apt-daily-upgrade.service \
20+
apt-daily-upgrade.timer \
21+
apt-daily.service \
22+
apt-daily.timer \
23+
console-getty.service \
24+
console-setup.service \
25+
dmesg.service \
26+
dpkg-db-backup.service \
27+
dpkg-db-backup.timer \
28+
e2scrub_all.service \
29+
e2scrub_all.timer \
30+
e2scrub_reap.service \
31+
emergency.service \
32+
fstrim.service \
33+
fstrim.timer \
34+
getty-static.service \
35+
36+
initrd-cleanup.service \
37+
initrd-parse-etc.service \
38+
initrd-switch-root.service \
39+
initrd-udevadm-cleanup-db.service \
40+
keyboard-setup.service \
41+
kmod-static-nodes.service \
42+
ldconfig.service \
43+
logrotate.service \
44+
logrotate.timer \
45+
46+
modprobe@dm_mod.service \
47+
48+
49+
50+
motd-news.service \
51+
motd-news.timer \
52+
netplan-ovs-cleanup.service \
53+
rescue.service \
54+
rsyslog.service \
55+
setvtrgb.service \
56+
syslog.socket \
57+
systemd-ask-password-console.service \
58+
systemd-ask-password-wall.service \
59+
systemd-battery-check.service \
60+
systemd-bsod.service \
61+
systemd-confext.service \
62+
systemd-fsck-root.service \
63+
systemd-fsckd.service \
64+
systemd-fsckd.socket \
65+
systemd-hibernate-resume.service \
66+
systemd-initctl.service \
67+
systemd-initctl.socket \
68+
systemd-journal-catalog-update.service \
69+
systemd-journal-flush.service \
70+
systemd-journald-dev-log.socket \
71+
systemd-journald.service \
72+
systemd-journald.socket \
73+
systemd-pcrextend.socket \
74+
systemd-pcrlock-file-system.service \
75+
systemd-pcrlock-firmware-code.service \
76+
systemd-pcrlock-firmware-config.service \
77+
systemd-pcrlock-machine-id.service \
78+
systemd-pcrlock-make-policy.service \
79+
systemd-pcrlock-secureboot-authority.service \
80+
systemd-pcrlock-secureboot-policy.service \
81+
systemd-pcrmachine.service \
82+
systemd-pcrphase-initrd.service \
83+
systemd-pcrphase-sysinit.service \
84+
systemd-pcrphase.service \
85+
systemd-random-seed.service \
86+
systemd-repart.service \
87+
systemd-soft-reboot.service \
88+
systemd-sysctl.service \
89+
systemd-sysext.service \
90+
systemd-sysext.socket \
91+
systemd-sysupdate-reboot.service \
92+
systemd-sysupdate-reboot.timer \
93+
systemd-sysupdate.service \
94+
systemd-sysupdate.timer \
95+
systemd-sysusers.service \
96+
systemd-timesyncd.service \
97+
systemd-tpm2-setup-early.service \
98+
systemd-tpm2-setup.service \
99+
systemd-update-done.service \
100+
systemd-update-utmp-runlevel.service \
101+
systemd-update-utmp.service \
102+
ua-reboot-cmds.service \
103+
ua-timer.service \
104+
ua-timer.timer \
105+
ubuntu-advantage.service; do
106+
ln -s /dev/null /etc/systemd/system/${i} || true
107+
done
108+
changed_when: true
109+
110+
- name: Mask network systemd units
111+
ansible.builtin.shell: |
112+
for i in \
113+
networkd-dispatcher.service \
114+
systemd-network-generator.service \
115+
systemd-networkd-wait-online.service \
116+
systemd-networkd.service \
117+
systemd-networkd.socket \
118+
systemd-resolved.service \
119+
systemd-udev-settle.service \
120+
systemd-udev-trigger.service \
121+
systemd-udevd-control.socket \
122+
systemd-udevd-kernel.socket \
123+
systemd-udevd.service; do
124+
ln -s /dev/null /etc/systemd/system/${i} || true
125+
done
126+
when: 'nsec_production | default(False)'
127+
changed_when: true
128+
129+
- name: Remove all cron jobs
130+
ansible.builtin.shell: |
131+
rm -f /etc/cron.*/* || true
132+
changed_when: true
133+
134+
- name: Reboot the instance
135+
ansible.builtin.reboot:

ctf/templates/.deploy/common.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
- name: Pre-deployment Common
2+
hosts: all
3+
order: shuffle
4+
gather_facts: false
5+
any_errors_fatal: true
6+
7+
tasks:
8+
- name: Distro update and Python3 install
9+
ansible.builtin.raw: |
10+
apt update && apt upgrade -y && apt install -y python3
11+
changed_when: true
12+
13+
- name: Importing cleanup.yaml Playbook
14+
ansible.builtin.import_playbook: cleanup.yaml
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
resource "incus_network_zone" "this" {
2+
remote = var.incus_remote
3+
4+
name = "ctf"
5+
description = "DNS zone for the internal .ctf TLD"
6+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
variable "incus_remote" {
2+
default = "local"
3+
type = string
4+
}
5+
6+
variable "deploy" {
7+
default = "dev"
8+
type = string
9+
}
10+
11+
locals {
12+
track = yamldecode(file("${path.module}/../track.yaml"))
13+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
terraform {
2+
required_version = ">=1.5.7"
3+
required_providers {
4+
incus = {
5+
source = "lxc/incus"
6+
version = ">=0.1.3"
7+
}
8+
}
9+
}

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ dependencies = [
1818
"black",
1919
"tabulate==0.9.0",
2020
]
21-
version = "1.1.3"
21+
version = "1.1.4"
2222
classifiers = [
2323
"Programming Language :: Python :: 3",
2424
"Operating System :: OS Independent",

0 commit comments

Comments
 (0)