Browse Source

roles/lxc_guest: add unprivileged support

python3
Zolfa 4 years ago
parent
commit
599e0b8996
Signed by: zolfa GPG Key ID: E1A43B038C4D6616
4 changed files with 145 additions and 4 deletions
  1. +1
    -0
      roles/lxc_guest/defaults/main.yaml
  2. +44
    -0
      roles/lxc_guest/files/find_subxid.sh
  3. +75
    -1
      roles/lxc_guest/tasks/main.yaml
  4. +25
    -3
      roles/lxc_guest/templates/config.j2

+ 1
- 0
roles/lxc_guest/defaults/main.yaml View File

@ -5,4 +5,5 @@ distro: 'buster'
vm_size: '5G'
vg_name: '{{ hostvars[ansible_lxc_host]["vg_name"] | default(ansible_lxc_host+"-vg") }}'
host_fqdn: '{{ inventory_hostname }}.dmz.{{ domain }}'
unprivileged: false
...

+ 44
- 0
roles/lxc_guest/files/find_subxid.sh View File

@ -0,0 +1,44 @@
#!/bin/bash
## Detect the first available continuous allocation of subuids/subgids
## of a given size.
##
## Returns output in idmap format:
## <starting_sub[ug]id> <allocation_length>
## Author: Lorenzo Zolfanelli <zolfa@lilik.it>
required_length=65536
function find_interval {
if [ ! -f "$1" ]; then
echo "100000 ${required_length}"
return 0
fi
min_id_list=(100000 $(sed -n -e 's/^[^:]\+:\([0-9]\+\):\([0-9]\+\)/\1/p' $1))
inc_id_list=(0 $(sed -n -e 's/^[^:]\+:\([0-9]\+\):\([0-9]\+\)/\2/p' $1))
rows=$(( ${#min_id_list[*]} - 1 ))
if [ $rows -lt 1 ]; then
echo "100000 ${required_length}"
return 0
fi
for i in $(seq 0 $rows); do
c_start=$(( ${min_id_list[i]} + ${inc_id_list[i]} ))
c_end=$(( ${c_start} + ${required_length} - 1 ))
overlap=0
for j in $(seq 0 $rows); do
j_start=${min_id_list[j]}
j_end=$(( ${min_id_list[j]} + ${inc_id_list[j]} - 1 ))
if ([ "${c_start}" -ge "${j_start}" ] && [ "${c_start}" -le "${j_end}" ]) || ([ "${c_end}" -ge "${j_start}" ] && [ "${c_end}" -le "${j_end}" ]); then
overlap=1
break
fi
done
if [ "${overlap}" -eq "0" ]; then
echo "${c_start} ${required_length}"
return 0
fi
done
}
find_interval /etc/subuid
find_interval /etc/subgid

+ 75
- 1
roles/lxc_guest/tasks/main.yaml View File

@ -21,7 +21,7 @@
- 'lxc'
- block:
- name: 'create the lxc container'
- name: 'privileged | create lxc container'
lxc_container:
name: '{{ vm_name }}'
backing_store: 'lvm'
@ -37,12 +37,72 @@
# leaking when lvm is invoked
environment:
LVM_SUPPRESS_FD_WARNINGS: 1
when: not unprivileged
- name: 'unprivileged | upload bash script'
copy:
src: 'find_subxid.sh'
dest: 'find_subxid.sh'
when: unprivileged
- name: 'unprivileged | get free subxid mappings'
command: 'bash find_subxid.sh'
register: avail_subxid
when: unprivileged
- name: 'unprivileged | set subxid mappings'
set_fact:
subuidmap: '{{ avail_subxid.stdout_lines[0] }}'
subgidmap: '{{ avail_subxid.stdout_lines[1] }}'
when: unprivileged
- name: 'unprivileged | create system subxid mappings'
command: >-
usermod
-v {{ '{}-{}'.format(subuidmap.split(' ')[0],
subuidmap.split(' ')[0]|int+subuidmap.split(' ')[1]|int-1) }}
-w {{ '{}-{}'.format(subgidmap.split(' ')[0],
subgidmap.split(' ')[0]|int+subgidmap.split(' ')[1]|int-1) }}
root
- name: 'unprivileged | create config seed'
copy:
content: |
lxc.idmap = u 0 {{ subuidmap }}
lxc.idmap = g 0 {{ subgidmap }}
dest: '/tmp/lxc_unpriv_config'
when: unprivileged
- name: 'unprivileged | create lxc container'
lxc_container:
name: '{{ vm_name }}'
backing_store: 'lvm'
fs_type: 'xfs'
fs_size: '{{ vm_size }}'
vg_name: '{{ vg_name }}'
lv_name: 'vm_{{ vm_name }}'
container_log: true
template: 'download'
template_options: '-d debian -r {{ distro }} -a amd64'
config: '/tmp/lxc_unpriv_config'
state: 'stopped'
when: unprivileged
- name: 'deploy container config'
template:
src: 'config.j2'
dest: '/var/lib/lxc/{{ vm_name }}/config'
- name: 'unprivileged | tweak config'
lxc_container:
name: '{{ vm_name }}'
container_command: |
echo 'nameserver {{ hostvars | ip_from_inventory('vm_gateway') }}' > /etc/resolv.conf
apt update
apt install -y python3 python3-apt
systemctl mask systemd-journald-audit.socket
state: 'stopped'
- name: 'start container'
lxc_container:
name: '{{ vm_name }}'
@ -52,6 +112,20 @@
tags:
- 'lxc'
- name: 'read unprivileged status from config'
command: >-
grep -e '^lxc.idmap = ' /var/lib/lxc/{{ vm_name }}/config
register: unpriv_status
changed_when: false
failed_when: unpriv_status.rc > 1
- name: 'set unprivileged status from config'
set_fact:
unprivileged: true
subuidmap: '{{ unpriv_status.stdout_lines[0] | replace("lxc.idmap = u 0 ", "") }}'
subgidmap: '{{ unpriv_status.stdout_lines[1] | replace("lxc.idmap = g 0 ", "") }}'
when: unpriv_status.rc == 0
- name: 'update container config'
template:
src: 'config.j2'


+ 25
- 3
roles/lxc_guest/templates/config.j2 View File

@ -1,7 +1,23 @@
lxc.include = /usr/share/lxc/config/debian.common.conf
{% if unprivileged %}
# Distribution configuration (unprivileged)
lxc.include = /usr/share/lxc/config/common.conf
lxc.include = /usr/share/lxc/config/userns.conf
lxc.arch = linux64
lxc.uts.name = {{ vm_name }}
lxc.rootfs.path = lvm:/dev/{{ vg_name }}/vm_{{ vm_name }}
lxc.mount.entry = /sys/kernel/debug sys/kernel/debug none bind,optional 0 0
lxc.mount.entry = /sys/kernel/security sys/kernel/security none bind,optional 0 0
lxc.mount.entry = /sys/fs/pstore sys/fs/pstore none bind,optional 0 0
lxc.mount.entry = mqueue dev/mqueue mqueue rw,relatime,create=dir,optional 0 0
lxc.apparmor.profile = generated
# Container specific configuration
lxc.idmap = u 0 {{ subuidmap }}
lxc.idmap = g 0 {{ subgidmap }}
{% else %}
# Distribution configuration (privileged)
lxc.include = /usr/share/lxc/config/debian.common.conf
lxc.apparmor.profile = generated
lxc.apparmor.allow_nesting = 1
@ -10,6 +26,12 @@ lxc.tty.max = 4
lxc.arch = amd64
lxc.pty.max = 1024
# Container specific configuration
{% endif %}
lxc.uts.name = {{ vm_name }}
lxc.rootfs.path = lvm:/dev/{{ vg_name }}/vm_{{ vm_name }}
# Network configuration
lxc.net.0.type = veth
lxc.net.0.flags = up
lxc.net.0.link = br0


Loading…
Cancel
Save