feat: Base rainbowsheep-cloud ansible playbooks and roles
This commit is contained in:
commit
494e748beb
12 changed files with 345 additions and 0 deletions
73
README.md
Normal file
73
README.md
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
# Rainbowsheep Cloud Server :sheep: :rainbow:
|
||||||
|
|
||||||
|
Ansible recipes to install and maintain an instance of the Rainbowsheep cloud.
|
||||||
|
|
||||||
|
The Rainbowsheep cloud is a very lightweight and secured data cloud based on
|
||||||
|
standard or widely available tools such as NFS, Kerberos and gocryptfs.
|
||||||
|
|
||||||
|
It is an alternative to heavy cloud infrastructure such as NextCloud that
|
||||||
|
requires databases, web clients and so on.
|
||||||
|
|
||||||
|
The Rainbowsheep cloud is accessible as a regular Linux file system. This allows
|
||||||
|
to easily connect to the cloud with standard Linux tools, and to easily and
|
||||||
|
efficiently perfom complex operations on files if required.
|
||||||
|
|
||||||
|
## Server structure
|
||||||
|
|
||||||
|
Data for all users are stored in the following directories:
|
||||||
|
```
|
||||||
|
/srv
|
||||||
|
├── protected
|
||||||
|
│ ├── user1
|
||||||
|
│ ├── user2
|
||||||
|
│ └── ...
|
||||||
|
└── vault
|
||||||
|
├── user1
|
||||||
|
├── user2
|
||||||
|
└── ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Data in `/srv/protected` is stored as plain files on the server, so this
|
||||||
|
endpoint must be served using `krb5p`, i.e. Kerberos authentication and
|
||||||
|
encryption. This means your data is securely transmitted and other users cannot
|
||||||
|
have access to your data, but a `root` user on the server can read it.
|
||||||
|
|
||||||
|
Data in `/srv/vault` is encrypted at the filesystem level using `gocryptfs`.
|
||||||
|
This means you need your own private password to access your data locally. Only
|
||||||
|
uncrypted data is visible from the server, even for `root` user. In consequence,
|
||||||
|
the `/srv/vault` endpoint can be securely served using `krb5`, i.e. Kerberos
|
||||||
|
authentication only, as transmitted data is the `gocryptfs` encrypted data.
|
||||||
|
|
||||||
|
# Configure
|
||||||
|
|
||||||
|
Initialize the Kerberos master password:
|
||||||
|
```bash
|
||||||
|
ansible-vault encrypt_string --ask-vault-pass --stdin-name "krb5_master_password" --output krb5_master_password.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
# Install
|
||||||
|
|
||||||
|
Install cloud using Ansible:
|
||||||
|
```bash
|
||||||
|
ansible-playbook -i inventory -e "@krb5_master_password.yml" --ask-vault-pass rainbowsheep-cloud.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
# Create user
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export RAINBOW_NEW_USER=...
|
||||||
|
```
|
||||||
|
|
||||||
|
Initialize user password:
|
||||||
|
```bash
|
||||||
|
ansible-vault encrypt_string --ask-vault-pass --stdin-name "password" --output $RAINBOW_NEW_USER.yml
|
||||||
|
echo "username=$RAINBOW_NEW_USER" >> $RAINBOW_NEW_USER.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
Deploy the new user:
|
||||||
|
```bash
|
||||||
|
ansible-playbook -i inventory -e "@$RAINBOW_NEW_USER.yml" create-user.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
Once created, the specified password can be used on client side for Kerberos
|
||||||
|
authentication (`kinit`) and to mount the `gocryptfs` vault.
|
||||||
65
create-user.yml
Normal file
65
create-user.yml
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
- name: Create new Rainbosheep cloud user
|
||||||
|
hosts: server
|
||||||
|
tasks:
|
||||||
|
- name: Create kerberos user
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "kadmin.local add_principal -pw '{{ password }}' {{ username }}"
|
||||||
|
register: create_krb_user_out
|
||||||
|
failed_when: create_krb_user_out.rc != 0 and create_krb_user_out.rc != 1
|
||||||
|
changed_when: create_krb_user_out.rc == 0
|
||||||
|
|
||||||
|
- name: Create linux group
|
||||||
|
ansible.builtin.group:
|
||||||
|
name: "{{ username }}"
|
||||||
|
|
||||||
|
- name: Create linux user
|
||||||
|
ansible.builtin.user:
|
||||||
|
name: "{{ username }}"
|
||||||
|
create_home: false
|
||||||
|
group: "{{ username }}"
|
||||||
|
|
||||||
|
- name: Create user protected repository
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/srv/protected/{{ username }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ username }}"
|
||||||
|
group: "{{ username }}"
|
||||||
|
mode: "770"
|
||||||
|
|
||||||
|
- name: Create user vault repository
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/srv/vault/{{ username }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ username }}"
|
||||||
|
group: "{{ username }}"
|
||||||
|
mode: "770"
|
||||||
|
|
||||||
|
- name: Init gocryptfs vault
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "gocryptfs --init /srv/vault/{{ username }}"
|
||||||
|
stdin: "{{ password }}\n"
|
||||||
|
register: gocryptfs_out
|
||||||
|
failed_when: gocryptfs_out.rc != 0 and gocryptfs_out.rc != 6
|
||||||
|
changed_when: gocryptfs_out.rc == 0
|
||||||
|
|
||||||
|
- name: Get gocryptfs master key
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "gocryptfs-xray -dumpmasterkey /srv/vault/{{ username }}/gocryptfs.conf"
|
||||||
|
stdin: "{{ password }}\n"
|
||||||
|
register: master_key
|
||||||
|
|
||||||
|
- name: Print master key
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: |
|
||||||
|
Your master key is:
|
||||||
|
|
||||||
|
{{ master_key.stdout }}
|
||||||
|
|
||||||
|
If the gocryptfs.conf file becomes corrupted or you ever forget your password,
|
||||||
|
there is only one hope for recovery: The master key. Print it to a piece of
|
||||||
|
paper and store it in a drawer.
|
||||||
|
|
||||||
|
- name: Log master key
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "{{ gocryptfs_out }}"
|
||||||
|
|
||||||
8
rainbowsheep-cloud.yml
Normal file
8
rainbowsheep-cloud.yml
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
- name: Rainbowsheep Cloud Server
|
||||||
|
hosts: server
|
||||||
|
roles:
|
||||||
|
- chrony
|
||||||
|
- kerberos
|
||||||
|
- nfs
|
||||||
|
- vault
|
||||||
22
roles/chrony/tasks/main.yml
Normal file
22
roles/chrony/tasks/main.yml
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
---
|
||||||
|
# tasks file for chrony_client
|
||||||
|
- name: Install chrony
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: chrony
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
# - name: Configure chrony client
|
||||||
|
# ansible.builtin.template:
|
||||||
|
# src: chrony.conf.j2
|
||||||
|
# dest: /etc/chrony/chrony.conf
|
||||||
|
# owner: root
|
||||||
|
# group: root
|
||||||
|
# mode: "0644"
|
||||||
|
# notify: Restart chrony
|
||||||
|
|
||||||
|
- name: Enable and start chrony
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: chrony
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
2
roles/kerberos/defaults/main.yml
Normal file
2
roles/kerberos/defaults/main.yml
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
|
||||||
|
kerberos_realm: "{{ ansible_facts['hostname'] }}"
|
||||||
8
roles/kerberos/handlers/main.yml
Normal file
8
roles/kerberos/handlers/main.yml
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
- name: Restart krb5 kdc
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: krb5-kdc
|
||||||
|
state: restarted
|
||||||
|
- name: Restart krb5 admin server
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: krb5-admin-server
|
||||||
|
state: restarted
|
||||||
76
roles/kerberos/tasks/main.yml
Normal file
76
roles/kerberos/tasks/main.yml
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
- name: Install Kerberos server
|
||||||
|
ansible.builtin.apt:
|
||||||
|
pkg:
|
||||||
|
- krb5-user
|
||||||
|
- krb5-kdc
|
||||||
|
- krb5-admin-server
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
- name: Enables krb5-kdc
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: krb5-kdc
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
- name: Enables krb5-admin-server
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: krb5-admin-server
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
- name: Configure krb5
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: krb5.conf.j2
|
||||||
|
dest: /etc/krb5.conf
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
notify:
|
||||||
|
- Restart krb5 kdc
|
||||||
|
- Restart krb5 admin server
|
||||||
|
|
||||||
|
- name: Configure krb5 kdc
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: kdc.conf.j2
|
||||||
|
dest: /etc/krb5kdc/kdc.conf
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
notify:
|
||||||
|
- Restart krb5 kdc
|
||||||
|
- Restart krb5 admin server
|
||||||
|
|
||||||
|
- name: Configure krb5 ACLs
|
||||||
|
# Allow */admin (notable root/admin) user to manage principals
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: kadm5.acl.j2
|
||||||
|
dest: /etc/krb5kdc/kadm5.acl
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
notify:
|
||||||
|
- Restart krb5 kdc
|
||||||
|
- Restart krb5 admin server
|
||||||
|
|
||||||
|
|
||||||
|
- name: Create kdc
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "kdb5_util create -P {{ krb5_master_password }}"
|
||||||
|
register: create_kdc
|
||||||
|
failed_when: create_kdc.rc != 0 and create_kdc.rc != 1
|
||||||
|
changed_when: create_kdc.rc == 0
|
||||||
|
|
||||||
|
- name: Create kdc stash file
|
||||||
|
# The stash file is specified in kdc.conf as key_stash_file
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "kdb5_util stash -P {{ krb5_master_password }}"
|
||||||
|
|
||||||
|
- name: Start krb5-kdc
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: krb5-kdc
|
||||||
|
state: started
|
||||||
|
|
||||||
|
- name: Start krb5-admin-server
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: krb5-admin-server
|
||||||
|
state: started
|
||||||
|
|
||||||
1
roles/kerberos/templates/kadm5.acl.j2
Normal file
1
roles/kerberos/templates/kadm5.acl.j2
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
*/admin@{{ kerberos_realm | upper }} *
|
||||||
21
roles/kerberos/templates/kdc.conf.j2
Normal file
21
roles/kerberos/templates/kdc.conf.j2
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
[kdcdefaults]
|
||||||
|
kdc_ports = 750,88
|
||||||
|
|
||||||
|
[realms]
|
||||||
|
{{ kerberos_realm | upper }} = {
|
||||||
|
database_name = /var/lib/krb5kdc/principal
|
||||||
|
admin_keytab = FILE:/etc/krb5kdc/kadm5.keytab
|
||||||
|
acl_file = /etc/krb5kdc/kadm5.acl
|
||||||
|
key_stash_file = /etc/krb5kdc/stash
|
||||||
|
kdc_ports = 750,88
|
||||||
|
max_life = 3d 0h 0m 0s
|
||||||
|
max_renewable_life = 7d 0h 0m 0s
|
||||||
|
#master_key_type = aes256-cts
|
||||||
|
#supported_enctypes = aes256-cts:normal aes128-cts:normal
|
||||||
|
default_principal_flags = +preauth
|
||||||
|
}
|
||||||
|
|
||||||
|
[logging]
|
||||||
|
kdc = CONSOLE
|
||||||
|
kdc = FILE:/var/log/kdc.log
|
||||||
|
debug = true
|
||||||
28
roles/kerberos/templates/krb5.conf.j2
Normal file
28
roles/kerberos/templates/krb5.conf.j2
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
[libdefaults]
|
||||||
|
default_realm = {{ kerberos_realm | upper }}
|
||||||
|
dns_lookup_realm = true
|
||||||
|
dns_lookup_kdc = true
|
||||||
|
|
||||||
|
# The following krb5.conf variables are only for MIT Kerberos.
|
||||||
|
kdc_timesync = 1
|
||||||
|
ccache_type = 4
|
||||||
|
forwardable = true
|
||||||
|
proxiable = true
|
||||||
|
rdns = false
|
||||||
|
|
||||||
|
ticket_lifetime = 3d
|
||||||
|
renew_lifetime = 7d
|
||||||
|
|
||||||
|
# The following libdefaults parameters are only for Heimdal Kerberos.
|
||||||
|
fcc-mit-ticketflags = true
|
||||||
|
|
||||||
|
[realms]
|
||||||
|
{{ kerberos_realm | upper }} = {
|
||||||
|
kdc = kerberos.{{ kerberos_realm }}
|
||||||
|
admin_server = kerberos.{{ kerberos_realm }}
|
||||||
|
default_principal_flags = +preauth
|
||||||
|
}
|
||||||
|
|
||||||
|
[domain_realm]
|
||||||
|
{{ kerberos_realm }} = {{ kerberos_realm | upper }}
|
||||||
|
.{{ kerberos_realm }} = {{ kerberos_realm | upper }}
|
||||||
36
roles/nfs/tasks/main.yml
Normal file
36
roles/nfs/tasks/main.yml
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: Install nfs server
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: nfs-kernel-server
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
- name: Create /srv/protected export
|
||||||
|
ansible.builtin.file:
|
||||||
|
state: directory
|
||||||
|
path: /srv/protected
|
||||||
|
|
||||||
|
- name: Export /srv/protected
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: /etc/exports
|
||||||
|
regexp: '^/srv/protected'
|
||||||
|
line: /srv/protected *(rw,sync,sec=krb5p,no_subtree_check)
|
||||||
|
|
||||||
|
- name: Create /srv/vault export
|
||||||
|
ansible.builtin.file:
|
||||||
|
state: directory
|
||||||
|
path: /srv/vault
|
||||||
|
|
||||||
|
- name: Export /srv/vault
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: /etc/exports
|
||||||
|
regexp: '^/srv/vault'
|
||||||
|
line: /srv/vault *(rw,sync,sec=krb5p:krb5i:krb5,no_subtree_check)
|
||||||
|
|
||||||
|
- name: Enable and start NFS server
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: nfs-kernel-server
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
|
||||||
5
roles/vault/tasks/main.yml
Normal file
5
roles/vault/tasks/main.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
- name: Install gocryptfs
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: gocryptfs
|
||||||
|
update_cache: true
|
||||||
Loading…
Add table
Add a link
Reference in a new issue