pam_container -- jeszcze lżejsza wirtualizacja
TRANSCRIPT
LXC – namespace'y
ipcns
mntns
netns
pidns
userns
utsns
http
://w
ww
.flic
kr.c
om/ p
hoto
s/m
bost
ock/
4365
3472
85
LXC – namespace'y
ipcns
mntns
netns
pidns
userns
utsns
http
://w
ww
.flic
kr.c
om/ p
hoto
s/m
bost
ock/
4365
3472
85
LXC – namespace'y
/proc/<pid>/ns/*
clone() unshare()
setns()
mount --bindnamespace
:
- ma nazwę
- ży je nawet bez
procesów
PAM
# grep -v ^# /etc/pam.d/common-auth
auth [success=1 default=ignore] \ pam_unix.so nullok_secureauth requisite pam_deny.soauth required pam_permit.soauth optional pam_cap.so
PAM
# grep -v ^# /etc/pam.d/common-auth
auth required pam_python.so \ /lib/security/gandalf.pyauth [success=1 default=ignore] \ pam_unix.so nullok_secureauth requisite pam_deny.soauth required pam_permit.soauth optional pam_cap.so
PAM
# cat /lib/security/gandalf.py
def pam_sm_authenticate(pamh, flags, args): # you shall not pass return pamh.PAM_AUTH_ERR
# wc -l pam_deny.c89
ctypes
from ctypes import CDLL
libc = CDLL('libc.so.6')
# linux/fs.hMS_RDONLY = 1# ...MS_MGC_VAL = 0xC0ED0000
def bind_mount(source, target, rec=False): flags = MS_BIND|MS_MGC_VAL if rec: flags |= MS_REC if libc.mount(source, target, 'none', flags, None) < 0: raise OSError('Failed to bind mount {0} at {1}'.format(source, target))
ctypes
from ctypes import CDLL
libc = CDLL('libc.so.6')
# linux/fs.hMS_RDONLY = 1# ...MS_MGC_VAL = 0xC0ED0000
def bind_mount(source, target, rec=False): flags = MS_BIND|MS_MGC_VAL if rec: flags |= MS_REC if libc.mount(source, target, 'none', flags, None) < 0: raise OSError('Failed to bind mount {0} at {1}'.format(source, target))
przeraża mnie system, w którym
istotna jest wydajność logowania
– Radomir Dopieralski, PyCon.PL 2012
„
pam_container.py
def setup_core_namespaces(user):
if not setns(ns_path('ipc', user)): unshare(CLONE_NEWIPC) pin_ns('ipc', user)
if not setns(ns_path('uts', user)): unshare(CLONE_NEWUTS) sethostname(user) pin_ns('uts', user)
pam_container.py
/var/run/ipcns/user
os.open()+libc.setns()
mount --bind /proc/self/ns/uts /var/run/utsns/user
def setup_core_namespaces(user):
if not setns(ns_path('ipc', user)): unshare(CLONE_NEWIPC) pin_ns('ipc', user)
if not setns(ns_path('uts', user)): unshare(CLONE_NEWUTS) sethostname(user) pin_ns('uts', user)
def setup_net_namespace(user): if setns(ns_path('net', user)): return
veth_id = random_id() veth_master = 'veth' + veth_id veth_slave = 'veths' + veth_id
# ip netns add user # ip link add name veth_master type veth \
# peer name veth_slave # ip link set veth_slave netns user # ip link set veth_master up # brctl addif br0 veth_master
pam_container.py netns▸
def setup_net_namespace(user): if setns(ns_path('net', user)): return
veth_id = random_id() veth_master = 'veth' + veth_id veth_slave = 'veths' + veth_id
# ip netns add user # ip link add name veth_master type veth \
# peer name veth_slave # ip link set veth_slave netns user # ip link set veth_master up # brctl addif br0 veth_master/var/run/netns/user
pam_container.py netns▸
if not setns(ns_path('net', user)): raise RuntimeError('Failed to setns into a freshly created netns')
# ip link set veth_slave name eth0 # ip link set lo up # ip link set eth0 up # ip addr add dev eth0 ... # ip route add default via ...
pam_container.py netns▸
if not setns(ns_path('net', user)): raise RuntimeError('Failed to setns into a freshly created netns')
# ip link set veth_slave name eth0 # ip link set lo up # ip link set eth0 up # ip addr add dev eth0 ... # ip route add default via ...
DHCP:- po FS nam
espace
- proces cały czas w t le
:(
pam_container.py netns▸
/home
user1 .bashrcuser2...
mount --rbind
/ns
user1/home user1user2/home user2...
pam_container.py mntns▸
def pivot_home_dir(user): home_parent = '/ns/{0}/home'.format(user) home = '/ns/{0}/home/{0}'.format(user) bind_mount('/home/{0}'.format(user), home, rec=True) bind_mount(home_parent, home_parent, rec=True) mount(home_parent, '/home', 'none', MS_MOVE, None)
pam_container.py mntns▸
:( brak /proc/self/ns/mnt
mount = restart (poprawione w 3.8)
:) własne /usr/local
ln -s fakeroot sudo
:) nss_extrausers
/var/lib/extrausers/passwd
:) mount / -o remount,ro
uwaga na /home
:) mount /proc -o hidepid=2
w globalnym mntns
pam_container.py mntns▸
/sys/fs/cgroups/cpu/lxc/virt/user1/cron/task1
cpublkiomemory...
LXC+pam_container=♥
pam_container.py cgroups▸
# cat /proc/self/cgroup8:perf_event:/lxc/ovhback7:blkio:/lxc/ovhback6:freezer:/lxc/ovhback5:devices:/lxc/ovhback4:memory:/lxc/ovhback3:cpuacct:/lxc/ovhback2:cpu:/lxc/ovhback1:cpuset:/lxc/ovhback
pam_container.py cgroups▸
CGROUP_ROOT='/sys/fs/cgroup'def setup_cgroups(subgroup): for line in open('/proc/self/cgroup'): idx, subsys, path = \ line.strip().split(':')
cgroup_path = os.path.join(CGROUP_ROOT, subsys, path[1:], subgroup) mkdirs(cgroup_path) # ... with open(os.path.join(cgroup_path, 'tasks'), 'w') as tasks: print >>tasks, os.getpid()
pam_container.py cgroups▸
CGROUP_ROOT='/sys/fs/cgroup'def setup_cgroups(subgroup): for line in open('/proc/self/cgroup'): idx, subsys, path = \ line.strip().split(':')
cgroup_path = os.path.join(CGROUP_ROOT, subsys, path[1:], subgroup) mkdirs(cgroup_path) # ... with open(os.path.join(cgroup_path, 'tasks'), 'w') as tasks: print >>tasks, os.getpid()
pam_container.py cgroups▸