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