lhc 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #!/usr/bin/env bash
  2. function print_help {
  3. echo '''
  4. Light Hardened Container / a super light hardened container using alpine and runc
  5. v1.0
  6. Usage: lhc <containername> <containerpath> <datapath>
  7. '''
  8. exit -1
  9. }
  10. get_arch() {
  11. ORIG_ARCH=`arch`
  12. case $ORIG_ARCH in
  13. aarch64)
  14. echo "arm64"
  15. ;;
  16. *)
  17. echo $ORIG_ARCH
  18. ;;
  19. esac
  20. }
  21. # print message to console
  22. # if there's not second parameter this is an info
  23. print_msg() {
  24. CONTENT=$1
  25. TYPE=${2:+"[\e[91mError\e[0m]"}
  26. TYPE=${msgType:-"[\e[92mInfo\e[0m]"}
  27. echo -e $TYPE $CONTENT
  28. }
  29. export ARCH=$(get_arch)
  30. print_msg "Arch: $ARCH"
  31. ## check if container's name is passed
  32. ## TODO, has to check if is not '--help' or '-h'
  33. if [ $# -lt 3 ]
  34. then
  35. print_help
  36. fi
  37. export CONTAINER_NAME=$1
  38. export FULL_CONTAINER_PATH=`readlink -f $2`/$CONTAINER_NAME
  39. export FULL_DATA_PATH=`readlink -f $3`/$CONTAINER_NAME
  40. print_msg "Container Name: '$CONTAINER_NAME'"
  41. print_msg "Creating directory '$FULL_CONTAINER_PATH'"
  42. mkdir $FULL_DATA_PATH
  43. mkdir $FULL_CONTAINER_PATH
  44. print_msg "Decompress alpine rootfs into '$FULL_CONTAINER_PATH'"
  45. sudo tar xf rootfs/alpine-minirootfs-3.5.1-$ARCH.tar.gz -C $FULL_CONTAINER_PATH
  46. chmod 0755 $FULL_CONTAINER_PATH
  47. ## set dns
  48. echo "nameserver 84.200.70.40" >> $FULL_CONTAINER_PATH/etc/resolv.conf
  49. echo "nameserver 4.2.2.2" >> $FULL_CONTAINER_PATH/etc/resolv.conf
  50. ## create user
  51. print_msg "Create user $CONTAINER_NAME"
  52. useradd $CONTAINER_NAME --no-create-home -p=''
  53. export CONTAINER_UID=`id $CONTAINER_NAME -u`
  54. export CONTAINER_GID=`id $CONTAINER_NAME -g`
  55. print_msg "uid: $CONTAINER_UID gid: $CONTAINER_GID"
  56. print_msg "Create container $CONTAINER_NAME"
  57. #export CAPABILITIES=', "CAP_SYS_ADMIN", "CAP_CHOWN", "CAP_FOWNER", "CAP_NET_RAW", "CAP_SETGID", "CAP_SETUID", "CAP_SYS_CHROOT"'
  58. export CAPABILITIES=""
  59. ./runc.template > config.json
  60. ## mount with loggedfs container root
  61. loggedfs -l files_$CONTAINER_NAME.log -c config.xml -p $FULL_CONTAINER_PATH
  62. ## run chroot
  63. print_msg "
  64. \n\n
  65. I'm running chroot now, all opened files will be logged in $CONTAINER_NAME.log\n
  66. \n
  67. - Install and setup your stuff, if you need some package use 'apk update' and 'apk search'\n
  68. - Configure your process to use /data as storage path (/ will be read-only)\n
  69. - Clean $CONTAINER_NAME.log from host machine: 'echo "" > $CONTAINER_NAME.log'\n
  70. - Start your process and try to activate funtionality, exit on done!\n\n
  71. "
  72. mount -t proc proc $FULL_CONTAINER_PATH/proc/
  73. mount -t sysfs sys $FULL_CONTAINER_PATH/sys/
  74. mount -o bind /dev $FULL_CONTAINER_PATH/dev/
  75. chroot $FULL_CONTAINER_PATH sh
  76. ## let's copy all used files/symlink in a new shiny dir
  77. escaped_path=$(echo $FULL_CONTAINER_PATH | sed -e 's/\//\\\//g')
  78. mkdir $FULL_CONTAINER_PATH.tmp
  79. files=`sed -rn "s/.* open (readwrite |writeonly )?$escaped_path\/?(.*) \{.*/\2/p" < files_$CONTAINER_NAME.log | sort | uniq`
  80. links=`sed -rn "s/.* readlink $escaped_path\/?(.*) \{.*/\1/p" < files_$CONTAINER_NAME.log | sort | uniq`
  81. cd $FULL_CONTAINER_PATH
  82. for f in $files; do
  83. echo $f
  84. cp --parents $f $FULL_CONTAINER_PATH.tmp/
  85. done
  86. for l in $links; do
  87. to=$(ls -la $l | sed -rn "s/.*-> (.*)/\1/p")
  88. echo "$l -> $to"
  89. ln -s $to $FULL_CONTAINER_PATH.tmp/$l
  90. done
  91. cd -
  92. umount $FULL_CONTAINER_PATH/proc
  93. umount $FULL_CONTAINER_PATH/dev
  94. umount $FULL_CONTAINER_PATH/sys
  95. umount $FULL_CONTAINER_PATH
  96. ORIG_SIZE=`du -hs $FULL_CONTAINER_PATH`
  97. LHC_SIZE=`du -hs $FULL_CONTAINER_PATH.tmp`
  98. print_msg "ORIGINAL CONTAINER SIZE: `du -hs $FULL_CONTAINER_PATH` // N_FILES: `find $FULL_CONTAINER_PATH | wc -l`"
  99. print_msg "LHC CONTAINER SIZE: `du -hs $FULL_CONTAINER_PATH.tmp` // N_FILES: `find $FULL_CONTAINER_PATH.tmp | wc -l`"
  100. mv $FULL_CONTAINER_PATH $FULL_CONTAINER_PATH.orig
  101. mv $FULL_CONTAINER_PATH.tmp $FULL_CONTAINER_PATH
  102. print_msg "Place specify your init command in config.json and try to run 'runc run $CONTAINER_NAME'$"
  103. cp config.json runc.config/$CONTAINER_NAME.json
  104. ###### CHECK #####