Docker Targets
Each target must reside on its own directory under Dockerfiles/
. Each target folder has the following structure
autoregister.yml
An ansible playbook that is executed during the docker image build. Most of the times you dont have to modify this file.Dockerfile
This includes your standardDockerfile
instructions in order to build your target imageentrypoint.sh
The script executed when the container startsREADME.md
A readme explaining the target, solution and other details (this is empty but you are advised to keep detailed records here as it will become harder to recall details the more targets you got)variables.yml
The variables used by theautoregister.yml
playbook to do its job
You can use the existing Dockerfiles/example
to get started or create your own.
Edit the file Dockerfiles/example/variables.yml
and start by modifying the basic information.
ansible_host: 10.0.160.3
DOCKER: localhost
mac: "de:ad:be:ef:c0:ff:ee"
hostname: example
fqdn: example.echocity-f.com
rootable: 0 # 1 for yes
difficulty: 3
#scheduled_at: "YYYY-mm-dd HH:MM:SS"
The meaning and use of the variables is:
ansible_host
the IP address that the container will be assigned. During development (eg while testingdocker build
) the default IP is usually one from the172.17.0.0/24
subnetDOCKER
The docker host that will run this container (egdockerd.example.net
)mac
A valid and unique mac address. A nice trick to generate mac addresses for your hosts is to run something like the following
printf "02:42:%.2x:%.2x:%.2x:%.2x\n" $(echo "IP_ADDRESS_OF_TARGET"|sed -e 's/\./ /g')
hostname
andFQDN
for the target. The hostname is also used as the container name when startedrootable
Wether or not this target can be rooted or not0=non-rootable
and1=rootable
difficulty
A difficulty score for the target between 0 and 5. With 0 being the easiest and 5 harderscheduled_at
Uncomment to schedule this target to power up at a specific date and time
After the basic information, container specific details are included.
container:
name: "{{hostname}}"
hostname: "{{fqdn}}"
build: "example" # The current folder name
image: "example" # The current folder name
state: "started"
mac_address: "{{mac}}"
purge_networks: "yes"
# tag: "v0.1"
# buildargs:
# var_name: var_value
env:
ETSCTF_FLAG: "ETSCTF_{{ETSCTF_ENV_FLAG}}"
dns_servers:
- "10.0.0.254"
networks:
- { name: AAnet, ipv4_address: "{{ansible_host}}" }
volumes: []
These details you need to modify include
build
andimage
The folder that we are going to build the image from and the name that the intermediate image will have. When the images are pushed to a registry the name changes tohostname
tag
A version/build tag. If no tag is defined then the default tag islatest
buildargs
Key/Value pair of variables needed to build the container. More details about this can be found at docker --build-argenv
Key/Value environment variables defined upon starting a container. More details about the docker--env
can be found at docker env variablesdns_servers
A list of dns servers that the container will use for name resolutionnetworks
The network this container will be attached. This is the same name as the one we created on our docker server (egAAnet
)volumes
A list of volumes to be mapped when the container starts
After that we can configure the core flags for /root
, env
, /etc/shadow
and /etc/passsw
ETSCTF_ROOT_FLAG: ""
ETSCTF_ENV_FLAG: ""
ETSCTF_SHADOW_FLAG: ""
ETSCTF_PASSWD_FLAG: ""
We prefer to use random md5 hashes for these flags, but you can use whatever you like. The way we generate them is by using the password generator pwgen
and piping its output to md5sum
like so
pwgen|md5sum
One you have created all your docker targets prepare their hosts file we did with the dockers
servers.
echo "[targets]"> inventories/targets/hosts
echo "example.fqdn.com">>inventories/targets/hosts
And add links from the variables.yml
file of each container into the
targets/host_vars
like the following example
ln -s ../../../Dockerfiles/example/variables.yml inventories/targets/host_vars/example.fqdn.com.yml
NOTE: Ansible tries to access the example.fqdn.com.yml
file relative to the inventories/targets/host_vars
folder. You need to include the ../../../
part when creating the symbolic link for it to be able to find the variables.
Alternatively you can generate both hosts
and their corresponding host_vars
by running the following from the ansible folder.
INVENTORY="targets"
echo "[$INVENTORY]">inventories/$INVENTORY/hosts
for i in Dockerfiles/*;do
fqdn=$(grep ^fqdn $i/variables.yml|awk '{print $2}')
ln -fs ../../../$i/variables.yml inventories/$INVENTORY/host_vars/${fqdn}.yml
echo -e "${fqdn}\t\t\t# "$(basename $i)>>inventories/$INVENTORY/hosts
done
In order to build the target images
ansible-playbook playbooks/build-images.yml -i inventories/targets --extra-vars "BUILDER=localhost" --extra-vars "DOCKER_REGISTRY=myregistry:5000" --extra-vars "DOCKER_REPOSITORY=targets"
Feed the data to the backend
ansible-playbook playbooks/feed-targets.yml -i inventories/targets -e '{"mui":{"URL": "http://127.0.0.1:8080"}}'
You can also create a file at inventories/targets/group_vars/all.yml
for the targets to include all those extra-vars details and not having to type them again
DOCKER_REGISTRY: "myregistry:5000"
DOCKER_REPOSITORY: "targets"
TOKEN: MyMUIToken
mui:
URL: "{{MUI_URL|default('http://localhost:8080')}}"
Alternative build
You can also use the playbooks/build-squash.yml to build images with squashed layers. This however requires to add the option "experimental": true,
to /etc/docker/daemon.json like so
{
"experimental": true,
"insecure-registries":["myregistry:5555"]
}
Once done restart the docker daemon for the changes to take effect and try to build your image
ansible-playbook playbooks/build-squash.yml -i inventories/targets
This playbook provides a few tags to ease in managing single tasks, such as * build: Build image * push: Push image to registry * rmi: Remove the image from local images
These tags can be used to perform a specific task or to skip some ie
ansible-playbook playbooks/build-squash.yml -i inventories/targets --skip-tags push,rmi