Skip to content

Commit 6d9d3af

Browse files
committed
Honey swarm first draft
0 parents  commit 6d9d3af

File tree

30 files changed

+924
-0
lines changed

30 files changed

+924
-0
lines changed

ansible/00-init-nodes.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
- hosts: all
3+
remote_user: root
4+
gather_facts: true
5+
tasks:
6+
- debug:
7+
msg: "Loaded base playbook"
8+
roles:
9+
- initialize
10+
- hardening
11+
- docker

ansible/01-setup-swarm.yml

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
---
2+
###
3+
# provision-02-docker-swarm playbook
4+
##
5+
# Set up the Swarm cluster and put it into the desired state
6+
#
7+
# Playbook inspired by https://github.com/nextrevision/ansible-swarm-playbook
8+
# Big thanks to John Patterson for his work!
9+
##
10+
11+
12+
# use dockerswarm_advertise_addr instead of iface when ethX has multiple IP addresses
13+
- hosts: all
14+
tasks:
15+
- name: define dockerswarm_advertise_addr_string (defined) - PROVIDED
16+
set_fact:
17+
dockerswarm_advertise_addr_string: "{{ dockerswarm_advertise_addr }}"
18+
when: dockerswarm_advertise_addr is defined
19+
- name: define dockerswarm_advertise_addr_string (defined) - DEFAULTED TO HOST IP
20+
set_fact:
21+
dockerswarm_advertise_addr_string: "{{ ansible_ssh_host }}"
22+
when: dockerswarm_advertise_addr is not defined
23+
24+
- name: Get info on Docker Swarm
25+
community.docker.docker_swarm_info:
26+
ignore_errors: yes
27+
register: swarm_node_facts
28+
29+
- name: Inform about basic flags
30+
ansible.builtin.debug:
31+
msg: |
32+
Was able to talk to docker daemon: {{ swarm_node_facts.can_talk_to_docker }}
33+
Docker in Swarm mode: {{ swarm_node_facts.docker_swarm_active }}
34+
This is a Manager node: {{ swarm_node_facts.docker_swarm_manager }}
35+
36+
# determine the status of each manager node and break them
37+
# into two groups:
38+
# - dockerswarm_manager_operational (swarm is running and active)
39+
# - dockerswarm_manager_bootstrap (host needs to be joined to the cluster)
40+
- hosts: all:&dockerswarm_manager
41+
tasks:
42+
43+
- name: Get info on Docker Swarm
44+
community.docker.docker_swarm_info:
45+
ignore_errors: yes
46+
register: swarm_node_facts
47+
48+
- name: create dockerswarm_manager_operational group
49+
add_host:
50+
hostname: "{{ item }}"
51+
groups: dockerswarm_manager_operational
52+
with_items: "{{ ansible_play_hosts | default(play_hosts) }}"
53+
when: swarm_node_facts.docker_swarm_active
54+
run_once: true
55+
changed_when: False
56+
57+
- name: create dockerswarm_manager_bootstrap group
58+
add_host:
59+
hostname: "{{ item }}"
60+
groups: dockerswarm_manager_bootstrap
61+
with_items: "{{ ansible_play_hosts | default(play_hosts) }}"
62+
when: not swarm_node_facts.docker_swarm_active
63+
run_once: true
64+
changed_when: False
65+
66+
# determine the status of each worker node and break them
67+
# into two groups:
68+
# - dockerswarm_worker_operational (host is joined to the swarm cluster)
69+
# - dockerswarm_worker_bootstrap (host needs to be joined to the cluster)
70+
- hosts: all:&dockerswarm_worker
71+
tasks:
72+
- name: create dockerswarm_worker_operational group
73+
add_host:
74+
hostname: "{{ item }}"
75+
groups: dockerswarm_worker_operational
76+
with_items: "{{ ansible_play_hosts | default(play_hosts) }}"
77+
when: swarm_node_facts.docker_swarm_active
78+
run_once: true
79+
changed_when: False
80+
81+
- name: create dockerswarm_worker_bootstrap group
82+
add_host:
83+
hostname: "{{ item }}"
84+
groups: dockerswarm_worker_bootstrap
85+
with_items: "{{ ansible_play_hosts | default(play_hosts) }}"
86+
when: not swarm_node_facts.docker_swarm_active
87+
run_once: true
88+
changed_when: False
89+
90+
# when the dockerswarm_manager_operational group is empty, meaning there
91+
# are no hosts running swarm, we need to initialize one of the hosts
92+
# then add it to the dockerswarm_manager_operational group
93+
- hosts: dockerswarm_manager_bootstrap[0]
94+
tasks:
95+
- name: initialize swarm cluster
96+
command: >
97+
docker swarm init
98+
--advertise-addr={{ dockerswarm_advertise_addr_string }}:2377
99+
when: "'dockerswarm_manager_operational' not in groups"
100+
register: bootstrap_first_node
101+
102+
- name: add initialized host to dockerswarm_manager_operational group # noqa 503
103+
add_host:
104+
hostname: "{{ item }}"
105+
groups: dockerswarm_manager_operational
106+
with_items: "{{ ansible_play_hosts | default(play_hosts) }}"
107+
when: bootstrap_first_node.changed
108+
109+
# retrieve the swarm tokens and populate a list of ips listening on
110+
# the swarm port 2377
111+
- hosts: dockerswarm_manager_operational[0]
112+
vars:
113+
tasks:
114+
- name: retrieve swarm manager token
115+
command: docker swarm join-token -q manager
116+
register: dockerswarm_manager_token
117+
changed_when: False
118+
119+
- name: retrieve swarm worker token
120+
command: docker swarm join-token -q worker
121+
register: dockerswarm_worker_token
122+
changed_when: False
123+
124+
- name: populate list of manager ips from dockerswarm_advertise_addr
125+
add_host:
126+
hostname: "{{ dockerswarm_advertise_addr_string }}"
127+
groups: dockerswarm_manager_ips
128+
changed_when: False
129+
130+
- name: Inform about basic flags
131+
ansible.builtin.debug:
132+
msg: |
133+
{{groups}}
134+
135+
# join the hosts not yet initialized to the swarm cluster
136+
- hosts: dockerswarm_manager_bootstrap:!dockerswarm_manager_operational
137+
vars:
138+
token: "{{ hostvars[groups.dockerswarm_manager_operational[0]]['dockerswarm_manager_token']['stdout'] }}"
139+
tasks:
140+
- name: join manager nodes to cluster # noqa 301
141+
command: >
142+
docker swarm join
143+
--advertise-addr={{ dockerswarm_advertise_addr_string }}:2377
144+
--token={{ token }}
145+
{{ groups.dockerswarm_manager_ips[0] }}:2377
146+
147+
# join the remaining workers to the swarm cluster
148+
- hosts: dockerswarm_worker_bootstrap
149+
vars:
150+
token: "{{ hostvars[groups.dockerswarm_manager_operational[0]]['dockerswarm_worker_token']['stdout'] }}"
151+
tasks:
152+
- name: join worker nodes to cluster # noqa 301
153+
command: >
154+
docker swarm join
155+
--advertise-addr={{ dockerswarm_advertise_addr_string }}
156+
--token={{ token }}
157+
{{ groups.dockerswarm_manager_ips[0] }}:2377

ansible/02-deploy-infrastucture.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
2+
- hosts: dockerswarm_manager[0] # executed on the first Swarm manager
3+
pre_tasks:
4+
- name: Create Docker public-network network where all apps talk to traefik
5+
docker_network:
6+
name: public-network
7+
driver: overlay
8+
9+
roles:
10+
# TRAEFIK
11+
- role: docker-stack
12+
tags:
13+
- stack-traefik
14+
vars:
15+
docker_stack_name: traefik
16+
17+
# PORTAINER
18+
- role: docker-stack
19+
tags:
20+
- portainer
21+
vars:
22+
docker_stack_name: portainer
23+
when: deploly_portainer

ansible/group_vars/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
localhost_bindmounts.yml
2+
*_overrides.yml

ansible/group_vars/all.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
###
3+
# Variables default values
4+
##
5+
# We recommend to use production values here
6+
# These variables can be overridden later in other group_vars files
7+
#
8+
# Here is the Ansible groups structure:
9+
# all
10+
# ├── production
11+
# ├── staging
12+
# └── any_other_remote_environment...
13+
#
14+
# Each group has its "_overrides" counterpart, which enables you to override
15+
# some variables locally in a xxx_overrides.yml file, which is not versionned
16+
# Have a look at .sample.yml files to see some examples
17+
##
18+
19+
## Additional software that is going to be installed on all the nodes
20+
## to facilitate your life managing them when you need to SSH them
21+
additional_packages:
22+
- vim
23+
- htop
24+
25+
26+
# Add the names of the users who will have root ssh access to all nodes,
27+
# and then add a public key to pubkeys with the file named for each user
28+
# eg.
29+
# users:
30+
# - sergio
31+
32+
users:
33+
34+
# Domains
35+
domains:
36+
main: "yourdomain.tld" # REPLACE THIS
37+
38+
39+
# Enable traefik ACME feature
40+
# If enabled, traefik will use Let's Encrypt to get an SSL certificate automatically
41+
# Should be disabled only on local environments (localhost or vagrant)
42+
letsencrypt: True
43+
letsencrypt_email: admin@{{ domains.main }}
44+
45+
46+
# geerlingguy.docker role configuration
47+
docker_edition: ce
48+
49+
50+
#### CORE
51+
52+
deploly_portainer: true
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
## SPECIFY ALL THE NODES HERE
2+
[nodes]
3+
node-1 ansible_user=root ansible_host=NODE_IP ansible_port=22
4+
node-2 ansible_user=root ansible_host=NODE_IP ansible_port=22 dockerswarm_advertise_addr=<INTERNAL_IP>
5+
6+
[dockerswarm_manager]
7+
node-1
8+
9+
[dockerswarm_worker]
10+
node-2

ansible/provision.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
---
2+
###
3+
# provision playbook
4+
##
5+
6+
- import_playbook: 00-init-nodes.yml
7+
tags: [setup]
8+
9+
- import_playbook: 01-setup-swarm.yml
10+
tags: [docker]
11+
12+
- import_playbook: 02-deploy-infrastucture.yml
13+
tags: [infrastructure]

ansible/pubkeys/.gitkeep

Whitespace-only changes.

ansible/requirements.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
collections:
3+
- name: ansible.posix
4+
5+
roles:
6+
- src: geerlingguy.pip
7+
version: 2.1.0
8+
9+
- src: geerlingguy.docker
10+
version: 4.1.1

ansible/roles/docker-stack/.yamllint

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
# Based on ansible-lint config
3+
extends: default
4+
5+
rules:
6+
braces:
7+
max-spaces-inside: 1
8+
level: error
9+
brackets:
10+
max-spaces-inside: 1
11+
level: error
12+
colons:
13+
max-spaces-after: -1
14+
level: error
15+
commas:
16+
max-spaces-after: -1
17+
level: error
18+
comments: disable
19+
comments-indentation: disable
20+
document-start: disable
21+
empty-lines:
22+
max: 3
23+
level: error
24+
hyphens:
25+
level: error
26+
indentation: disable
27+
key-duplicates: enable
28+
line-length: disable
29+
new-line-at-end-of-file: disable
30+
new-lines:
31+
type: unix
32+
trailing-spaces: disable
33+
truthy: disable

0 commit comments

Comments
 (0)