Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
mcbloch committed Jan 15, 2022
0 parents commit af07021
Show file tree
Hide file tree
Showing 41 changed files with 1,055 additions and 0 deletions.
22 changes: 22 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

# Created by https://www.toptal.com/developers/gitignore/api/ansible,vagrant
# Edit at https://www.toptal.com/developers/gitignore?templates=ansible,vagrant

### Ansible ###
*.retry

### Vagrant ###
# General
.vagrant/

# Log files (if you are creating logs in debug mode, uncomment this)
# *.log

### Vagrant Patch ###
*.box

# End of https://www.toptal.com/developers/gitignore/api/ansible,vagrant

### VSCode ###
# General
.vscode/
2 changes: 2 additions & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ansible-base = 2.10.16
python = 3.10.1
28 changes: 28 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
.PHONY: init, lint, format, clean, config, test, test-container

init:
ansible-galaxy install -r requirements.yml
lint:
ansible-lint --exclude=vagrantconfig.yaml
format:
cd configuration && dhall format config.dhall
cd configuration && dhall format esa.dhall
cd configuration && dhall format types.dhall
cd configuration && dhall format validations.dhall
clean:
vagrant destroy
yeet:
cd configuration && echo '(./esa.dhall)' | dhall-to-yaml
config:
cd configuration && echo '(./esa.dhall).hostVars' | dhall-to-yaml \
--explain \
--documents \
--generated-comment \
--output host_vars.yml
cd configuration && echo '(./esa.dhall).ssh_config' | dhall text \
--output ssh.config
test:
vagrant up --provision
test-container:
ansible-playbook -i inventory.ini simple-web.yml
ansible-playbook -i inventory.ini ruby-web.yml
52 changes: 52 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# ESA - Expressive Safe Ansible

An opinionated wrapper around ansible to make it hard to use incorrectly.

Work in progress. All suggestions and comments are welcome.

## Introduction


A best practices setup that tries to make it harder to make a bad ansible configuration by adding good presets and handy wrappers.

- Users: Are defined globally and can be assigned to containers to get access. They will get their own user per container.

A host is a metal machine or a container
A group can be the metals that need a container setup or applications that need to be deployed on a container.

### Notes

- Only compatible with debian at the moment

## TODO

- Retrieve IP of created container and set as dynamic variable
- Probably need to use a better dynamic hosts tool
- Use static ip's
- Not setting the ip is possible but you are then unable to run a playbook against the host automatically. You will need to paste the ip in the inventory manually. The container is possible to get port forwards but the ssh config can not be set automatically atm. Also, all port forwards break on reboot :)

## Roadmap

- Add vault best practices
- Add a bastion user to jump through the host to containers (without shell access for the bastion)
- Run unprivileged containers
- Add ssh wrapper that adds flags to add the generated ssh.config

- Add automatic testing on filechanges
- Check yaml validity
- Check ansible validity
- Try vagrant test

## Extras

- Check network bridge on host: `ip -4 -o a show`
- List lxc containers: `lxc-ls --fancy`
- Ssh to a container or host defined in the ssh.config file: `ssh -o ControlMaster=auto -o ControlPersist=30m -o ControlPath=/tmp/ansible-%r@%h:%p -F ssh.config simple-web-01`
- Check NAT rules: `iptables -L -n -t nat`
- List prerouting rules: `sudo iptables -t nat -L PREROUTING -n --line-number`
- Remove a prerouting rule `sudo iptables -t nat -D PREROUTING 1`

## More things I try to achieve

- Keep everything in the folder. No usage of external servers or heavy tools.
-
33 changes: 33 additions & 0 deletions Vagrantfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Alternative oss boxes: https://app.vagrantup.com/bento

# groups with ip's
# - metal => machine1 | vagrant ;
# - simple_web-container => swc-01 | 172.0.0.1 ;


# virtual groups
# - simple_web -> simple_web-container,
# - container -> simple_web-container,


Vagrant.configure("2") do |config|

config.vm.define "machine1"
#
# Run Ansible from the Vagrant Host
#
config.vm.network "forwarded_port", guest: 8321, host: 8321
config.vm.network "forwarded_port", guest: 8322, host: 8322

config.vm.box = "bento/debian-10.11"
config.vm.provision "ansible" do |ansible|
ansible.playbook = "playbook.yml"
ansible.groups = {
"metal" => ["machine1"],
#"simple_web" => ["simple_web-container"],
#"container" => ["simple_web-container"],
}
# ansible.verbose = "vvv"
# ansible.tags = "network"
end
end
15 changes: 15 additions & 0 deletions ansible.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Examples: https://github.com/ansible/ansible/blob/stable-2.9/examples/ansible.cfg

[defaults]

nocows = 1
# cow_selection = random
interpreter_python = auto_legacy_silent
inventory=inventory.ini

# human-readable stdout/stderr results display
# stdout_callback=debug

[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=30m -o ControlPath=/tmp/ansible-%r@%h:%p -F ssh.config
45 changes: 45 additions & 0 deletions configuration/config.dhall
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
let Prelude =
https://prelude.dhall-lang.org/v21.1.0/package.dhall
sha256:eb693342eb769f782174157eba9b5924cf8ac6793897fc36a31ccbd6f56dafe2

let types = ./types.dhall

let c1 =
types.Container::{
, name = "simple-web-01"
, distro = "debian"
, release = "buster"
, arch = "amd64"
, store = "dir"
}

let c2 = types.Container::{ name = "ruby-web-01" }

let machine1 =
types.Metal::{
, name = "machine1"
, lxc_containers = Some [ c1, c2 ]
, port_forwards = Some
[ { host_port = 8321, container_port = 80, container_name = c1.name }
, { host_port = 8322, container_port = 80, container_name = c2.name }
]
, ssh_config = types.SshConfig::{
, hostname = "127.0.0.1"
, user = "vagrant"
, port = 2222
, identity_file = ".vagrant/machines/machine1/virtualbox/private_key"
}
}

let machine2 =
types.Metal::{
, name = "zeus-king"
, ssh_config = types.SshConfig::{
, hostname = "zeus.ugent.be"
, port = 2222
, user = "root"
, identity_file = "~/.ssh/id_ed25519_zeus"
}
}

in { containers = [ c1, c2 ], metals = [ machine1, machine2 ] } : types.Config
85 changes: 85 additions & 0 deletions configuration/esa.dhall
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
let Prelude =
https://prelude.dhall-lang.org/v21.1.0/package.dhall
sha256:eb693342eb769f782174157eba9b5924cf8ac6793897fc36a31ccbd6f56dafe2

let types = ./types.dhall

let config = ./config.dhall

let validations = ./validations.dhall

let validateConfig =
λ(config : types.Config)
let validMetals = validations.validateMetals config.metals

in { validMetals }

let validate = assert : validateConfig config { validMetals = True }

let type_containers = List types.Container.Type

let type_container_entry = { mapKey : Text, mapValue : types.Container.Type }

let type_container_map = List type_container_entry

let toMetalHostVars =
λ(metal : types.Metal.Type)
{ mapKey = metal.name
, mapValue =
{ name = metal.name
, lxc_containers =
Prelude.Optional.map
type_containers
type_container_map
( λ(lxc_containers : type_containers)
Prelude.List.map
types.Container.Type
type_container_entry
( λ(c : types.Container.Type)
Prelude.Map.keyValue types.Container.Type c.name c
)
lxc_containers
)
metal.lxc_containers
, port_forwards = metal.port_forwards
}
}

let toHostVars =
λ(config : types.Config)
{ all.hosts
=
Prelude.List.map
types.Metal.Type
{ mapKey : Text, mapValue : types.MetalVars }
toMetalHostVars
config.metals
}

let defaultSshIdentityFile = λ(m : types.Metal.Type) "files/private/${m.name}"

let toSshConfig =
λ(ms : List types.Metal.Type)
Prelude.Text.concatMapSep
"\n"
types.Metal.Type
( λ(m : types.Metal.Type)
''
Host ${m.name}
HostName ${m.ssh_config.hostname}
User ${m.ssh_config.user}
Port ${Natural/show m.ssh_config.port}
IdentityFile ${m.ssh_config.identity_file}
''
)
ms
++ ''


Host *
LogLevel FATAL
PasswordAuthentication no
IdentitiesOnly yes
''

in { hostVars = toHostVars config, ssh_config = toSshConfig config.metals }
28 changes: 28 additions & 0 deletions configuration/host_vars.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Code generated by dhall-to-yaml. DO NOT EDIT.
---
all:
hosts:
machine1:
lxc_containers:
ruby-web-01:
arch: amd64
distro: debian
name: ruby-web-01
release: buster
store: dir
simple-web-01:
arch: amd64
distro: debian
name: simple-web-01
release: buster
store: dir
name: machine1
port_forwards:
- container_name: simple-web-01
container_port: 80
host_port: 8321
- container_name: ruby-web-01
container_port: 80
host_port: 8322
zeus-king:
name: zeus-king
17 changes: 17 additions & 0 deletions configuration/ssh.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Host machine1
HostName 127.0.0.1
User vagrant
Port 2222
IdentityFile .vagrant/machines/machine1/virtualbox/private_key

Host zeus-king
HostName zeus.ugent.be
User root
Port 2222
IdentityFile ~/.ssh/id_ed25519_zeus


Host *
LogLevel FATAL
PasswordAuthentication no
IdentitiesOnly yes
50 changes: 50 additions & 0 deletions configuration/types.dhall
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
let Prelude =
https://prelude.dhall-lang.org/v21.1.0/package.dhall
sha256:eb693342eb769f782174157eba9b5924cf8ac6793897fc36a31ccbd6f56dafe2

let Container =
{ Type =
{ name : Text
, distro : Text
, release : Text
, arch : Text
, store : Text
}
, default =
{ distro = "debian", release = "buster", arch = "amd64", store = "dir" }
}

let PortForward =
{ host_port : Natural, container_port : Natural, container_name : Text }

let MetalVars =
{ name : Text
, lxc_containers :
Optional (List { mapKey : Text, mapValue : Container.Type })
, port_forwards : Optional (List PortForward)
}

let SshConfig =
{ Type =
{ hostname : Text, user : Text, port : Natural, identity_file : Text }
, default =
{ hostname = "127.0.0.1", user = "", port = 22, identity_file = "" }
}

let Metal =
{ Type =
{ name : Text
, lxc_containers : Optional (List Container.Type)
, port_forwards : Optional (List PortForward)
, ssh_config : SshConfig.Type
}
, default =
{ lxc_containers = None (List Container.Type)
, port_forwards = None (List PortForward)
, ssh_config = SshConfig.default
}
}

let Config = { containers : List Container.Type, metals : List Metal.Type }

in { Container, PortForward, Metal, MetalVars, Config, SshConfig }
Loading

0 comments on commit af07021

Please sign in to comment.