├── .gitignore ├── ADMIN.md ├── AUTHORS ├── LICENSE ├── Makefile ├── README.md ├── SECURITY.md ├── Vagrantfile ├── bin ├── islet_shell └── isletd ├── config ├── islet.conf ├── islet.upstart ├── modules │ └── docker.conf └── plugins │ ├── clear.conf │ ├── del_training.conf │ ├── del_user.conf │ └── restart.conf ├── configure ├── docs └── islet.5 ├── extra ├── Dockerfile-bro ├── argus.conf ├── brolive.conf ├── cadvisor.upstart ├── check_islet.sh ├── ids.conf ├── iptables-rules ├── netsniff-ng.conf ├── ossec.conf ├── sagan.conf ├── silklive.conf ├── tcpdump.conf └── volatility.conf ├── functions.sh ├── init ├── isletd.conf └── isletd.service ├── lib └── libislet ├── modules └── docker └── plugins ├── clear ├── del_container ├── del_user └── restart /.gitignore: -------------------------------------------------------------------------------- 1 | *.bu 2 | *.vagrant 3 | -------------------------------------------------------------------------------- /ADMIN.md: -------------------------------------------------------------------------------- 1 | Administration Guide 2 | ========= 3 | 4 | ### Post-Install First Steps 5 | 6 | Post-installation first steps 7 | 8 | 1. Change the password for the islet user (default: demo) 9 | ``` 10 | passwd demo 11 | ``` 12 | 13 | 2. Create a Docker image for your training environment (see Adding Training Environments) 14 | ``` 15 | cat < Dockerfile 16 | # Build image for C programming 17 | FROM ubuntu 18 | MAINTAINER Jon Schipp 19 | 20 | RUN adduser --disabled-password --gecos "" demo 21 | RUN apt-get update -qq 22 | RUN apt-get install -y build-essential 23 | RUN apt-get install -y git vim emacs nano tcpdump gawk rsyslog 24 | RUN apt-get install -y --no-install-recommends man-db 25 | EOF 26 | 27 | docker build -t gcc-training - < Dockerfile 28 | ``` 29 | 3. Create an ISLET configuration file for the Docker image (see Adding Training Environments) 30 | ``` 31 | make template > /etc/islet/gcc.conf 32 | vim /etc/islet/islet/gcc.conf 33 | # Set ENVIRONMENT variable to name of training environment (e.g. gcc-training) 34 | # Set VIRTUSER variable to name of user in docker image that the student will become (e.g. demo) 35 | ``` 36 | 37 | ### Configuration 38 | 39 | In order of variable precedence 40 | * Global configuration file: */etc/islet/islet.conf* 41 | * Module configuration files: */etc/islet/modules/$MODULE.conf* 42 | * Environments configuration files: */etc/islet/environments/$ENVIRONMENT.conf* 43 | * Plugin configuration files: */etc/islet/plugins/$PLUGIN.conf* 44 | 45 | Settings in the global configuration file are overridden by those in module 46 | config file, and finally those in the environment config file. This means that 47 | you set global defaults and can get more granular with specific environments. 48 | 49 | For each training environment you want available for use by ISLET, create a 50 | a environment configuration file with the necessary settings and place it in the 51 | */etc/islet/environments* directory. These images will be selectable from the ISLET 52 | menu after authentication via SSH. Plugin configurations are also selectable from the menu 53 | and are intended to add functionality. 54 | 55 | Common Tasks: 56 | 57 | * Add another training account for ISLET (used to remotely access e.g. ssh) 58 | 59 | ``` 60 | useradd --create-home --shell /opt/islet/bin/islet_shell training 61 | echo "training:training" | chpasswd 62 | gpasswd -a training docker # User needs to be in the docker grouip 63 | gpasswd -a training islet # User needs to be in the islet group 64 | ``` 65 | 66 | * Change the password of a container user (Not a system account). 67 | 68 | ``` 69 | $ PASS=$(echo "newpassword" | sha1sum | sed 's/ .*//) 70 | $ sqlite3 /var/tmp/islet.db "UPDATE accounts SET password='$PASS' WHERE user='jon';" 71 | $ sqlite3 /var/tmp/islet.db "SELECT password FROM accounts WHERE user='jon';" 72 | aaaaaaa2a4817e5c9a56db45d41ed876e823fcf|1413533585 73 | 74 | ``` 75 | 76 | * Configure container and user lifetime (e.g. conference duration) 77 | 78 | 1. Specify the number of days for user account and container lifetime in: 79 | 80 | ``` 81 | $ grep ^DAYS /etc/islet/islet.conf 82 | DAYS=3 # Length of the event in days 83 | ``` 84 | 85 | Removal scripts are cron jobs that are scheduled in /etc/cron.d/islet 86 | 87 | * Allocate more or less resources for containers, and control other container settings. 88 | These changes will take effect for each newly created container. 89 | - System and use case dependent 90 | 91 | ``` 92 | $ grep -A 5 "Container config /etc/islet/environments/brolive.conf 93 | # Container Configuration 94 | VIRTUSER="demo" # Account used when container is entered (Must exist in container!) 95 | CPUSHARES="1024" # Proportion of cpu share allocation per container 96 | MEMORY="256m" # Amount of memory allocated to each container 97 | SWAP="100m" # Amount of swap memory allocated to each container 98 | HOSTNAME="bro" # Set hostname in container. PS1 will end up as $VIRTUSER@$HOSTNAME:~$ in shell 99 | NETWORK="none" # Disable networking by default: none; Enable networking: bridge 100 | DNS="127.0.0.1" # Use loopback when networking is disabled to prevent error messages from resolver 101 | MOUNT="-v /exercises:/exercises:ro" # Mount point(s), sep. by -v: /src:/dst:attributes, ro = readonly (avoid rw) 102 | OPTIONS="--cap-add=NET_RAW --cap-add=NET_ADMIN" # Apply any other options you want passed to Docker run here 103 | MOTD="Training materials are in /exercises" # Message of the day is displayed before container launch and reattachment 104 | ``` 105 | 106 | * Adding, removing, or modifying exercises 107 | 108 | 1. Make changes in /exercises on the host's filesystem 109 | 110 | * Changes are immediately available for new and existing containers 111 | 112 | # Case Study 113 | 114 | The precursor to ISLET was used to aid the instructers in teaching the Bro platform at BroCon14. 115 | 116 | Workflow: 117 | 1. Install ISLET and dependencies 118 | 2. Build Docker image containing Bro (docker pull broplatform/brolive) 119 | 3. Write a ISLET config file for the Bro image 120 | 4. Set a banner in the ISLET config file for light branding (logo) 121 | 5. Hand out the demo account credentials to your students so they can SSH in 122 | 6. Instruct them on the software 123 | 124 | Here's a brief demonstration: 125 | 126 | ``` 127 | $ ssh demo@live.bro.org 128 | 129 | Welcome to Bro Live! 130 | ==================== 131 | 132 | ----------- 133 | / \ 134 | | ( (0) ) | 135 | | // | 136 | \ <====// / 137 | ----------- 138 | 139 | A place to try out Bro. 140 | 141 | Are you a new or existing user? [new/existing]: new 142 | 143 | A temporary account will be created so that you can resume your session. Account is valid for the length of the event. 144 | 145 | Choose a username [a-zA-Z0-9]: jon 146 | Your username is jon 147 | Choose a password: 148 | Verify your password: 149 | Your account will expire on Fri 29 Aug 2014 07:40:11 PM UTC 150 | 151 | Enjoy yourself! 152 | Training materials are located in /exercises. 153 | e.g. $ bro -r /exercises/beginner/http.pcap 154 | 155 | demo@bro:~$ pwd 156 | /home/demo 157 | demo@bro:~$ which bro 158 | /usr/local/bro/bin/bro 159 | ``` 160 | 161 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Maintainer: 2 | 3 | * Jon Schipp 4 | 5 | Major contributors (> 30 commits): 6 | 7 | * Jon Schipp 8 | 9 | Minor contributors (<= 30 commits): 10 | 11 | * Mike Downey 12 | 13 | Special thanks: 14 | 15 | * Bro Team (bro.org) - for using it and making it possible 16 | * NCSA (Adam Slagell, Warren Raquel, Jeannette Dopheide) - for supporting the effort 17 | * CITES (Wayland Morgan) - for promoting and using it for digital forensics courses at UIUC 18 | * CriticalStack (Liam Randall) - for promoting and using it 19 | 20 | Notes: 21 | 22 | Want to join the team? Submit enough great patches over a long time, 23 | implement what's available in the Github issues and show an ongoing, 24 | active interest in supporting ISLET. What's in it for you? Being involved 25 | in a useful project that helps things like hacker conferences and user group 26 | events, plus I'll buy you a beer, meal, or something. 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | # http://opensource.org/licenses/NCSA 2 | # ISLET is based on the bro-sandbox scripts I wrote during my employment at the NCSA 3 | Copyright (c) 2014 National Center for Supercomputing Applications 4 | All rights reserved. 5 | 6 | Developed by: CyberSecurity Directorate, National Center for Supercomputing Applications 7 | University of Illinois at Urbana-Champaign 8 | http://www.ncsa.illinois.edu/ 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files 11 | (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, 12 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. 16 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers 17 | in the documentation and/or other materials provided with the distribution. Neither the names of , nor the names of its contributors may be used to endorse or promote products derived from this Software 19 | without specific prior written permission. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS 23 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: default help install uninstall pull update logo mrproper package 2 | 3 | PROG = islet 4 | VERSION = 1.0.0 5 | CONFIG_DIR = /etc/$(PROG) 6 | INSTALL_DIR = /opt/$(PROG) 7 | LIB_DIR = $(INSTALL_DIR)/lib 8 | BIN_DIR = $(INSTALL_DIR)/bin 9 | PLUGIN_DIR = $(INSTALL_DIR)/plugins 10 | MODULE_DIR = $(INSTALL_DIR)/modules 11 | MAN_DIR = /usr/share/man 12 | FUNCTIONS = ./functions.sh 13 | USER = demo 14 | PASS = demo 15 | GROUP = islet 16 | IPTABLES = /etc/network/if-pre-up.d/iptables-rules 17 | UPSTART = /etc/init 18 | REPO = $(shell grep url .git/config) 19 | PACKAGE = deb 20 | Q = @ 21 | bold = $(shell tput bold) 22 | underline = $(shell tput smul) 23 | normal = $(shell tput sgr0) 24 | red = $(shell tput setaf 1) 25 | yellow = $(shell tput setaf 3) 26 | 27 | default: help 28 | 29 | help: 30 | $(Q)echo "$(bold)ISLET (v$(VERSION)) installation targets:$(normal)" 31 | $(Q)echo " $(red)install$(normal) - Install and configure islet on the host" 32 | $(Q)echo " $(red)install-contained$(normal) - Install islet as container, with little modification to host" 33 | $(Q)echo " $(red)uninstall$(normal) - Uninstalls islet ($(yellow)Backup first!$(normal))" 34 | $(Q)echo " $(red)update$(normal) - Update code and reinstall islet" 35 | $(Q)echo " $(red)mrproper$(normal) - Remove all files not in source distribution" 36 | $(Q)echo "$(bold)System configuration targets$(bold):$(normal)" 37 | $(Q)echo " $(red)user-config$(normal) - Configure demo user for islet" 38 | $(Q)echo " $(red)security-config$(normal) - Configure security controls (sshd_config)" 39 | $(Q)echo " $(red)iptables-config$(normal) - Install iptables rules (def: /etc/network/if-pre-up.d/)" 40 | $(Q)echo "$(bold)Miscellaneous targets:$(normal)" 41 | $(Q)echo " $(red)install-brolive-config$(normal) - Install and configure Brolive image" 42 | $(Q)echo " $(red)template$(normal) - Print ISLET config template to stdout" 43 | $(Q)echo " $(red)package$(normal) - Create package from an ISLET installation (def: deb)" 44 | $(Q)echo " $(red)logo$(normal) - Print logo to stdout" 45 | 46 | install: install-files configuration 47 | 48 | install-contained: 49 | $(Q)echo " $(yellow)Installing $(PROG)$(normal)" 50 | mkdir -m 755 -p $(CONFIG_DIR)/modules $(CONFIG_DIR)/environments $(CONFIG_DIR)/plugins 51 | install -o 0 -g 0 -m 644 config/islet.conf $(CONFIG_DIR)/$(PROG).conf 52 | install -o 0 -g 0 -m 644 config/plugins/*.conf $(CONFIG_DIR)/plugins/ 53 | install -o 0 -g 0 -m 644 config/modules/*.conf $(CONFIG_DIR)/modules/ 54 | sed -i.bu "s|ISLETVERS|$(VERSION)|" $(CONFIG_DIR)/islet.conf 55 | sed -i.bu "s|USERACCOUNT|$(USER)|g" $(CONFIG_DIR)/islet.conf 56 | rm -f *.bu 57 | docker run -d --name="islet" \ 58 | -v /usr/bin/docker:/usr/bin/docker:ro \ 59 | -v /var/lib/docker/:/var/lib/docker:rw \ 60 | -v /sbin/iptables:/sbin/iptables:ro \ 61 | -v /sbin/sysctl:/sbin/sysctl:ro \ 62 | -v /exercises:/exercises:ro \ 63 | -v /etc/islet:/etc/islet:ro \ 64 | -v /var/run/docker.sock:/var/run/docker.sock \ 65 | --cap-add=NET_ADMIN \ 66 | -p $(PORT):22 jonschipp/islet 67 | install -o 0 -g 0 -m 644 config/islet.upstart $(UPSTART)/islet.conf 68 | $(Q)echo " $(bold)--> Connect to ISLET on $(normal)$(underline)SSH port $(PORT)$(normal)" 69 | 70 | install-files: 71 | $(Q)echo " $(yellow)Installing $(PROG)$(normal)" 72 | mkdir -m 755 -p $(CONFIG_DIR)/modules $(CONFIG_DIR)/environments $(CONFIG_DIR)/plugins 73 | mkdir -m 755 -p $(LIB_DIR) $(BIN_DIR) $(PLUGIN_DIR) $(MODULE_DIR) 74 | install -o 0 -g 0 -m 644 config/islet.conf $(CONFIG_DIR)/ 75 | install -o 0 -g 0 -m 644 config/plugins/*.conf $(CONFIG_DIR)/plugins/ 76 | install -o 0 -g 0 -m 644 config/modules/*.conf $(CONFIG_DIR)/modules/ 77 | install -o 0 -g 0 -m 644 lib/libislet $(LIB_DIR)/libislet 78 | install -o 0 -g 0 -m 755 bin/islet_shell $(BIN_DIR)/$(PROG)_shell 79 | install -o 0 -g 0 -m 755 bin/isletd $(BIN_DIR)/$(PROG)d 80 | install -o 0 -g 0 -m 755 plugins/* $(PLUGIN_DIR)/ 81 | install -o 0 -g 0 -m 755 modules/* $(MODULE_DIR)/ 82 | install -o 0 -g 0 -m 644 docs/islet.5 $(MAN_DIR)/man5/islet.5 83 | $(Q)test -f /sbin/start && install -o 0 -g 0 -m 644 init/isletd.conf /etc/init || true 84 | $(Q)test -d /usr/lib/systemd/system/ && install -o 0 -g 0 -m 644 init/isletd.service /usr/lib/systemd/system || true 85 | $(Q)echo " $(bold)--> Configuration directory is$(normal) $(underline)$(CONFIG_DIR)$(normal)" 86 | $(Q)echo " $(bold)--> Install directory is$(normal) $(underline)$(INSTALL_DIR)$(normal)" 87 | 88 | configuration: 89 | $(Q)echo " $(yellow)Post-install configuration$(normal)" 90 | sed -i.bu "s|ISLETVERS|$(VERSION)|" $(CONFIG_DIR)/islet.conf 91 | sed -i.bu "s|USERACCOUNT|$(USER)|g" $(CONFIG_DIR)/islet.conf 92 | sed -i.bu "s|LOCATION|$(CONFIG_DIR)/$(PROG).conf|g" $(BIN_DIR)/* 93 | $(Q)rm -f $(CONFIG_DIR)/*.bu $(BIN_DIR)/*.bu 94 | $(Q)echo " $(yellow)Starting isletd$(normal)" 95 | $(Q)test -f /etc/init/isletd.conf && start isletd || true 96 | $(Q)test -f /usr/lib/systemd/system/isletd.service && systemctl enable isletd && systemctl start isletd || true 97 | 98 | uninstall: 99 | $(Q)echo " $(yellow)Uninstalling $(PROG)$(normal)" 100 | rm -rf $(CONFIG_DIR) 101 | rm -rf $(INSTALL_DIR) 102 | rm -f /var/tmp/$(PROG)_db 103 | rm -f /etc/security/limits.d/islet.conf 104 | rm -f $(MAN_DIR)/man5/islet.5 105 | fgrep -q $(USER) /etc/passwd && userdel -r $(USER) || true 106 | fgrep -q $(GROUP) /etc/group && groupdel $(GROUP) || true 107 | 108 | mrproper: 109 | $(Q)echo " $(yellow)Removing files not in source$(normal)" 110 | $(Q)git ls-files -o | xargs rm -rf 111 | 112 | pull: 113 | $(Q)echo " $(yellow)Pulling latest code from:$(normal) $(underline)$(REPO)$(normal)" 114 | $(Q)git checkout master 1>/dev/null 2>/dev/null 115 | $(Q)git pull 116 | 117 | update: pull 118 | $(Q)echo " $(yellow)Installing latest code$(normal)" 119 | make install 120 | 121 | install-brolive-config: 122 | $(FUNCTIONS) install_sample_configuration 123 | mkdir -m 755 -p $(CONFIG_DIR)/environments 124 | install -o 0 -g 0 -m 644 extra/brolive.conf $(CONFIG_DIR)/environments/brolive.conf 125 | $(Q)echo " $(yellow)Try it out: ssh demo@$(normal)" 126 | 127 | install-sample-nsm: install-sample-nsm-configs 128 | $(FUNCTIONS) install_nsm_configurations 129 | $(Q)echo " $(yellow)Try it out: ssh demo@$(normal)" 130 | 131 | install-sample-nsm-configs: 132 | mkdir -m 755 -p $(CONFIG_DIR) 133 | install -o 0 -g 0 -m 644 extra/brolive.conf $(CONFIG_DIR)/environments/brolive.conf 134 | install -o 0 -g 0 -m 644 extra/ids.conf $(CONFIG_DIR)/environments/ids.conf 135 | install -o 0 -g 0 -m 644 extra/argus.conf $(CONFIG_DIR)/environments/argus.conf 136 | install -o 0 -g 0 -m 644 extra/tcpdump.conf $(CONFIG_DIR)/environments/tcpdump.conf 137 | install -o 0 -g 0 -m 644 extra/netsniff-ng.conf $(CONFIG_DIR)/environments/netsniff-ng.conf 138 | install -o 0 -g 0 -m 644 extra/volatility.conf $(CONFIG_DIR)/environments/volatility.conf 139 | install -o 0 -g 0 -m 644 extra/sagan.conf $(CONFIG_DIR)/environments/sagan.conf 140 | 141 | install-sample-distros: 142 | $(FUNCTIONS) install_sample_distributions 143 | mkdir -m 755 -p $(CONFIG_DIR)/environments 144 | 145 | install-sample-cadvisor: 146 | docker run -d -v /var/run:/var/run:rw -v /sys:/sys:ro -v /var/lib/docker/:/var/lib/docker:ro -p 8080:8080 --name="cadvisor" google/cadvisor:latest 147 | install -o 0 -g 0 -m 644 extra/cadvisor.upstart $(UPSTART)/cadvisor.conf 148 | 149 | install-docker: 150 | $(FUNCTIONS) install_docker 151 | 152 | user-config: 153 | $(FUNCTIONS) user_configuration $(USER) $(PASS) $(GROUP) $(BIN_DIR)/$(PROG)_shell 154 | 155 | security-config: 156 | $(FUNCTIONS) security_configuration $(USER) $(BIN_DIR)/$(PROG)_shell 157 | 158 | bro-training: install user-config security-config install-docker install-brolive-config 159 | 160 | iptables-config: 161 | install -o 0 -g 0 -m 750 extra/iptables-rules $(IPTABLES) 162 | $(IPTABLES) 163 | 164 | package: 165 | $(Q)! command -v fpm 1>/dev/null && echo "$(yellow)fpm is not installed or in PATH, try \`\`gem install fpm''.$(normal)" \ 166 | || fpm -s dir -t $(PACKAGE) -n "islet" -v $(VERSION) /etc/islet /opt/islet \ 167 | 168 | logo: 169 | $(FUNCTIONS) logo 170 | 171 | template: 172 | $(Q) $(FUNCTIONS) template 173 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Isolated, Scalable, & Lightweight Environment for Training 2 | ========= 3 | 4 | [![Join the chat at https://gitter.im/jonschipp/ISLET](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/jonschipp/ISLET?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 5 | 6 | Making IT training a smoother process...
7 | 8 | ISLET is a container based system for teaching Gnu/Linux based software, which requires minimal effort for participation and configuration. ISLET supports running a variety different training environments concurrently, and has a plugin system for extending functionality. ISET is modular in design, which makes it easy to add different run times and is flexible to different needs. The participation barrier is set very low, so students will only need an SSH or similar remote access client to connect. 9 | 10 | ![ISLET Screenshot](http://www.jonschipp.com/islet/islet.png) 11 | 12 | #### Uses 13 | 14 | * Event and staff training 15 | * Capture the flag competitions 16 | * Development environments 17 | 18 | #### Who Uses ISLET? 19 | ISLET has been used in official training for two leading open source network security projects. These, in addition to other notable examples, are listed below. 20 | 21 | * [Bro](https://bro.org) Team 22 | * [Suricata](http://suricata-ids.org/) Team 23 | * [CriticalStack](https://criticalstack.com) 24 | * University of Illinois at Urbana-Champaign Digital Forensics 2 Course 25 | * [OpenNSM](http://open-nsm.net) 26 | * ACM [GNU/LUG](http://www.gnulug.org/) at UIUC 27 | 28 | If you would like commercial support for ISLET, including creating and deploying custom training environments, contact me through my company [Draconyx](http://www.draconyx.net/). 29 | 30 | ## Design 31 | 32 | These images are a little old, but they mostly represent the design. 33 | 34 | #### Simplified Diagram 35 | 36 | ![ISLET Diagram](http://www.jonschipp.com/islet/islet_diagram.jpg) 37 | 38 | #### Detailed Flowchart 39 | 40 | ![ISLET Flowchart](http://www.jonschipp.com/islet/islet_flowchart.png) 41 | 42 | ## Installation 43 | 44 | The installation of ISLET is very simple. First, grab the dependencies and then 45 | install ISLET. 46 | 47 | ### Dependencies 48 | 49 | * Linux, Bash, Cron, OpenSSH, Make, SQLite, and Docker Engine 50 | 51 | The configure script will check for dependencies (except Docker) 52 | ```shell 53 | ./configure 54 | ``` 55 | 56 | ![ISLET Configure Screenshot](http://www.jonschipp.com/islet/islet_configure.png) 57 | 58 | Typically, all you need is Make, SQLite and Docker Engine (for Debian/Ubuntu): 59 | ```shell 60 | apt-get install make sqlite 61 | ``` 62 | See Docker's documentation for installation instructions. 63 | 64 | ### Install 65 | 66 | After installing the dependencies, run: 67 | ```shell 68 | make user-config && make install && make security-config 69 | ``` 70 | 71 | See the menu for more options, `make` 72 | ![ISLET Make Screenshot](http://www.jonschipp.com/islet/islet_make.png) 73 | 74 | Target: | Description: 75 | ----------------|---------------- 76 | install | Install ISLET: install-files + configuration 77 | update | Downloads and install new code (custom changes to default files will be overwritten) 78 | uninstall | Uninstall ISLET (Recommended to backup your stuff first) 79 | mrproper | Removes files that did not come with the source 80 | user-config | Configures a user account called demo w/ password demo 81 | security-config | Configures sshd with islet relevant security in mind 82 | iptables-config | Installs iptables ruleset 83 | 84 | GNU `make` accepts arguments if you want a customized installation (*not supported*): 85 | ```shell 86 | make user-config INSTALL_DIR=/usr/local/islet USER=training PASS=training 87 | make install INSTALL_DIR=/usr/local/islet USER=training 88 | make security-config INSTALL_DIR=/usr/local/islet USER=training 89 | make uninstall INSTALL_DIR=/usr/local/islet USER=training 90 | ``` 91 | 92 | Variable: | Description: 93 | ----------------|---------------- 94 | CONFIG_DIR | ISLET configuration directory (def: /etc/islet) 95 | INSTALL_DIR | ISLET installation directory (def: /opt/islet) 96 | USER | User account created with user-config target (def: demo) 97 | PASS | User account password created with user-config target (def: demo) 98 | IPTABLES | Iptables ruleset (def: /etc/network/if-pre-up.d/iptables-rules) 99 | 100 | ## Updating 101 | 102 | Updating an existing ISLET installation is very simple: 103 | 104 | ```shell 105 | tar zcf islet_config.tgz /etc/islet # Backup configs 106 | make update 107 | tar zxf islet_config.tgz -C / # Restore configs 108 | ``` 109 | 110 | # Adding Training Environments 111 | 112 | See Docker's [image documentation](https://docs.docker.com/engine/reference/commandline/build/) 113 | 114 | 1. Build or pull in a new Docker image 115 | 116 | 2. Create an ISLET config file for that image (training environment). You can use `make template` for an example. 117 | 118 | 3. Place it in /etc/islet/environments with a `.conf` extension. 119 | 120 | It should now be available from the selection menu upon login. 121 | 122 | ![ISLET Configs Screenshot](http://www.jonschipp.com/islet/islet_configs.png) 123 | 124 | More info: 125 | See the SECURITY file for more information on manually securing the system. 126 | See the ADMIN file for more information on administering the system. 127 | [Mailing List] (https://groups.google.com/d/forum/islet) 128 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Recommendations 2 | 3 | Once ISET is installed, users may want to consider reconfiguring their systems to enhance security. The list below is for manually configuring security controls and documenting recommendations. 4 | Most of these are satisified by `make` targets. 5 | 6 | #### SSH: _/etc/ssh/sshd_config_ 7 | 8 | The following command will configure sshd_config to match the next example, with the exception of modifying LoginGraceTime. 9 | 10 | ```shell 11 | make security-config 12 | ``` 13 | 14 | ```shell 15 | LoginGraceTime 30s 16 | ClientAliveInterval 15 17 | ClientAliveCountMax 10 18 | 19 | #Subsystem sftp /usr/libexec/openssh/sftp-server 20 | 21 | Match User training 22 | ForceCommand /opt/islet/bin/islet_shell 23 | X11Forwarding no 24 | AllowTcpForwarding no 25 | PermitTunnel no 26 | PermitOpen none 27 | MaxAuthTries 3 28 | MaxSessions 1 29 | AllowAgentForwarding no 30 | PermitEmptyPasswords no 31 | ``` 32 | 33 | #### Drop capabilities in containers 34 | 35 | ISLET includes security options in `$CONFIG_DIR/modules/docker.conf`, which can be used to easily add or drop kernel capabilities(7) 36 | (and apply ulimit values to containers) to all Docker environments. They can be set in any ISLET configuration file. 37 | Only add what you need to run the software in the container. 38 | 39 | #### System limitation contraints 40 | 41 | **Note:** ISLET with Docker 1.6 supports passing ulimit settings in config files. 42 | 43 | The following command will configure decent ulimit settings for docker processes. 44 | These have the effect of restricting the user's environment inside the container. 45 | 46 | Adjust as necessary: _/etc/init/docker.conf_ 47 | ``` 48 | # BEGIN ISLET Additions 49 | limit nofile 1000 2000 # Limit number of open files 50 | limit nproc 1000 2000 # Prevent fork bombs 51 | limit fsize 100000000 200000000 # Limit file sizes to max of 200MB 52 | # END 53 | ``` 54 | 55 | #### Separate storage for containers 56 | 57 | ``` 58 | service docker stop 59 | rm -rf /var/lib/docker/* 60 | mkfs.ext2 /dev/sdb1 61 | mount -o defaults,noatime,nodiratime /dev/sdb1 /var/lib/docker 62 | tail -1 /etc/fstab 63 | /dev/sdb1 /var/lib/docker ext2 defaults,noatime,nodiratime,nobootwait 0 1 64 | service docker start 65 | ``` 66 | 67 | #### Limit container storage size to prevent DoS or resource abuse 68 | 69 | Switching storage backends to devicemapper allows for disk quotas. 70 | Set dm.basesize to the maximum size the container can grow to (def: 10G) 71 | 72 | **Note:** Currently unstable, and all existing container and image data will be lost. 73 | 74 | ``` 75 | service docker stop 76 | rm -rf /var/lib/docker/* 77 | docker -d --storage-driver=devicemapper --storage-opt dm.basesize=3G & 78 | sleep 3 && pkill docker 79 | tail -1 /etc/default/docker 80 | DOCKER_OPTS="--storage-driver=devicemapper --storage-opt dm.basesize=3G" 81 | start docker 82 | ``` 83 | 84 | **Note:** There's currently a bug in devicemapper that may cause docker to fail to run containers [more info](https://github.com/docker/docker/issues/4036). 85 | 86 | #### Rate limiting 87 | 88 | Use iptables for protection of the SSH service. 89 | ``` 90 | make iptables-config 91 | ``` 92 | 93 | #### GRSecurity kernel patches 94 | 95 | To aid in protecting the host system, it's recommended to patch the Linux kernel [more info](https://grsecurity.net/) 96 | 97 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! 5 | VAGRANTFILE_API_VERSION = "2" 6 | 7 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| 8 | 9 | config.vm.box = "trusty" 10 | config.vm.box_url = "https://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box" 11 | config.vm.synced_folder ".", "/islet" 12 | 13 | config.vm.provider "virtualbox" do |vb| 14 | vb.gui = false 15 | vb.name = "islet-dev" 16 | vb.customize ["modifyvm", :id, "--memory", "1024"] 17 | vb.customize ["modifyvm", :id, "--cpus", 1] 18 | end 19 | 20 | config.vm.provision "shell", inline: <<-SHELL 21 | apt-get update -qq 22 | apt-get install -yq cowsay git make sqlite pv 23 | 24 | if test -d /islet; then 25 | cd /islet 26 | make install-docker && ./configure && make logo && 27 | make user-config && make install && make security-config && make iptables-config || { printf "ISLET install failed\!\n" && exit 1; } 28 | make install-sample-nsm-configs 29 | printf "\nTry it out: ssh -p 2222 demo@127.0.0.1 -o UserKnownHostsFile=/dev/null\n" 30 | fi 31 | SHELL 32 | 33 | end 34 | -------------------------------------------------------------------------------- /bin/islet_shell: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Global Declarations 3 | ARG="$1" 4 | ARGC=$# 5 | CONFIG=LOCATION 6 | COUNT=0 7 | LIST=() 8 | ANIMATE=$(which pv 2>/dev/null) 9 | ANIMATE_SPEED=90 10 | AVAILABLE_USER=1 11 | TIMEOUT="8h" 12 | 13 | # Store some stuff, these can be referenced from config files 14 | read CLIENT SRCPORT SERVER DSTPORT <<<"${SSH_CONNECTION}" 15 | export CLIENT SRCPORT SERVER DSTPORT IP="$SERVER" 16 | export SSH_TTY 17 | export DISPLAY="${CLIENT}:0" 18 | export TERM 19 | export PPID HOST_PORT="$PPID" 20 | export TMOUT=60 21 | export CONFIG 22 | readonly CLIENT SRCPORT SERVER DSTPORT SSH_TTY TERM PPID TMOUT 23 | 24 | err(){ 25 | local message="$1" 26 | logger -s -p local0.notice -t "islet" "$0: $message" 27 | exit 1 28 | } 29 | 30 | # Get global variables 31 | if [[ -f "$CONFIG" ]]; then 32 | . "$CONFIG" 33 | . "$LIBISLET" 34 | readonly CONFIG 35 | else 36 | err "Error: ${CONFIG:-config} or ${LIBISLET:-libislet} not found!" 37 | fi 38 | 39 | # Export import_configs function to use in modules 40 | export -f import_configs 41 | 42 | # Rewrite MODULE variable for ease of use 43 | MODULE="$INSTALL_DIR/modules/$MODULE" 44 | 45 | clear 46 | 47 | readonly TIME=$(date +"%s") 48 | readonly EXPIRATION=$(date --date=@$((TIME+86400*DAYS)) +"%c") 49 | 50 | # Display ISLET Banner 51 | if [[ "$ARG" != "nobanner" ]]; then 52 | test -f "${ANIMATE:-notset}" && islet_banner | pv -qL "$ANIMATE_SPEED" || islet_banner 53 | # Press key to continue 54 | timecount $TMOUT 55 | clear && echo 56 | fi 57 | 58 | ####################################### 59 | # Create SQLite database 60 | # Globals: 61 | # DB - Location of database file 62 | # USER - Owner of database file 63 | # GROUp - Group of database file 64 | # Arguments: 65 | # None 66 | # Returns: 67 | # None 68 | ####################################### 69 | 70 | create_db() { 71 | sqlite3 "$DB" </dev/null | grep -q SQLite; then 102 | rm -f "$DB" 2>/dev/null 103 | create_db 104 | test $? -eq 0 && return 0 || quit "Unable to create $DB" 105 | fi 106 | { [[ $(stat -c %U ${DB}) == "$USER" ]] || chown "$USER" "$DB" 2>/dev/null; } || quit "Fatal: cannot set owner ${USER} on ${DB}, do you have permission?" 107 | { [[ $(stat -c %G ${DB}) == "$GROUP" ]] || chown :"${GROUP}" "$DB" 2>/dev/null; } || quit "Fatal: cannot set group ${GROUP} on ${DB}, do you have permission?" 108 | { [[ $(stat -c %a ${DB}) == 660 ]] || chmod 660 "$DB" 2>/dev/null; } || quit "Fatal: cannot set modes 660 on ${DB}, do you have permission?" 109 | } 110 | 111 | ####################################### 112 | # Configures autocompletion 113 | # Globals: 114 | # TMP - Temporary directory 115 | # Arguments: 116 | # None 117 | # Returns: 118 | # None 119 | ####################################### 120 | 121 | enable_autocompletion(){ 122 | # Hackish way 123 | TMP="/tmp/islet" 124 | [[ "$PWD" == "$TMP" ]] || { mkdir -p "$TMP" && cd "$TMP"; } 125 | [[ "$PWD" == "$TMP" ]] && touch {new,existing,yes,no} 126 | } 127 | 128 | ####################################### 129 | # Prompt user if they're new or existing 130 | # Globals: 131 | # None 132 | # Arguments: 133 | # None 134 | # Returns: 135 | # None 136 | ####################################### 137 | 138 | identify(){ 139 | local choice 140 | enable_autocompletion 141 | ask "Are you a new or existing user? " 142 | prompt "choice" "notsecret" "new" "existing" 143 | # Normalize to lowercase 144 | choice=${choice,,} 145 | 146 | if [[ "$choice" =~ ^[n][e][w]$ ]] || 147 | [[ "$choice" =~ ^[e][x][i][s][t][i][n][g]$ ]] || 148 | [[ "$choice" =~ ^n$ ]] || [[ "$choice" =~ ^e$ ]] 149 | then 150 | { [[ "$choice" =~ ^[n][e][w]$ ]] || [[ "$choice" =~ ^n$ ]]; } && new_user 151 | { [[ "$choice" =~ ^[e][x][i][s][t][i][n][g]$ ]] || [[ "$choice" =~ ^e$ ]]; } && existing_user 152 | else 153 | try_again 154 | fi 155 | } 156 | 157 | ################################################### 158 | # Get username and password for new user 159 | # Globals: 160 | # AVAILABLE_USER - 1 if user already exists in DB 161 | # Arguments: 162 | # None 163 | # Returns: 164 | # None 165 | ################################################### 166 | 167 | new_user(){ 168 | notice "A temporary account will be created so that you can resume your session." 169 | echo 170 | 171 | until test "$AVAILABLE_USER" -ne 1 172 | do 173 | choose_username && verify_new_user 174 | done 175 | 176 | until [[ "$PASSWORD" ]] && [[ "$PASSWORD_VERIFY" ]] 177 | do 178 | choose_password && verify_new_password 179 | done 180 | } 181 | 182 | choose_username(){ 183 | ask "Choose a username: " 184 | prompt "USERNAME" "notsecret" "a-zA-Z0-9" 185 | [[ "$USERNAME" ]] || { alert "Empty value not permitted" && return 1; } 186 | USERNAME=$(sanitize "$USERNAME") && export USERNAME && return 0 187 | } 188 | 189 | choose_password(){ 190 | ask "Choose a password: " 191 | prompt "PASSWORD" "secret" "a-zA-Z0-9{${MIN_PASSWD_LEN},}" 192 | [[ "$PASSWORD" ]] || { alert "\nEmpty value not permitted" && return 1; } 193 | echo 194 | ask "Verify your password: " 195 | prompt "PASSWORD_VERIFY" "secret" 196 | [[ "$PASSWORD_VERIFY" ]] || { alert "\nEmpty value not permitted" && return 1; } 197 | echo 198 | } 199 | 200 | ################################################### 201 | # Handles container reattachment for existing users 202 | # Globals: 203 | # FAILURE_COUNT - Max # of authentication failures 204 | # BASE - Environment config base filename 205 | # Arguments: 206 | # None 207 | # Returns: 208 | # None 209 | ################################################### 210 | 211 | existing_user(){ 212 | local password 213 | local hash 214 | local auth 215 | local exists 216 | local count=1 217 | notice "Your previous account is only valid for the length of the event, after that you must create a new account" 218 | echo 219 | while test "$count" -le "$FAILURE_COUNT"; do 220 | ask "Username: " 221 | prompt "USERNAME" "notsecret" 222 | USERNAME=$(sanitize $USERNAME) && export USERNAME 223 | ask "Password: " 224 | prompt "PASSWORD" "secret" 225 | echo 226 | 227 | hash=$(echo "$PASSWORD" | sha1sum | sed 's/ .*//') 228 | auth=$(sqlite3 $DB "SELECT user, password FROM accounts WHERE user='$USERNAME' AND password='$hash';") 229 | 230 | [[ "$auth" ]] && info "Success" && sleep 1 && break 231 | notice "Login failed, try again ("$count"/"$FAILURE_COUNT")." 232 | let count++ 233 | done 234 | let count-- 235 | [[ $auth ]] || quit "Too many failed attempts! ("$count"/"$FAILURE_COUNT")." 236 | } 237 | 238 | ################################################### 239 | # Checks if user already exists in database 240 | # Globals: 241 | # USERNAME - Username to validate 242 | # AVAILABLE_USER - 0 if username is note taken 243 | # Arguments: 244 | # None 245 | # Returns: 246 | # None 247 | ################################################### 248 | 249 | verify_new_user(){ 250 | local exists="$(sqlite3 "$DB" "SELECT user FROM accounts WHERE user='$USERNAME';")" 251 | if [[ "$exists" ]]; then 252 | AVAILABLE_USER=1 253 | notice "User already exists! Try a different one." 254 | else 255 | AVAILABLE_USER=0 256 | echo "Your username is ${MF}$USERNAME${N}" 257 | fi 258 | } 259 | 260 | ########################################################### 261 | # Validate password, hash, and write account to database 262 | # Globals: 263 | # PASSWORD - Password to validate and store in db 264 | # USERNAME - Used to create account in database 265 | # FAILURE_COUNT - Max # of authentication failures 266 | # CLIENT - IP address of connecting user 267 | # EXPIRATION - Date/time account expires 268 | # Arguments: 269 | # None 270 | # Returns: 271 | # None 272 | ########################################################### 273 | 274 | verify_new_password(){ 275 | local count=1 276 | local hash 277 | while [[ "$PASSWORD" != "$PASSWORD_VERIFY" ]] || [[ "${#PASSWORD}" -lt "$MIN_PASSWD_LEN" ]]; do 278 | if [[ "$count" -lt "$FAILURE_COUNT" ]]; then 279 | notice "Passwords do not match or meet length requirements (${BF}"${MIN_PASSWD_LEN}"${N}${Y}). Try again ("$count"/"$FAILURE_COUNT")." 280 | choose_password 281 | else 282 | quit "Too many failed attempts! ("$count"/"$FAILURE_COUNT")." 283 | fi 284 | let count++ 285 | done 286 | 287 | readonly hash=$(echo "$PASSWORD" | sha1sum | sed 's/ .*//') 288 | sqlite3 "$DB" "pragma foreign_keys = on; INSERT INTO accounts VALUES('"${USERNAME}"','${hash}', strftime('%s', 'now'));" 2>/dev/null || quit "Couldn't write to $DB!" 289 | log "${USERNAME}: Account created from $CLIENT" 290 | 291 | echo "Your account will expire on ${MF}$EXPIRATION${N}" 292 | } 293 | 294 | menu_loop(){ 295 | while true; do 296 | { [[ -d "$CONFIG_DIR" ]] && cd "$CONFIG_DIR"; } || quit "Unable to access ${CONFIG_DIR}!" 297 | LIST=() 298 | config_menu 299 | done 300 | } 301 | 302 | config_menu(){ 303 | local count=0 304 | local menu 305 | local attach 306 | # Configuration menu 307 | notice "\t\t\t\tAvailable configurations:\n" 308 | printf '\t\t\t%-29s %-7s %-30s\n' "${B}Configuration${N}" "|" "${B}Description${N}" 309 | printf '\t\t\t%-30s %-7s %-30s\n' "${BF}$SPACER1${N}" "|" "${BF}$SPACER1${N}" 310 | 311 | # Iterate over configuration files in $CONFIG_DIR and display them as options 312 | # It prints the config file ($config) and its description ($DESCRIPTION) 313 | unset BANNER VISIBLE ENABLE PLUGIN config config_name 314 | for config in environments/*.conf plugins/*.conf; do 315 | [[ -f "$config" ]] && . "$config" 316 | if [[ "$VISIBLE" = "yes" || "$ENABLE" = "yes" ]]; then 317 | config_name="$(basename $config)" # blah.conf 318 | printf '\t\t\t%-30s %-7s %-30s\n' "${WF}$config_name${N}" "|" "${U}$DESCRIPTION${N}" 319 | LIST+=("$config") 320 | fi 321 | unset BANNER VISIBLE ENABLE PLUGIN config config_name 322 | done 323 | 324 | # Quit if there are no config files present 325 | [[ "${#LIST[@]}" -eq 0 ]] && quit "\t\t\tNo configurations available!" 326 | echo && unset BANNER 327 | notice "Choose a number to load the configuration (or ^C to exit):" 328 | 329 | PS3="${Y}[${N}${BF}Choice${N}${Y}]${N}: " 330 | # Here the user chooses the configuration from the menu 331 | # Inherit the variables from the config file after selection 332 | select CONFIGURATION in "${LIST[@]}" 333 | do 334 | menu=1 335 | if [[ -f "$CONFIG_DIR/$CONFIGURATION" ]]; then 336 | . "$CONFIG_DIR/$CONFIGURATION" # /etc/islet + / + environments/blah.conf 337 | # Export for use in modules 338 | BASE=$(basename $(basename $CONFIGURATION) .conf) 339 | export CONFIGURATION # environments/blah.conf 340 | export BASE # blah 341 | break 342 | else 343 | let count++ 344 | if [[ "$count" -ge "$FAILURE_COUNT" ]]; then 345 | quit "Too many failed attempts! ($count/$FAILURE_COUNT)" 346 | fi 347 | alert "Invalid choice! Try again ($count/$FAILURE_COUNT)" 348 | fi 349 | done 350 | 351 | unset LIST 352 | 353 | # If configuration is for plugin then execute it 354 | if [[ $PLUGIN ]]; then 355 | if [[ -f "$INSTALL_DIR/plugins/$PLUGIN" ]]; then 356 | . "$INSTALL_DIR/plugins/$PLUGIN" 357 | else 358 | alert "Plugin $PLUGIN does not exist..contact the administrator." 359 | fi 360 | # Go back to menu_loop after 361 | unset PLUGIN 362 | return 0 363 | fi 364 | 365 | # Avoid launching last value of CONFIGURATION when user sends EOF 366 | [[ $menu ]] || quit "Quit by user..." 367 | unset menu 368 | 369 | # Display environment banner 370 | [[ "$BANNER" ]] && clear && echo "$BANNER" 371 | 372 | # This is how we handle using the same account for multiple environments 373 | attach=$(sqlite3 $DB "SELECT environment FROM environments WHERE user='$USERNAME' AND environment='$BASE'";) 374 | if [[ $attach ]]; then 375 | $MODULE attach # Call function in module to attach to existing environment 376 | else 377 | $MODULE start # Call function in module to create environment 378 | fi 379 | } 380 | 381 | ########################################################### 382 | # Reprompt if user did not select new or existing user 383 | # Globals: 384 | # None 385 | # Arguments: 386 | # None 387 | # Returns: 388 | # None 389 | ########################################################### 390 | 391 | try_again(){ 392 | local try 393 | ask "I didn't understand your response. Would you like to try again? " 394 | prompt "try" "notsecret" "yes" "no" 395 | # Normalize to lowercase 396 | try=${try,,} 397 | if [[ "$try" =~ ^[yn]$ ]] || [[ "$try" =~ ^[y][e][s]$ ]] || [[ "$try" =~ ^[n][o]$ ]]; then 398 | [[ "$try" =~ ^y$ ]] || [[ "$try" =~ ^[y][e][s]$ ]] && identify 399 | [[ "$try" =~ ^n$ ]] || [[ "$try" =~ ^[n][o]$ ]] && quit "user decided to leave from try_again" 400 | else 401 | quit "User forced to exit from try_again because of invalid response to question" 402 | fi 403 | } 404 | 405 | trap 'echo; quit "Trap received, exiting..."' 1 2 3 20 406 | # It all begins here 407 | is_sqlite 408 | $MODULE verify 409 | identify 410 | menu_loop 411 | exit 412 | -------------------------------------------------------------------------------- /bin/isletd: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Global Declarations 3 | export TERM="xterm" 4 | CONFIG=LOCATION 5 | . $CONFIG 6 | 7 | ################################################### 8 | # Error and log - fallback to syslog 9 | # Globals: 10 | # None 11 | # Arguments: 12 | # message - Message to write out and log 13 | # Returns: 14 | # None 15 | ################################################### 16 | 17 | syslog(){ 18 | local message="$1" 19 | logger -s -p local0.notice -t "isletd" "$0: $message" 20 | } 21 | 22 | ################################################### 23 | # Write to islet log file 24 | # Globals: 25 | # None 26 | # Arguments: 27 | # message - Message to write out and log 28 | # Returns: 29 | # None 30 | ################################################### 31 | 32 | logfile(){ 33 | local message="$1" 34 | printf "$(date) isletd: $message\n" 35 | } 36 | 37 | ################################################### 38 | # 39 | # Globals: 40 | # LOG - Log file for writing 41 | # Arguments: 42 | # None 43 | # Returns: 44 | # None 45 | ################################################### 46 | 47 | enable_logging(){ 48 | if [[ "$LOG" ]]; then 49 | dirname="$(dirname $LOG)" 50 | [[ -d "$dirname" ]] || mkdir -p "$dirname" 51 | [[ -f "$LOG" ]] || touch "$LOG" 52 | [[ -w "$LOG" ]] && exec >> "$LOG" || return 1 53 | else 54 | return 1 55 | fi 56 | return 0 57 | } 58 | 59 | ################################################### 60 | # Load variables from configuration files 61 | # Globals: 62 | # CONFIG - Main configuration file 63 | # LIBISLET - Load library containing functions 64 | # MODULE - Runtime configuration file 65 | # Arguments: 66 | # None 67 | # Returns: 68 | # None 69 | ################################################### 70 | 71 | load_config(){ 72 | local environment="$1" 73 | local module 74 | if [[ -f "$CONFIG" ]]; then 75 | . "$CONFIG" 76 | module="$CONFIG_DIR/modules/${MODULE}.conf" 77 | [[ -f "$LIBISLET" ]] && . "$LIBISLET" || logfile "Unable to open $LIBISLET" 78 | [[ -f "$module" ]] && . "$module" || logfile "Unable to open $module" 79 | [[ -f "$environment" ]] && . "$environment" || logfile "Unable to open $environment" 80 | export CONFIG LIBISLET 81 | else 82 | logfile "$FUNCNAME: Unable to read $CONFIG" 83 | return 1 84 | fi 85 | } 86 | 87 | ################################################### 88 | # Clean up variables after each iteration 89 | # Globals: 90 | # Many 91 | # Arguments: 92 | # None 93 | # Returns: 94 | # None 95 | ################################################### 96 | 97 | clear_vars(){ 98 | # Main globals 99 | unset LIBISLET DB MODULE 100 | # Cleanup variables 101 | unset DAYS 102 | } 103 | 104 | ################################################### 105 | # Get time for time based tasks 106 | # Globals: 107 | # None 108 | # Arguments: 109 | # None 110 | # Returns: 111 | # None 112 | ################################################### 113 | 114 | get_time(){ 115 | TIME=$(date +"%s") 116 | EXPIRATION=$(date --date=@$((TIME+86400*DAYS)) +"%c") 117 | } 118 | 119 | ################################################### 120 | # Remove users older than days 121 | # Globals: 122 | # DB 123 | # Arguments: 124 | # days - Value of DAYS, option in config file 125 | # Returns: 126 | # None 127 | ################################################### 128 | 129 | cleanup_by_user(){ 130 | local days="$1" 131 | if file "$DB" 2>/dev/null | grep -q SQLite; then 132 | sqlite3 "$DB" "pragma foreign_keys = on; DELETE FROM accounts WHERE (strftime('%s','now') - ts) >= (${days}*86400);" 133 | fi 134 | } 135 | 136 | ################################################### 137 | # Execute module tasks 138 | # Globals: 139 | # DEBUG - Debugging option from configs 140 | # Arguments: 141 | # module - Path to module script 142 | # task - Name of function to execute in module 143 | # opt - An option passed to function (optional) 144 | # env - Training environment config file 145 | # Returns: 146 | # None 147 | ################################################### 148 | 149 | execute_task(){ 150 | local module="$1" 151 | local task="$2" 152 | local option="$3" 153 | local environment="$4" 154 | "$module" "$task" "$opt" "$env" 155 | rc="$?" 156 | [[ "$DEBUG" == "yes" ]] && logfile "Executed $task with status code $rc" 157 | } 158 | 159 | ################################################### 160 | # Daemonize, run indefinitely every 60 seconds 161 | # Globals: 162 | # Many 163 | # Arguments: 164 | # None 165 | # Returns: 166 | # None 167 | ################################################### 168 | 169 | main(){ 170 | # We're a daemon, we don't end 171 | while true; do 172 | ## Global tasks 173 | sleep ${INTERVAL:-60} # Default to one minute 174 | # Remove users which are older than $DAYS days 175 | [[ "$DAYS" ]] && cleanup_by_user "$DAYS" 176 | ## Per config tasks 177 | for environment in $CONFIG_DIR/environments/*.conf $CONFIG_DIR/islet.conf; do 178 | clear_vars 179 | if [[ -r "$environment" ]]; then 180 | # Obtain configurations 181 | load_config "$environment" || continue 182 | # Execute cleanup functions from module 183 | MODULE="$INSTALL_DIR/modules/$MODULE" 184 | if [[ -x "$MODULE" ]]; then 185 | # Execute module tasks here 186 | echo 187 | else 188 | logfile "Error: $MODULE does not exist or is not executable, skipping module maintenance." 189 | fi 190 | fi 191 | done 192 | done 193 | } 194 | 195 | trap 'logfile "Stopped: Signal caught"; exit 0' 2 3 15 196 | 197 | enable_logging || syslog "Cannot write to ${LOG}, check permissions" 198 | logfile "Started" 199 | main 200 | logfile "Stopped" 201 | -------------------------------------------------------------------------------- /config/islet.conf: -------------------------------------------------------------------------------- 1 | ################################# 2 | # ISLET Main Configuration File # 3 | ################################# 4 | 5 | VERSION=ISLETVERS 6 | 7 | ######################## 8 | # System Configuration # 9 | ######################## 10 | 11 | # Paths 12 | CONFIG_DIR="/etc/islet" # Directory to search for configuration files. Used by scripts. 13 | INSTALL_DIR="/opt/islet" # ISLET installation directory 14 | LIBISLET="$INSTALL_DIR/lib/libislet" # Common functions are stored in libislet 15 | DB="/var/tmp/islet.db" # Credentials database. Must be readable by $USER 16 | LOG="/var/log/islet/islet.log" # Islet log file 17 | 18 | MODULE="docker" # Training environment runtime system 19 | USER="USERACCOUNT" # Linux system user created for ssh'ing to ISLET, give account to trainees 20 | GROUP="islet" # Linux system group for accounts that need to access ISLET 21 | INTERVAL="60" # How often isletd should run maintenance tasks (in seconds) 22 | DEBUG="no" # Enable debugging info to stdout and syslog 23 | 24 | ######################### 25 | # Network Configuration # 26 | ######################### 27 | 28 | INTERFACE="eth0" # Physical interface packets are arriving on 29 | BIND="172.17.42.1" # IP address to use to access services on containers (def: docker0) 30 | 31 | ########################## 32 | # Security Configuration # 33 | ########################## 34 | 35 | VISIBLE="no" # This config file should not be visible from config selection menu 36 | FAILURE_COUNT=3 # Number of failed choice attempts before exiting (username, password, config) 37 | MIN_PASSWD_LEN=4 # Minimum length of password for user accounts 38 | DAYS=3 # Container+user lifetime specified in days. Removed after # days by cron jobs 39 | TIMEOUT="8h" # Max runtime of containers, accepts timeout(1) arguments 40 | 41 | ################################## 42 | # Global Container Configuration # 43 | ################################## 44 | 45 | GLOBAL_OPTIONS="" # Apply options to all configs, line should not be present in per image configs 46 | export PLATFORM=islet # Exported to container's environment. Made available using ENVS in per image config 47 | -------------------------------------------------------------------------------- /config/islet.upstart: -------------------------------------------------------------------------------- 1 | description "ISLET container" 2 | author "Jon Schipp" 3 | start on filesystem and started docker 4 | stop on runlevel [!2345] 5 | respawn 6 | script 7 | /usr/bin/docker start -a islet 8 | end script 9 | -------------------------------------------------------------------------------- /config/modules/docker.conf: -------------------------------------------------------------------------------- 1 | ##################################### 2 | # Docker Backend Configuration File # 3 | ##################################### 4 | 5 | # Options in this file are set per container via ``docker run''- 6 | # and can be overridden in per image config files 7 | 8 | ######################## 9 | # System Configuration # 10 | ######################## 11 | 12 | MODULE="docker" 13 | DOCKER_DIR="/var/lib/docker" # Location of Docker directory 14 | METADATA="/var/lib/docker/containers/*/config.json" # Path of container metadata 15 | 16 | ######################### 17 | # Network Configuration # 18 | ######################### 19 | 20 | INTERFACE="eth0" # Physical interface packets are arriving on 21 | BIND="172.17.42.1" # IP address to use to access services on containers (def: docker0) 22 | 23 | ################################## 24 | # Global Container Configuration # 25 | ################################## 26 | 27 | GLOBAL_OPTIONS="" # Apply options to all configs, line should not be present in per image configs 28 | export PLATFORM=islet # Exported to container's environment. Made available using ENVS in per image config 29 | 30 | ########################## 31 | # Security Configuration # 32 | ########################## 33 | 34 | VISIBLE="no" # This config file should not be visible from config selection menu 35 | REMOVE="no" # Container is removed after exit, user cannot re-attach and resume work 36 | TIMEOUT="8h" # Max runtime of containers, accepts timeout(1) arguments 37 | DAYS=3 # Container+user lifetime specified in days. Removed after # days by cron jobs 38 | 39 | ################################# 40 | # Ulimit Settings for Containers 41 | ################################# 42 | # Docker 1.6+ (otherwise ignored) 43 | # Formats: 44 | # - soft:hard e.g. ULIMIT_NPROC="1024:2048" 45 | # - soft and hard same value e.g. ULIMIT_NPROC="2048" 46 | 47 | ULIMIT_CORE="" # The maximum size of core files created 48 | ULIMIT_CPU="" # The maximum amount of cpu time (in seconds) 49 | ULIMIT_DATA="" # The maximum size of a process's data segment 50 | ULIMIT_FSIZE="" # The maximum size of files (in bytes) created by the shell 51 | ULIMIT_LOCKS="" # The maximum number of file locks 52 | ULIMIT_MEMLOCK="" # The maximum size (in bytes) that may be locked into memory 53 | ULIMIT_MSGQUEUE="" # The maximum number of bytes in POSIX message queues 54 | ULIMIT_NICE="" # The maximum scheduling priority ("nice") 55 | ULIMIT_NOFILE="" # The maximum number of open file descriptors 56 | ULIMIT_NPROC="" # The maximum number of processes available to a single user 57 | ULIMIT_RSS="" # The maximum resident set size (in bytes) 58 | ULIMIT_RTPRIO="" # The maximum real-time scheduling priority 59 | ULIMIT_RTTIME="" # The maximum amount of cpu time under real time scheduling (in microseconds) 60 | ULIMIT_SIGPENDING="" # The maximum number of pending signals 61 | ULIMIT_STACK="" # The maximum stack size (in bytes) 62 | 63 | ##################################### 64 | # Kernel Capabilities for Containers 65 | ##################################### 66 | 67 | # Select all 68 | DROP_ALL="no" # Drop all capabilities (overrides individuals) 69 | ADD_ALL="no" # Add all capabilities (overrides individuals) 70 | 71 | # Docker defaults (ISLET turns them off by default) 72 | # 5 | # Subject to the GNU GPL 6 | 7 | # Get colors from libislet 8 | LIBISLET=lib/libislet 9 | [ -f $LIBISLET ] && source $LIBISLET 10 | 11 | # Global Declarations 12 | OK=0 13 | CRITICAL=1 14 | DEPENDS="bash make sshd sqlite3" 15 | MISSING=() 16 | DEBIAN=0 17 | NO="${Y}[${N}${RF}NO${N}${Y}]${N}" 18 | YES="${Y}[${N}${BF}YES${N}${Y}]${N}" 19 | BULLET="${Y}[${N}${BF}*${N}${Y}]${N}" 20 | 21 | check_arch() 22 | { 23 | echo -n "${BULLET} Checking arch ... " 24 | ARCH=$(getconf LONG_BIT) 25 | if [ $ARCH -ne 64 ]; then 26 | echo "$NO Not a 64-bit system" 27 | MISSING+=('64-bit') 28 | else 29 | echo "$YES 64-bit system" 30 | fi 31 | } 32 | 33 | check_linux() 34 | { 35 | echo -n "${BULLET} Checking Linux ... " 36 | 37 | if [[ "$(uname)" != "Linux" ]]; then 38 | echo "$NO Linux not found" 39 | MISSING+=('Linux') 40 | else 41 | echo "$YES Linux found" 42 | fi 43 | } 44 | 45 | is_debian() 46 | { 47 | test -f /etc/debian_version && DEBIAN=1 48 | } 49 | 50 | check_dependencies() 51 | { 52 | local depends=$1 53 | echo -n "${BULLET} Checking $depends ... " 54 | 55 | if [[ "x$(which $depends 2>/dev/null)" == "x" ]]; then 56 | MISSING+=("$depends") 57 | else 58 | echo "$YES $depends found" 59 | fi 60 | } 61 | 62 | check_bash_version() 63 | { 64 | echo -n "${BULLET} Checking bash version ... " 65 | ! [[ "x$(which bash 2>/dev/null)" == "x" ]] && vers=$(bash -c 'echo $BASH_VERSION') 66 | echo $vers | grep -q '^[45]' && echo "$YES 4.0+ found" || echo "$NO 4.0+ not found" 67 | } 68 | 69 | check_arch 70 | check_linux 71 | is_debian 72 | 73 | for i in $DEPENDS 74 | do 75 | check_dependencies $i 76 | done 77 | 78 | check_bash_version 79 | 80 | if [ ${#MISSING[@]} -gt 0 ]; then 81 | count=$(echo ${#MISSING[@]}) 82 | echo -n "${Y}[${N}${RF}!${N}${Y}]${N} Missing dependencies: " 83 | for (( i=0; i<${count}; i++ )); do 84 | echo -n "${MISSING[$i]} " 85 | done 86 | echo 87 | exit $CRITICAL 88 | else 89 | echo "${BULLET} All dependencies found, now you can run \`\`make install''" 90 | fi 91 | -------------------------------------------------------------------------------- /docs/islet.5: -------------------------------------------------------------------------------- 1 | .Dd December 03, 2014 2 | .Dt ISLET 5 3 | .Os 4 | .Sh NAME 5 | .Nm Isolated, Scalable, and Lightweight Environment for Training 6 | .Nd Configuration details 7 | .Sh DESCRIPTION 8 | An ISLET config file consists of variables that will be passed to the backend. 9 | These settings define the operation of the training environments. An environment setting is of the form, 10 | .Bd -literal 11 | NAME="value" 12 | .Ed 13 | 14 | There cannot be any whitespace between the variable name, the assignment operator, and the value. 15 | Also, quoting is not required but recommended for security and whitespace issues. 16 | ISLET has three types of configuration files that differ only with scope: 17 | .Bd -literal -offset indent 18 | Config Description 19 | ------ -------------- 20 | Global Global values inherited by all environments but optionally superseded by module and environment configuration 21 | Module Defines behavior of software that creates the environments but optionally superseded by environment configuration 22 | Environment Environment configurations are specific to a training environment 23 | Plugin Plugin configurations are used to launch plugins 24 | .Ed 25 | 26 | The default locations for ISLET are 27 | .Bd -literal -offset indent 28 | Location Description 29 | -------- -------------- 30 | /etc/islet Configuration directory 31 | /etc/islet/modules Module configuration directory 32 | /etc/islet/plugins Plugin configuration directory 33 | /etc/islet/environments Environment configuration directory 34 | /opt/islet Installation directory 35 | /opt/islet/bin ISLET scripts 36 | /opt/islet/modules Modules directory 37 | /opt/islet/plugins Plugin directory 38 | /opt/islet/lib Library 39 | .Ed 40 | 41 | .Pa /etc/islet/islet.conf 42 | is the global configuration file and must exist. 43 | Settings in this file are inherited into all ISLET scripts. Environment configuration files only pertain 44 | to a specific training environment and are inherited last overriding any variables of the module and global 45 | configuration files. 46 | 47 | At the very least an environment configuration must contain the variable ENVIRONMENT set to the name of the training environment as used by the backend. 48 | For example, when using the Docker Engine backend, the value of ENVIRONMENT must match the name of an image from ``docker images''. 49 | Variables used to configure environments are passed directly to the backend e.g. 50 | .Xr docker-run 1 51 | .Pp 52 | .Sh EXAMPLE GLOBAL CONFIG FILE 53 | .Bd -literal 54 | ################################# 55 | # ISLET Main Configuration File # 56 | ################################# 57 | 58 | # System Configuration 59 | CONFIG_DIR="/etc/islet" # Directory to search for configuration files, used by scripts. 60 | INSTALL_DIR="/opt/islet" # ISLET installation directory 61 | LIBISLET="$INSTALL_DIR/lib/libislet" # Common functions are stored in libislet 62 | DB="/var/tmp/islet.db" # Credentials database. Must be readable by $USER 63 | 64 | MODULE="docker" # Training environment runtime system 65 | USER="demo" # Linux system user created for ssh'ing to ISLET, give account to trainees 66 | DEBUG="no" # Enable debugging info to stdout and syslog 67 | 68 | # Security Configuration 69 | VISIBLE="no" # This config file is visible from config selection menu 70 | ENABLE="no" # Same as VISIBLE 71 | FAILURE_COUNT=3 # Number of failed choice attempts before exiting (username, password, config) 72 | DAYS=3 # Container+user lifetime specified in days. Removed after # days by cron jobs 73 | TIMEOUT="8h" # Max runtime of environment, accepts timeout(1) arguments 74 | 75 | # Global Container Configuration 76 | GLOBAL_OPTIONS="" # Apply options to all configs, line should not be present in environment configs 77 | export PLATFORM=islet" # Exported to container's environment. Made available using ENVS in environment configuration. 78 | .Ed 79 | .Sh EXAMPLE ENVIRONMENT CONFIG FILE 80 | .Bd -literal 81 | # Environment Configuration 82 | ENVIRONMENT="broplatform/brolive" # Launch containers from this Docker image, must match name in ``docker images'' 83 | DESCRIPTION="Bro 2.3.1 training image" # Brief description of image, listed in islet_shell selection menu 84 | 85 | # Security Configuration 86 | VISIBLE="yes" # This config file is visible from config selection menu 87 | DAYS=3 # Container lifetime specified in days, removed after x days by cron jobs 88 | 89 | # Container Configuration 90 | VIRTUSER="demo" # Account used when container is entered (Must exist in container!) 91 | WORKDIR="/home/$VIRTUSER" # User begins in this directory, usually its VIRTUSER's HOME 92 | COMMAND="bash" # Command to launch on container entry, typically used to get a shell 93 | CPUSHARE=1024 # Proportion of cpu share allocation per container (Option used to be CPU) 94 | MEMORY="256m" # Amount of memory allocated to each container (Option used to be RAM) 95 | SWAP="100m" # Amount of swap memory allocated to each container 96 | HOSTNAME="bro" # Set hostname in container. PS1 will end up as $VIRTUSER@$HOSTNAME:~$ in shell 97 | NETWORK="none" # Disable networking by default: none; Enable networking: bridge 98 | DNS="127.0.0.1" # Use loopback when networking is disabled to prevent error messages from resolver 99 | MOUNT="-v /exercises:/exercises:ro" # Mount point(s), sep. by -v: /src:/dst:attributes, ro = readonly (avoid rw) 100 | CAP_NET_ADMIN="yes" # Configure the network 101 | CAP_NET_RAW="yes" # Use RAW and PACKET sockets 102 | LOCAL_OPTIONS="" # Apply any other options you want passed to docker run here 103 | export ENVIRONMENT # Export variables for container environment 104 | ENVS="PLATFORM ENVIRONMENT" # Make exported variables available in container 105 | 106 | # Branding & Information 107 | MOTD="Training materials are in /exercises" # Message of the day is displayed before entering container 108 | BANNER=" 109 | ================================ 110 | Welcome to the Bro configuration 111 | 112 | ----------- 113 | / \\ 114 | | ( (0) ) | 115 | | // | 116 | \\ <====// / 117 | ----------- 118 | 119 | A place to try out Bro. 120 | 121 | ================================ 122 | " 123 | .Ed 124 | 125 | .Ed 126 | .Sh EXAMPLE PLUGIN CONFIG FILE 127 | ISLET supports plugins which are any interpreted scripts that can be run as the ISLET user. 128 | A plugin configuration file describes the plugin. The most important setting being the variable PLUGIN which points to the script to execute. 129 | Plugin configuration files are placed in /etc/islet/plugins and the plugin scripts are located in /opt/islet/plugins. 130 | .Bd -literal 131 | ENABLE="yes" # Enable plugin 132 | DESCRIPTION="Restart ISLET session" # Description of plugin 133 | PLUGIN="restart" # Filename of plugin to run 134 | .Ed 135 | 136 | ISLET ships with a few default plugins: 137 | .Bd -literal -offset indent 138 | Plugin Description 139 | ------ -------------- 140 | restart Restart the ISLET program without reconnecting 141 | del_user Deletes the current user's account from the database 142 | del_training Deletes a user's training environment, data contained will be lost 143 | clear Used to clear the screen 144 | .Ed 145 | 146 | .Sh SEE ALSO 147 | .Xr docker-run 1 , 148 | .Sh AUTHORS 149 | .An Jon Schipp jonschipp@gmail.com, http://jonschipp.com 150 | .Sh BUGS 151 | -------------------------------------------------------------------------------- /extra/Dockerfile-bro: -------------------------------------------------------------------------------- 1 | # Bro Sandbox - Bro 2.3.1 2 | # 3 | # VERSION 1.0.8 4 | FROM ubuntu 5 | MAINTAINER Jon Schipp 6 | 7 | # Specify container username e.g. training, demo 8 | ENV VIRTUSER demo 9 | # Specify Bro version to download and install (e.g. bro-2.2, bro-2.3) 10 | ENV BRO_VERSION bro-2.3.1 11 | # Place to install bro 12 | ENV DST /home/$VIRTUSER/bro 13 | 14 | RUN apt-get update 15 | RUN apt-get install -y build-essential cmake make gcc g++ flex bison libpcap-dev libgeoip-dev libssl-dev python-dev zlib1g-dev libmagic-dev swig2.0 wget 16 | RUN apt-get install -y gawk vim emacs nano screen tmux 17 | RUN adduser --disabled-password --gecos "" $VIRTUSER 18 | RUN su -l -c "wget http://www.bro.org/downloads/release/$BRO_VERSION.tar.gz && tar -xzf $BRO_VERSION.tar.gz" $VIRTUSER 19 | RUN su -l -c "cd $BRO_VERSION && ./configure --prefix=$DST && make && make install" $VIRTUSER 20 | RUN rm -rf /home/$VIRTUSER/$BRO_VERSION* 21 | RUN echo "PATH=$PATH:/usr/local/bro/bin/" > /etc/profile.d/bro.sh && chmod 555 /etc/profile.d/bro.sh 22 | RUN echo "export TMOUT=1800; readonly TMOUT" > /etc/profile.d/timeout.sh && chmod 555 /etc/profile.d/timeout.sh 23 | RUN su -l -c 'ln -s /exercises exercises' $VIRTUSER 24 | RUN ln -s $DST /usr/local/bro 25 | RUN setcap cap_net_raw,cap_net_admin=eip $DST/bin/bro 26 | -------------------------------------------------------------------------------- /extra/argus.conf: -------------------------------------------------------------------------------- 1 | # System Configuration 2 | ENVIRONMENT="jonschipp/islet-argus" # Launch containers from this image. Over-ridden by per-image config files 3 | DESCRIPTION="ARGUS training image" # Brief description of image, listed in islet_shell selection menu 4 | 5 | # Security Configuration 6 | ENABLE="yes" # Enable config from selection menu 7 | DAYS="3" # Container lifetime specified in days, removed after x days by cron jobs 8 | 9 | # Container Configuration 10 | VIRTUSER="demo" # Account used when container is entered (Must exist in container!) 11 | CPUSHARES="1024" # Proportion of cpu share allocation per container 12 | MEMORY="256m" # Amount of memory allocated to each container 13 | SWAP="10m" # Amount of swap memory allocated to each container 14 | HOSTNAME="argus" # Set hostname in container. PS1 will end up as $VIRTUSER@$HOSTNAME:~$ in shell 15 | NETWORK="none" # Disable networking by default: none; Enable networking: bridge 16 | DNS="127.0.0.1" # Use loopback when networking is disabled to prevent error messages from resolver 17 | MOUNT="-v /exercises:/exercises:ro" # Mount point(s), sep. by -v: /src:/dst:attributes, ro = readonly (avoid rw) 18 | CAP_NET_ADMIN="yes" # Configure the network 19 | CAP_NET_RAW="yes" # Use RAW and PACKET sockets 20 | export ENVIRONMENT PLATFORM=islet # Export variables for container environment 21 | ENVS="ENVIRONMENT PLATFORM" # Make exported variables available in container 22 | WORKDIR="/home/$VIRTUSER" # User begins in this directory, usually its VIRTUSER's HOME 23 | COMMAND="bash" # Command to launch on container entry, typically used to get a shell 24 | 25 | # Branding & Information 26 | MOTD="Training materials are in /exercises" # Message of the day is displayed before entering container 27 | BANNER=" 28 | ================================================================= 29 | Welcome to ARGUS Live! 30 | 31 | <--------------------------------------------> 32 | Argus, the network Audit Record Generation and Utilization System. 33 | <--------------------------------------------> 34 | 35 | A place to try out ARGUS 36 | ================================================================= 37 | " 38 | -------------------------------------------------------------------------------- /extra/brolive.conf: -------------------------------------------------------------------------------- 1 | # System Configuration 2 | ENVIRONMENT="broplatform/brolive" # Launch containers from this image. Over-ridden by per-image config files 3 | DESCRIPTION="Bro 2.4 training image" # Brief description of image, listed in islet_shell selection menu 4 | 5 | # Security Configuration 6 | ENABLE="yes" # Enable config from selection menu 7 | DAYS="3" # Container lifetime specified in days, removed after x days by cron jobs 8 | 9 | # Container Configuration 10 | VIRTUSER="demo" # Account used when container is entered (Must exist in container!) 11 | CPUSHARES="1024" # Proportion of cpu share allocation per container 12 | MEMORY="256m" # Amount of memory allocated to each container 13 | SWAP="10m" # Amount of swap memory allocated to each container 14 | HOSTNAME="bro" # Set hostname in container. PS1 will end up as $VIRTUSER@$HOSTNAME:~$ in shell 15 | NETWORK="none" # Disable networking by default: none; Enable networking: bridge 16 | DNS="127.0.0.1" # Use loopback when networking is disabled to prevent error messages from resolver 17 | MOUNT="-v /exercises:/exercises:ro" # Mount point(s), sep. by -v: /src:/dst:attributes, ro = readonly (avoid rw) 18 | CAP_NET_RAW="yes" # Use RAW and PACKET sockets 19 | LOCAL_OPTIONS="" # Apply any other options you want passed to Docker run here 20 | export ENVIRONMENT PLATFORM=islet # Export variables for container environment 21 | ENVS="ENVIRONMENT PLATFORM" # Make exported variables available in container 22 | WORKDIR="/home/$VIRTUSER" # User begins in this directory, usually its VIRTUSER's HOME 23 | COMMAND="bash" # Command to launch on container entry, typically used to get a shell 24 | 25 | # Branding & Information 26 | MOTD="Training materials are in /exercises" # Message of the day is displayed before entering container 27 | BANNER=" 28 | ================================ 29 | Welcome to the Bro configuration 30 | 31 | ----------- 32 | / \\ 33 | | ( (0) ) | 34 | | // | 35 | \\ <====// / 36 | ----------- 37 | 38 | A place to try out Bro. 39 | 40 | ================================ 41 | " 42 | -------------------------------------------------------------------------------- /extra/cadvisor.upstart: -------------------------------------------------------------------------------- 1 | description "cAdvisor container" 2 | author "Jon Schipp" 3 | start on filesystem and started docker 4 | stop on runlevel [!2345] 5 | respawn 6 | script 7 | /usr/bin/docker start -a cadvisor 8 | end script 9 | -------------------------------------------------------------------------------- /extra/check_islet.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Author: Jon Schipp 4 | # Date: 10-08-2014 5 | ######## 6 | # Examples: 7 | 8 | # 1.) Check status of the ISLET configuration 9 | # $ ./check_islet.sh -f /etc/islet/islet.conf -T status 10 | 11 | # 2.) Check all configurations for images 12 | # $ ./check_islet.sh -T available -s islet.conf,test.conf 13 | 14 | # 3.) Count configurations marked invisible 15 | # $ ./check_islet.sh -T unavailable -c 0 16 | 17 | # 4.) Check container sizes in bytes 18 | # $ ./check_islet.sh -T size -w 536870912 -c 1073741824 19 | 20 | # 5.) Check database 21 | # $ ./check_islet.sh -T database 22 | 23 | # NRPE 24 | 25 | # command[check_islet_status]=/usr/bin/sudo /usr/local/nagios/libexec/check_islet.sh -T status 26 | # command[check_islet_available]=/usr/bin/sudo /usr/local/nagios/libexec/check_islet.sh -T available -s islet.conf 27 | 28 | # Nagios Exit Codes 29 | OK=0 30 | WARNING=1 31 | CRITICAL=2 32 | UNKNOWN=3 33 | 34 | # Default location of global config 35 | # Set this to the proper location if your installation differs or use ``-f'' 36 | CONFIG=/etc/islet/islet.conf 37 | 38 | usage() 39 | { 40 | cat < Set optional absolute path of global config (def: $CONFIG) 46 | -T Check type, "status/available/unavailable/print" 47 | status - Checks status of islet by verifying configuration 48 | available - Check available configurations for images 49 | unavailable - Check configurations marked as invisible 50 | size - Check container sizes (\`\`-w|c '') 51 | database - Check database properties 52 | -s Item(s) to skip (sep:,) "islet.conf,test.conf" 53 | -c Critical value 54 | -w Warning value 55 | 56 | Usage: $0 -f /etc/islet/islet.conf -T status 57 | $0 -T available -s islet.conf,test.conf -c 0 58 | EOF 59 | } 60 | 61 | argcheck() { 62 | # if less than n argument 63 | if [[ $ARGC -lt $1 ]]; then 64 | echo "Missing arguments! Use \`\`-h'' for help." 65 | exit 1 66 | fi 67 | } 68 | 69 | check_values(){ 70 | if [[ ${1:-$MISSING} -gt $CRIT ]]; then 71 | echo "CRITICAL: Failed item count of ${1:-$MISSING} is greater than $CRIT" 72 | exit $CRITICAL 73 | elif [[ ${1:-$MISSING} -gt $WARN ]]; then 74 | echo "WARNING: Failed item count of ${1:-$MISSING} is greater than $WARN" 75 | exit $WARNING 76 | else 77 | echo "SUCCESS: Everything is referenced properly" 78 | exit $OK 79 | fi 80 | } 81 | 82 | # Declarations 83 | CRIT=0 84 | WARN=0 85 | 86 | LIST_CHECK=0 87 | SIZE_CHECK=0 88 | AVAILABLE_CHECK=0 89 | UNAVAILABLE_CHECK=0 90 | VARIABLE_CHECK=0 91 | STATUS_CHECK=0 92 | PRINT_CHECK=0 93 | DATABASE_CHECK=0 94 | MISSING=0 95 | COUNT=0 96 | ARGC=$# 97 | LIST=() 98 | 99 | argcheck 1 100 | 101 | while getopts "hfc:p:s:T:w:" OPTION 102 | do 103 | 104 | case $OPTION in 105 | h) 106 | usage 107 | ;; 108 | f) 109 | shift 110 | if [[ $1 == *islet.conf ]]; then 111 | CONFIG="$1" 112 | else 113 | echo "File name appears to be incorrect, not islet.conf)" 114 | fi 115 | ;; 116 | c) 117 | CRIT="$OPTARG" 118 | ;; 119 | p) 120 | PRINT="$OPTARG" 121 | ;; 122 | s) 123 | SKIP=$(echo "$OPTARG" | sed 's/,/ /g') 124 | ;; 125 | T) 126 | if [[ "$OPTARG" == status ]]; then 127 | STATUS_CHECK=1 128 | elif [[ "$OPTARG" == size ]]; then 129 | SIZE_CHECK=1 130 | elif [[ "$OPTARG" == available ]]; then 131 | LIST_CHECK=1 132 | AVAILABLE_CHECK=1 133 | elif [[ "$OPTARG" == unavailable ]]; then 134 | LIST_CHECK=1 135 | UNAVAILABLE_CHECK=1 136 | elif [[ "$OPTARG" == variable ]]; then 137 | PRINT_CHECK=1 138 | elif [[ "$OPTARG" == database ]]; then 139 | DATABASE_CHECK=1 140 | else 141 | echo "Unknown argument type" 142 | exit $UNKNOWN 143 | fi 144 | ;; 145 | w) 146 | WARN="$OPTARG" 147 | ;; 148 | \?) 149 | exit 1 150 | ;; 151 | esac 152 | done 153 | 154 | 155 | if [[ -f $CONFIG ]]; 156 | then 157 | source $CONFIG 158 | else 159 | echo "ERROR: islet.conf has not been found. Update the CONFIG variable in $0 or specify the path with \`\`-f''" 160 | exit $UNKNOWN 161 | fi 162 | 163 | if [[ $UNAVAILABLE_CHECK -eq 1 ]]; then 164 | for config in $(find $CONFIG_DIR -type f -name "*.conf") 165 | do 166 | name=$(basename $CONFIG_DIR/$config) 167 | 168 | CONTINUE=0 169 | for i in $SKIP 170 | do 171 | if [[ "$name" == "$i" ]]; then 172 | CONTINUE=1 173 | fi 174 | done 175 | 176 | if [[ $CONTINUE -eq 1 ]]; then 177 | continue 178 | fi 179 | 180 | if grep -q 'VISIBLE="no"' $config 2>/dev/null 181 | then 182 | LIST+=("$name") 183 | let COUNT++ 184 | fi 185 | done 186 | 187 | if [[ $COUNT -gt 0 ]]; then 188 | echo "Invisible items: ${LIST[@]}" 189 | fi 190 | 191 | check_values $COUNT 192 | fi 193 | 194 | if [[ $AVAILABLE_CHECK -eq 1 ]]; then 195 | for config in $(find $CONFIG_DIR -type f -name "*.conf") 196 | do 197 | name=$(basename $CONFIG_DIR/$config) 198 | 199 | CONTINUE=0 200 | for i in $SKIP 201 | do 202 | if [[ "$name" == "$i" ]]; then 203 | CONTINUE=1 204 | fi 205 | done 206 | 207 | if [[ $CONTINUE -eq 1 ]]; then 208 | continue 209 | fi 210 | 211 | source $config 212 | docker images $ENVIRONMENT | grep -q $ENVIRONMENT 213 | if [[ $? -eq 0 ]]; 214 | then 215 | echo "Image is available for $name" 216 | else 217 | echo "Error: missing image for $name" 218 | let MISSING++ 219 | fi 220 | done 221 | 222 | check_values 223 | fi 224 | 225 | if [[ $STATUS_CHECK -eq 1 ]]; then 226 | 227 | for dir in $CONFIG_DIR $INSTALL_DIR 228 | do 229 | if [[ ! -d $dir ]] 230 | then 231 | echo "Error: $dir does not exist or is not accessible!" 232 | let MISSING++ 233 | fi 234 | done 235 | 236 | for file in $LIBISLET $SHELL $DB 237 | do 238 | if [[ ! -f $file ]] 239 | then 240 | echo "Error: $file does not exist or is not accessible!" 241 | let MISSING++ 242 | fi 243 | done 244 | 245 | if ! getent passwd $USER 1>/dev/null 246 | then 247 | echo "Error: $USER doesn't exist!" 248 | let MISSING++ 249 | fi 250 | 251 | if ! getent passwd $USER | grep -q $SHELL 252 | then 253 | echo "Error: ${USER}'s shell is different than declared in ${CONFIG}!" 254 | let MISSING++ 255 | fi 256 | 257 | if ! getent group $GROUP 1>/dev/null 258 | then 259 | echo "Error: Group $GROUP doesn't exist!" 260 | let MISSING++ 261 | fi 262 | 263 | check_values 264 | fi 265 | 266 | if [[ $DATABASE_CHECK -eq 1 ]]; then 267 | 268 | [[ -e $DB ]] || { echo "CRITICAL: $DB not found"; exit $CRITICAL; } 269 | 270 | user=$(stat -c "%U" $DB) 271 | group=$(stat -c "%G" $DB) 272 | file=$(file -b /var/tmp/islet.db) 273 | 274 | [[ "$USER" = "$user" ]] || { let MISSING++; echo "$USER does not own $DB"; } 275 | [[ "$GROUP" = "$group" ]] || { let MISSING++; echo "$GROUP does not group own $DB"; } 276 | echo "$file" | grep -q "SQLite 3" || { let MISSING++; echo "$DB is not a SQLite 3 database"; } 277 | 278 | check_values 279 | fi 280 | -------------------------------------------------------------------------------- /extra/ids.conf: -------------------------------------------------------------------------------- 1 | # System Configuration 2 | ENVIRONMENT="jonschipp/islet-ids" # Launch containers from this image. Over-ridden by per-image config files 3 | DESCRIPTION="Snort and Suricata training image" # Brief description of image, listed in islet_shell selection menu 4 | 5 | # Security Configuration 6 | ENABLE="yes" # Enable config from selection menu 7 | DAYS="3" # Container lifetime specified in days, removed after x days by cron jobs 8 | 9 | # Container Configuration 10 | VIRTUSER="demo" # Account used when container is entered (Must exist in container!) 11 | CPUSHARES="1024" # Proportion of cpu share allocation per container 12 | MEMORY="256m" # Amount of memory allocated to each container 13 | SWAP="10m" # Amount of swap memory allocated to each container 14 | HOSTNAME="ids" # Set hostname in container. PS1 will end up as $VIRTUSER@$HOSTNAME:~$ in shell 15 | NETWORK="none" # Disable networking by default: none; Enable networking: bridge 16 | DNS="127.0.0.1" # Use loopback when networking is disabled to prevent error messages from resolver 17 | MOUNT="-v /exercises:/exercises:ro" # Mount point(s), sep. by -v: /src:/dst:attributes, ro = readonly (avoid rw) 18 | CAP_NET_ADMIN="yes" # Configure the network 19 | CAP_NET_RAW="yes" # Use RAW and PACKET sockets 20 | LOCAL_OPTIONS="" # Apply any other options you want passed to Docker run here 21 | LOCAL_ENV="" # Variables that get passed to VIRTUSER's shell for container 22 | export ENVIRONMENT PLATFORM=islet # Export variables for container environment 23 | ENVS="ENVIRONMENT PLATFORM" # Make exported variables available in container 24 | WORKDIR="/home/$VIRTUSER" # User begins in this directory, usually its VIRTUSER's HOME 25 | COMMAND="bash" # Command to launch on container entry, typically used to get a shell 26 | 27 | # Branding & Information 28 | MOTD="Training materials are in /exercises" # Message of the day is displayed before entering container 29 | BANNER=" 30 | ================================================================= 31 | Welcome to the IDS Configuration! 32 | 33 | --== Initialization Complete ==-- 34 | 35 | ,,_ -*> Snort! <*- 36 | o\" )~ <================> 37 | '''' -*> Suricata! <*- 38 | 39 | A place to try out Snort and Suricata 40 | ================================================================= 41 | " 42 | -------------------------------------------------------------------------------- /extra/iptables-rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Flushing all rules 3 | iptables -F 4 | iptables -X 5 | 6 | # Setting default filter policy 7 | iptables -P INPUT DROP 8 | iptables -P OUTPUT ACCEPT 9 | iptables -P FORWARD ACCEPT 10 | 11 | # Logging 12 | #iptables -I INPUT 1 -p tcp --dport 22 -j LOG 13 | iptables -t nat -I PREROUTING 1 -j LOG 14 | 15 | # Allow traffic on loopback 16 | iptables -A INPUT -i lo -j ACCEPT 17 | iptables -A OUTPUT -o lo -j ACCEPT 18 | iptables -A INPUT -s 127/8 -j DROP 19 | 20 | # Docker stuff 21 | iptables -A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 22 | iptables -A FORWARD -i docker0 ! -o docker0 -j ACCEPT 23 | iptables -A FORWARD -i docker0 -o docker0 -j ACCEPT 24 | 25 | # Allow existing connections 26 | iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 27 | iptables -A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 28 | 29 | # Rate limiting SSH 30 | iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --name ssh --set 31 | iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --name ssh --update --seconds 60 --hitcount 5 -j DROP 32 | iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT 33 | 34 | # Nagios NRPE 35 | iptables -A INPUT -p tcp --dport 5666 -m conntrack --ctstate NEW -j ACCEPT 36 | -------------------------------------------------------------------------------- /extra/netsniff-ng.conf: -------------------------------------------------------------------------------- 1 | # System Configuration 2 | ENVIRONMENT="jonschipp/islet-netsniff-ng" # Launch containers from this image. Over-ridden by per-image config files 3 | DESCRIPTION="Netsniff-NG Toolkit training image" # Brief description of image, listed in islet_shell selection menu 4 | 5 | # Security Configuration 6 | ENABLE="yes" # Enable config from selection menu 7 | DAYS="3" # Container lifetime specified in days, removed after x days by cron jobs 8 | 9 | # Container Configuration 10 | VIRTUSER="demo" # Account used when container is entered (Must exist in container!) 11 | CPUSHARES="1024" # Proportion of cpu share allocation per container 12 | MEMORY="256m" # Amount of memory allocated to each container 13 | SWAP="10m" # Amount of swap memory allocated to each container 14 | HOSTNAME="netsniff-ng" # Set hostname in container. PS1 will end up as $VIRTUSER@$HOSTNAME:~$ in shell 15 | NETWORK="none" # Disable networking by default: none; Enable networking: bridge 16 | DNS="127.0.0.1" # Use loopback when networking is disabled to prevent error messages from resolver 17 | MOUNT="-v /exercises:/exercises:ro" # Mount point(s), sep. by -v: /src:/dst:attributes, ro = readonly (avoid rw) 18 | CAP_NET_ADMIN="yes" # Configure the network 19 | CAP_NET_RAW="yes" # Use RAW and PACKET sockets 20 | LOCAL_OPTIONS="" # Apply any other options you want passed to Docker run here 21 | export ENVIRONMENT PLATFORM=islet # Export variables for container environment 22 | ENVS="ENVIRONMENT PLATFORM" # Make exported variables available in container 23 | WORKDIR="/home/$VIRTUSER" # User begins in this directory, usually its VIRTUSER's HOME 24 | COMMAND="bash" # Command to launch on container entry, typically used to get a shell 25 | 26 | # Branding & Information 27 | MOTD="Training materials are in /exercises" # Message of the day is displayed before entering container 28 | BANNER=" 29 | ================================================================= 30 | 31 | Welcome to Netsniff-NG Configuration! 32 | 33 | netsniff-ng is a free, performant Linux network analyzer and 34 | linux network analyzer and networking toolkit. If you will, 35 | the Swiss army knife for network packets. 36 | 37 | Web: http://netsniff-ng.org 38 | 39 | /( )\\ 40 | ./ {______} \. 41 | \ ^, ,^ / 42 | |'O\ /O'| _.<0101011>-- 43 | > \`' '\` < / 44 | ) ,.==., ( | 45 | .-(|/--~~--\|)-' 46 | ( ___ 47 | \__.=|___E 48 | 49 | A place to try out Netsniff-NG 50 | 51 | ================================================================= 52 | " 53 | -------------------------------------------------------------------------------- /extra/ossec.conf: -------------------------------------------------------------------------------- 1 | # System Configuration 2 | ENVIRONMENT="jonschipp/islet-ossec" # Launch containers from this image. Over-ridden by per-image config files 3 | DESCRIPTION="OSSEC training image" # Brief description of image, listed in islet_shell selection menu 4 | 5 | # Security Configuration 6 | ENABLE="yes" # Enable config from selection menu 7 | DAYS="3" # Container lifetime specified in days, removed after x days by cron jobs 8 | 9 | # Container Configuration 10 | VIRTUSER="root" # Account used when container is entered (Must exist in container!) 11 | CPUSHARES="1024" # Proportion of cpu share allocation per container 12 | MEMORY="256m" # Amount of memory allocated to each container 13 | SWAP="10m" # Amount of swap memory allocated to each container 14 | HOSTNAME="ossec" # Set hostname in container. PS1 will end up as $VIRTUSER@$HOSTNAME:~$ in shell 15 | NETWORK="none" # Disable networking by default: none; Enable networking: bridge 16 | DNS="127.0.0.1" # Use loopback when networking is disabled to prevent error messages from resolver 17 | MOUNT="-v /exercises:/exercises:ro" # Mount point(s), sep. by -v: /src:/dst:attributes, ro = readonly (avoid rw) 18 | export ENVIRONMENT PLATFORM=islet # Export variables for container environment 19 | ENVS="ENVIRONMENT PLATFORM" # Make exported variables available in container 20 | WORKDIR="/home/$VIRTUSER" # User begins in this directory, usually its VIRTUSER's HOME 21 | COMMAND="bash" # Command to launch on container entry, typically used to get a shell 22 | 23 | # Branding & Information 24 | MOTD="Be sure to start rsyslog" # Message of the day is displayed before entering container 25 | BANNER=" 26 | ================================================================= 27 | Welcome to the OSSEC Configuration! 28 | 29 | 30 | :::: 31 | :::::. 32 | ::::;:. 33 | :::;.,::;:. 34 | :::;:::::::::, ;;''. ;;;; .;;;. ;;;;;; :;;;: 35 | ::::::::::::::: ,;;;;;;; ;;;;;':;;;;; ;;;;;; ;;;;;;; 36 | ;;;;;:';;;;':;;: .;;; ,;;'.;; ' ;;, , ;;.... ;;;,.,;; 37 | .;;;;;;,:';;;;:;;: ;;; ;;;;; ;; ;; ,;; . 38 | .;;;;: ;.,;;;::;;; '' '''''' '''. '' ;;; 39 | ; .;;;: ''' ,;;;.;;: .'' ;''''''' '''', '''''' 40 | .;;.;;;. +++..;;; .;. .'' ''' ;''' .'''.'''''' 41 | ;;;.:;;; :':.;;;;..:. ++. ++' ++ +++++ +++ 42 | ,;;;,;;;; ..:;;;;. . +++ ;++ + ++.. +++++ .++, ' 43 | .';;;;;;;;,;;;;;;. ++++'++++;++++++++++++,++#### #+++++++ 44 | ,';;;;;;;;;;;;;;. .######' .##### #####+ ###### ######+ 45 | ,;;;;;;;;;';;;;. .;', :': .'' ,,,,,, ;'; 46 | .:;''''';,;;;: 47 | .,,:,..;;;;. 48 | :;;;;;, 49 | .;;;':. 50 | .,;;,. 51 | 52 | A place to try out OSSEC 53 | ================================================================= 54 | " 55 | -------------------------------------------------------------------------------- /extra/sagan.conf: -------------------------------------------------------------------------------- 1 | # System Configuration 2 | ENVIRONMENT="jonschipp/islet-sagan" # Launch containers from this image, must match name in Docker exactly. 3 | DESCRIPTION="Sagan training image" # Brief description of image, shown in selection menu 4 | 5 | # Security Configuration 6 | ENABLE="yes" # Enable config from selection menu 7 | DAYS="3" # Container lifetime specified in days, removed after x days by cron jobs 8 | REMOVE="no" # Container is removed after exit, user cannot re-attach and resume work 9 | TIMEOUT="6h" # Max runtime of containers, accepts timeout(1) arguments 10 | 11 | # Container Configuration 12 | VIRTUSER="demo" # Account used when container is entered (Must exist in image!) 13 | CPUSHARES="1024" # Proportion of cpu share allocation per container 14 | MEMORY="100m" # Amount of memory allocated to each container 15 | SWAP="10m" # Amount of swap memory allocated to each container 16 | HOSTNAME="sagan" # Set hostname in container. PS1 will end up as $VIRTUSER@$HOSTNAME:~$ in shell 17 | NETWORK="none" # Disable networking by default: none; Enable networking: bridge 18 | DNS="127.0.0.1" # Use loopback when networking is disabled to prevent error messages from resolver 19 | MOUNT="" # Mount point(s), sep. by -v: /src:/dst:attributes, ro = readonly (avoid rw if possible) 20 | CAP_NET_ADMIN="yes" # Configure the network 21 | CAP_NET_RAW="yes" # Use RAW and PACKET sockets 22 | LOCAL_OPTIONS="" # Apply any other options you want passed to Docker run here 23 | export ENVIRONMENT PLATFORM=islet # Export variables for container environment 24 | ENVS="ENVIRONMENT PLATFORM" # Make exported variables available in container 25 | WORKDIR="/home/$VIRTUSER" # User begins in this directory, usually its VIRTUSER's HOME 26 | COMMAND="bash" # Command to launch on container entry, typically used to get a shell 27 | 28 | # Branding & Information 29 | MOTD="Start rsyslog first: $ sudo service rsyslog start 30 | Then try out Sagan: $ sudo sagan --help" # Message of the day is displayed before entering container 31 | BANNER=" 32 | ============================================================================ 33 | 34 | Welcome to Sagan Configuration! 35 | 36 | Sagan is an open source (GNU/GPLv2) high performance, real-time log analysis 37 | & correlation engine that run under *nix operating systems. It is written in 38 | C and uses a multi-threaded architecture to deliver high performance log & 39 | event analysis. Sagan's structure and rules work similarly to the 40 | Sourcefire/Cisco\"Snort\" IDS/IPS engine. 41 | 42 | Web: http://sagan.org 43 | 44 | ,-._,-. -*> Sagan! <*- 45 | \/)\"(\/ 46 | (_o_) Champ Clark III & The Quadrant InfoSec Team [quadrantsec.com] 47 | / \/) Copyright (C) 2009-2014 Quadrant Information Security, et al. 48 | (|| ||) Using PCRE version: 8.31 2012-07-06 49 | oo-oo Sagan is processing events..... 50 | 51 | 52 | A place to try out Sagan 53 | 54 | ============================================================================ 55 | " 56 | -------------------------------------------------------------------------------- /extra/silklive.conf: -------------------------------------------------------------------------------- 1 | # Copyright 2016 Carnegie Mellon University 2 | # This material is based upon work funded and supported by Flocon - which is funded by Cost Recovery Dollars under Contract No. FA8721-05-C-0003 with Carnegie Mellon University for the operation of the Software Engineering Institute, a federally funded research and development center sponsored by the United States Department of Defense. 3 | # Any opinions, findings and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of Flocon - which is funded by Cost Recovery Dollars or the United States Department of Defense. 4 | # NO WARRANTY. THIS CARNEGIE MELLON UNIVERSITY AND SOFTWARE ENGINEERING INSTITUTE MATERIAL IS FURNISHED ON AN “AS-IS” BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT. 5 | # [Distribution Statement A] This material has been approved for public release and unlimited distribution. Please see Copyright notice for non-US Government use and distribution. 6 | # DM-0004314 7 | 8 | # System Configuration 9 | ENVIRONMENT="certcc/silklive" # Launch containers from this image, must match name in Docker exactly. 10 | DESCRIPTION="SiLK training image" # Brief description of image, shown in selection menu 11 | 12 | # Security Configuration 13 | VISIBLE="yes" # This config file is visible from config selection menu 14 | DAYS="3" # Container lifetime specified in days, removed after x days by cron jobs 15 | 16 | # Container Configuration 17 | VIRTUSER="demo" # Account used when container is entered (Must exist in image!) 18 | CPUSHARES="1024" # Proportion of CPU share allocation per container 19 | MEMORY="256m" # Amount of memory allocated to each container 20 | HOSTNAME="silklive" # Set hostname in container. PS1 will end up as $VIRTUSER@$HOSTNAME:~$ in shell 21 | NETWORK="none" # Disable networking by default: none; Enable networking: bridge 22 | DNS="127.0.0.1" # Use loopback when networking is disabled to prevent error messages from resolver 23 | MOUNT="-v /data/:/data/:ro" # Mount point(s), sep. by -v: /src:/dst:attributes, ro = readonly (avoid rw if possible) 24 | LOCAL_OPTIONS="" # Apply any other options you want passed to Docker run here 25 | export LD_LIBRARY_PATH=/usr/local/lib # Export Variables for container environment 26 | ENVS="LD_LIBRARY_PATH" # Make exported variables available in container 27 | WORKDIR="/home/$VIRTUSER" # User begins in this directory 28 | COMMAND="bash" # Command to launch on container entry 29 | 30 | # Branding & Information 31 | MOTD="Run rwsiteinfo for information on repository 32 | e.g. $ rwsiteinfo --fields=sensor,describe-sensor,type:list" # Message of the day is displayed before entering container 33 | BANNER=" 34 | ================================================================= 35 | 36 | Welcome to SiLK Configuration! 37 | 38 | SiLK, the System for Internet-Level Knowledge, is a collection of 39 | traffic analysis tools developed by the CERT Network Situational 40 | Awareness Team (CERT NetSA) to facilitate security analysis of 41 | large networks. The SiLK tool suite supports the efficient 42 | collection, storage, and analysis of network flow data, enabling 43 | network security analysts to rapidly query large historical 44 | traffic data sets. 45 | 46 | Web: http://tools.netsa.cert.org 47 | 48 | ____ _____ ____ _____ 49 | / ___| ____| _ \_ _| 50 | | | | _| | |_) || | 51 | | |___| |___| _ < | | 52 | \____|_____|_| \_\|_| 53 | 54 | A place to try out SiLK 55 | 56 | ================================================================= 57 | " 58 | -------------------------------------------------------------------------------- /extra/tcpdump.conf: -------------------------------------------------------------------------------- 1 | # System Configuration 2 | ENVIRONMENT="jonschipp/islet-tcpdump" # Launch containers from this image. Over-ridden by per-image config files 3 | DESCRIPTION="Tcpdump and Tshark training image" # Brief description of image, listed in islet_shell selection menu 4 | 5 | # Security Configuration 6 | ENABLE="yes" # Enable config from selection menu 7 | DAYS="3" # Container lifetime specified in days, removed after x days by cron jobs 8 | 9 | # Container Configuration 10 | VIRTUSER="demo" # Account used when container is entered (Must exist in container!) 11 | CPUSHARES="1024" # Proportion of cpu share allocation per container 12 | MEMORY="256m" # Amount of memory allocated to each container 13 | SWAP="10m" # Amount of swap memory allocated to each container 14 | HOSTNAME="tcpdump" # Set hostname in container. PS1 will end up as $VIRTUSER@$HOSTNAME:~$ in shell 15 | NETWORK="none" # Disable networking by default: none; Enable networking: bridge 16 | DNS="127.0.0.1" # Use loopback when networking is disabled to prevent error messages from resolver 17 | MOUNT="-v /exercises:/exercises:ro" # Mount point(s), sep. by -v: /src:/dst:attributes, ro = readonly (avoid rw) 18 | CAP_NET_ADMIN="yes" # Configure the network 19 | CAP_NET_RAW="yes" # Use RAW and PACKET sockets 20 | LOCAL_OPTIONS="" # Apply any other options you want passed to Docker run here 21 | export ENVIRONMENT PLATFORM=islet # Export variables for container environment 22 | ENVS="ENVIRONMENT PLATFORM" # Make exported variables available in container 23 | WORKDIR="/home/$VIRTUSER" # User begins in this directory, usually its VIRTUSER's HOME 24 | COMMAND="bash" # Command to launch on container entry, typically used to get a shell 25 | 26 | # Branding & Information 27 | MOTD="Training materials are in /exercises" # Message of the day is displayed before entering container 28 | BANNER=" 29 | ================================================================= 30 | Welcome to the Tcpdump Configuration! 31 | 32 | A place to try out Tcpdump and Tshark 33 | ================================================================= 34 | " 35 | -------------------------------------------------------------------------------- /extra/volatility.conf: -------------------------------------------------------------------------------- 1 | # System Configuration 2 | ENVIRONMENT="jonschipp/islet-volatility" # Launch containers from this image. Over-ridden by per-image config files 3 | DESCRIPTION="Volatility training image" # Brief description of image, listed in islet_shell selection menu 4 | 5 | # Security Configuration 6 | ENABLE="yes" # Enable config from selection menu 7 | DAYS="3" # Container lifetime specified in days, removed after x days by cron jobs 8 | 9 | # Container Configuration 10 | VIRTUSER="demo" # Account used when container is entered (Must exist in container!) 11 | CPUSHARES="1024" # Proportion of cpu share allocation per container 12 | MEMORY="256m" # Amount of memory allocated to each container 13 | SWAP="10m" # Amount of swap memory allocated to each container 14 | HOSTNAME="volatility" # Set hostname in container. PS1 will end up as $VIRTUSER\@$HOSTNAME:~$ in shell 15 | NETWORK="none" # Disable networking by default: none; Enable networking: bridge 16 | DNS="127.0.0.1" # Use loopback when networking is disabled to prevent error messages from resolver 17 | MOUNT="-v /exercises:/exercises:ro" # Mount point(s), sep. by -v: /src:/dst:attributes, ro = readonly (avoid rw) 18 | LOCAL_OPTIONS="" # Apply any other options you want passed to Docker run here 19 | export ENVIRONMENT PLATFORM=islet # Export variables for container environment 20 | ENVS="ENVIRONMENT PLATFORM" # Make exported variables available in container 21 | WORKDIR="/home/$VIRTUSER" # User begins in this directory, usually its VIRTUSER's HOME 22 | COMMAND="bash" # Command to launch on container entry, typically used to get a shell 23 | 24 | # Branding & Information 25 | MOTD="Training materials are in /exercises" # Message of the day is displayed before entering container 26 | BANNER=" 27 | ===================================================================================================================================== 28 | Welcome to the Volatility configuration 29 | 30 | \` 31 | # # 32 | @ @, @\` 33 | @ @@ @@ 34 | '@; @@: @@+ 35 | @@@ @@: @@@@@@@@@@@@@@@@ @@@ .;;;;;;;;;;;;;;;, 36 | @@@ @@: @@@@@@@@@@@@@@+ @@@ @@@@@@@@@@@@@@@ 37 | +@@@; @@: :#####@@@##### @@@ ,@@@@@@@@@@@@@: 38 | @@@@@ @@: @@@ @@@ @@@ 39 | @@ @@ @@: @@@ @@@ @@@ 40 | #@@ @@; @@: @@@ @@@ @@@ 41 | @@, :@@ @@: @@@ @@@ @@@ 42 | .@@ @@ @@: @@@ @@@ @@@ 43 | #@@@@@###++' @@@ +@; @: @@: \`\`\`\` @@@ @@@ @@@ 44 | ,@@@@@@@@@@ @@, @@####@ @: + @@: '@@@ @@@ @@@ @@@ 45 | +##@@@@@@, :@@ @@@@@@@ @: @@@ @@: \`@@@. @@@ @@@ @@@ 46 | \`@@@ @@@ :@@@@@; @: #@@@ @@: @@@@@ @@@ @@@ @@@ 47 | @@@ @@. :@@+ @: @@@ @@: @@@@@ @@@ . @@@ . @@@ 48 | ;@@; ;@@ @@+ @@+ @@: #@@@@@. @@@ @# @@@ ;@ @@@ 49 | @@@ @@@ ;@@ :@@ @@: @@@@@@@ @@@ @@@ @@@ ;@@, @@@ 50 | @@@ @@\` @@+ @@\` @@: +@@#@@@@ @@@ @@@ @@@ ;@@: @@@ @#;. ,'#: 51 | @@# +@@ @@. @@, @@: @@@ :@@@, @@@ @@@ @@@ ;@@: @@@ @@@\` +@@@ 52 | @@@ @@# @@\` @@, @@: ;@@@ @@@@ @@@ @@@ @@@ ;@@: @@@ '@@@ @@@\` 53 | +@@, \`@@ @@+ @@\` @@: @@@@# @@@@ @@@ @@@ @@@ ;@@: @@@ @@@; @@@# 54 | @@@ #@@ ;@@ :@@ @@: ,@@@@ .@@@, @@@ @@@ @@@ ;@@: @@@ \`@@@ ,@@@ 55 | @@@ @@# @@+ @@+ @@: @@@@ @@@@ @@@ @@@ @@@ ;@@: @@@ @@@# @@@: 56 | ,@@+@@ :@@' @@@ @@: @@@, #@@@ @@@ @@@ @@@ ;@@, @@@ @@@+@@@ 57 | @@@@@ +@@@; \`#@@@ @@########@@@@ \`@@@, @@@ @@ @@@@@@@@@@@@ ;@, @@@ '@@@@@ 58 | #@@@# :@@@@@@@@@@ @@@@@@@@@@@@@+ @@@@ @@@ @ @@@@@@@@@@@@ ; @@@ @@@@# 59 | @@@ ;@@@@@# @@@@@@@@@@@@@ '@@@ @@@ @@@@@@@@@@@@ @@@ .@@@ 60 | @@@ @@@,@@@ @@@ 61 | ;@# @@@#@@@ @@@ 62 | @ :@@@@@@ @@@ 63 | @ @@@@@@ @@@ 64 | \` @@@@@@ @@@ 65 | .@@@@@ @@@ 66 | @@@@@ @@@ 67 | #@@@@ @@@ 68 | @@@@ @@@ 69 | @@@@ @@: 70 | '@@@ @\` 71 | ===================================================================================================================================== 72 | " 73 | -------------------------------------------------------------------------------- /functions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Author: Jon Schipp 3 | # Written for Ubuntu Saucy and Trusty, should be adaptable to other distros. 4 | 5 | # Installation notification (not implemented yet) 6 | MAIL="$(which mail 2>/dev/null)" 7 | COWSAY=/usr/games/cowsay 8 | IRCSAY=/usr/local/bin/ircsay 9 | IRC_CHAN="#replace_me" 10 | HOST="$(hostname -s)" 11 | LOGFILE=install.log 12 | EMAIL=user@company.com 13 | 14 | # System Configuration 15 | USER="demo" # User account to create for that people will ssh into to enter container 16 | PASS="demo" # Password for the account that users will ssh into 17 | GROUP="islet" # ISLET Group, used for permissions of database 18 | SIZE=2G # Maximum size of containers, DoS prevention 19 | SSH_CONFIG=/etc/ssh/sshd_config 20 | CONTAINER_DESTINATION= # Put containers on another volume e.g. /dev/sdb1 (optional). You must mkfs.$FS first! 21 | FS="ext4" # Filesystem type for CONTAINER_DESTINATION, used for mounting 22 | INSTALL_DIR=/opt/islet # ISLET component directory 23 | BIN_DIR="$INSTALL_DIR/bin" # Directory to install islet scripts 24 | SHELL="$BIN_DIR/islet_shell" # $USER's shell and container launcher 25 | 26 | # Other Declarations 27 | RESTART_SSH=0 28 | RESTART_DOCKER=0 29 | LIMITS=/etc/security/limits.d 30 | DEFAULT=/etc/default/docker 31 | UPSTART=/etc/init/docker.conf 32 | 33 | # Logging 34 | #exec > >(tee -a "$LOGFILE") 2>&1 35 | #printf "\n --> Logging stdout & stderr to ${LOGFILE}\n" 36 | 37 | die(){ 38 | if [[ -f "${COWSAY:-none}" ]]; then 39 | "$COWSAY" -d "$*" 40 | else 41 | printf "$(tput setaf 1)$*$(tput sgr0)\n" 42 | fi 43 | if [[ -f "$IRCSAY" ]]; then 44 | ( set +e; "$IRCSAY" "$IRC_CHAN" "$*" 2>/dev/null || true ) 45 | fi 46 | if [[ -f "${MAIL:-none}" ]]; then 47 | echo "$*" | mail -s "[vagrant] Bro Sandbox install information on $HOST" "$EMAIL" 48 | fi 49 | 50 | exit 1 51 | } 52 | 53 | hi(){ 54 | if [[ -f "${COWSAY:-none}" ]]; then 55 | "$COWSAY" "$*" 56 | else 57 | printf "$(tput setaf 3)$*$(tput sgr0)\n" 58 | fi 59 | if [[ -f "$IRCSAY" ]]; then 60 | ( set +e; "$IRCSAY" "$IRC_CHAN" "$*" 2>/dev/null || true ) 61 | fi 62 | if [[ -f "${MAIL:-none}" ]]; then 63 | echo "$*" | mail -s "[vagrant] Bro Sandbox install information on $HOST" "$EMAIL" 64 | fi 65 | } 66 | 67 | template(){ 68 | cat <<"EOF" 69 | # System Configuration 70 | ENVIRONMENT="jonschipp/islet-netsniff-ng" # Launch containers from this image, must match name in Docker exactly. 71 | DESCRIPTION="Netsniff-NG Toolkit training image" # Brief description of image, shown in selection menu 72 | 73 | # Security Configuration 74 | VISIBLE="yes" # This config file is visible from config selection menu 75 | DAYS="3" # Container lifetime specified in days, removed after x days by cron jobs 76 | REMOVE="no" # Container is removed after exit, user cannot re-attach and resume work 77 | TIMEOUT="4h" # Max runtime of containers, accepts timeout(1) arguments 78 | 79 | # Container Configuration 80 | VIRTUSER="demo" # Account used when container is entered (Must exist in image!) 81 | CPUSHARES="1024" # Proportion of cpu share allocation per container 82 | MEMORY="256m" # Amount of memory allocated to each container 83 | HOSTNAME="netsniff-ng" # Set hostname in container. PS1 will end up as $VIRTUSER@$HOSTNAME:~$ in shell 84 | NETWORK="none" # Disable networking by default: none; Enable networking: bridge 85 | DNS="127.0.0.1" # Use loopback when networking is disabled to prevent error messages from resolver 86 | MOUNT="-v /exercises:/exercises:ro" # Mount point(s), sep. by -v: /src:/dst:attributes, ro = readonly (avoid rw if possible) 87 | LOCAL_OPTIONS="--cap-add=NET_RAW --cap-add=NET_ADMIN" # Apply any other options you want passed to Docker run here 88 | LOCAL_ENV="" # Variables that get passed to VIRTUSER's shell for container 89 | 90 | # Branding & Information 91 | MOTD="Training materials are in /exercises 92 | e.g. $ netsniff-ng --in /exercises/pcap/traffic.pcap" # Message of the day is displayed before entering container 93 | BANNER=" 94 | ================================================================= 95 | 96 | Welcome to Netsniff-NG Configuration! 97 | 98 | netsniff-ng is a free, performant Linux network analyzer and 99 | linux network analyzer and networking toolkit. If you will, 100 | the Swiss army knife for network packets. 101 | 102 | Web: http://netsniff-ng.org 103 | 104 | /( )\\ 105 | ./ {______} \. 106 | \ ^, ,^ / 107 | |'O\ /O'| _.<0101011>-- 108 | > \`' '\` < / 109 | ) ,.==., ( | 110 | .-(|/--~~--\|)-' 111 | ( ___ 112 | \__.=|___E 113 | 114 | A place to try out Netsniff-NG 115 | 116 | ================================================================= 117 | " 118 | EOF 119 | } 120 | 121 | logo(){ 122 | cat <<"EOF" 123 | =============================================================== 124 | 125 | ISLET: A Linux-based Software Training System 126 | 127 | (I)solated, 128 | (S)calable, 129 | & (L)ightweight (E)nvironment 130 | for (T)raining 131 | 132 | Web: https://github.com/jonschipp/islet 133 | 134 | =============================================================== 135 | EOF 136 | } 137 | 138 | is_ubuntu(){ 139 | if ! lsb_release -s -d 2>/dev/null | egrep -q 'Ubuntu|Debian'; then 140 | die "Debian or Ubuntu Linux is required for installation!" 141 | fi 142 | } 143 | 144 | install_docker(){ 145 | is_ubuntu 146 | hi " Installing Docker!\n" 147 | 148 | # Check that HTTPS transport is available to APT 149 | if [[ ! -e /usr/lib/apt/methods/https ]]; then 150 | apt-get update -qq 151 | apt-get install -qy apt-transport-https 152 | echo 153 | fi 154 | 155 | # Add the repository to your APT sources 156 | # Then import the repository key 157 | if [[ ! -e /etc/apt/sources.list.d/docker.list ]]; then 158 | echo deb https://get.docker.com/ubuntu docker main > /etc/apt/sources.list.d/docker.list 159 | apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9 160 | echo 161 | fi 162 | 163 | # Install docker 164 | if ! command -v docker >/dev/null 2>&1; then 165 | apt-get update -qq 166 | apt-get install -qy --no-install-recommends lxc-docker cgroup-lite 167 | #apt-get install -qy lxc-docker linux-image-extra-$(uname -r) aufs-tools 168 | fi 169 | } 170 | 171 | docker_configuration(){ 172 | local RESTART=0 173 | local SIZE="${1:-$SIZE}" 174 | if command -v docker >/dev/null 2>&1; then 175 | # Set devicemapper storage limit 176 | [[ -f /etc/init.d/docker ]] && service docker stop 2>&1 >/dev/null || stop -q docker 2>/dev/null 177 | sleep 1 178 | [[ -d /var/lib/docker/aufs ]] && umount /var/lib/docker/aufs 179 | [[ -d /var/lib/docker/devicemapper ]] && umount /var/lib/docker/devicemapper 180 | rm -rf /var/lib/docker/* || die "Unable to remove /var/lib/docker!" 181 | docker -d --storage-driver=devicemapper --storage-opt dm.basesize="$SIZE" & 182 | sleep 3 183 | pkill docker 184 | sed -i '/DOCKER_OPTS/d' "$DEFAULT" 185 | echo DOCKER_OPTS=\"--storage-driver=devicemapper --storage-opt dm.basesize=$SIZE\" >> "$DEFAULT" 186 | [[ -f /etc/init.d/docker ]] && RESTART=1 && service docker start || die "Docker did not start correctly!" 187 | [[ "$RESTART" -eq 0 ]] && [[ -f /etc/init/docker.conf ]] && start -q docker || hi "Docker started!" && exit 0 188 | else 189 | die "Docker is required for configuration!" 190 | fi 191 | } 192 | 193 | user_configuration(){ 194 | local USER="${1:-$USER}" 195 | local PASS="${2:-$PASS}" 196 | local GROUP="${3:-$GROUP}" 197 | local SHELL="${4:-$SHELL}" 198 | hi " Configuring the $USER user account!\n" 199 | 200 | if ! getent passwd "$USER" 1>/dev/null; then 201 | useradd --create-home --shell "$SHELL" "$USER" 202 | echo "$USER:$PASS" | chpasswd 203 | fi 204 | 205 | if ! getent group "$GROUP" | grep -q "$USER" 1>/dev/null; then 206 | groupadd "$GROUP" 2>/dev/null 207 | gpasswd -a "$USER" "$GROUP" 2>/dev/null 208 | fi 209 | 210 | if ! getent group docker | grep -q "$USER" 1>/dev/null; then 211 | groupadd docker 2>/dev/null 212 | gpasswd -a "$USER" docker 2>/dev/null 213 | fi 214 | } 215 | 216 | security_configuration(){ 217 | local USER="${1:-$USER}" 218 | local SHELL="${2:-$SHELL}" 219 | hi " Configuring the system with security in mind!\n" 220 | 221 | if ! grep -q "ClientAliveInterval 15" "$SSH_CONFIG"; then 222 | printf "\nClientAliveInterval 600\nClientAliveCountMax 3\n" >> "$SSH_CONFIG" 223 | RESTART_SSH=1 224 | fi 225 | 226 | if ! grep -q "Match User $USER" "$SSH_CONFIG"; then 227 | cat <> "$SSH_CONFIG" 228 | Match User "$USER" 229 | ForceCommand "$SHELL" 230 | PasswordAuthentication yes 231 | X11Forwarding no 232 | AllowTcpForwarding no 233 | GatewayPorts no 234 | PermitTunnel no 235 | MaxAuthTries 3 236 | MaxSessions 1 237 | AllowAgentForwarding no 238 | PermitEmptyPasswords no 239 | EOF 240 | RESTART_SSH=1 241 | fi 242 | 243 | if grep -q '^Subsystem sftp' "$SSH_CONFIG"; then 244 | sed -i '/Subsystem.*sftp/s/^/#/' "$SSH_CONFIG" 245 | RESTART_SSH=1 246 | fi 247 | 248 | if [[ "$RESTART_SSH" -eq 1 ]]; then 249 | if sshd -t 2>/dev/null; then 250 | [[ -f /etc/init.d/sshd ]] && service sshd restart 2>/dev/null 251 | [[ -f /etc/init.d/ssh ]] && service ssh restart 2>/dev/null 252 | else 253 | echo "Syntax error in ${SSH_CONFIG}." 254 | fi 255 | echo 256 | fi 257 | 258 | if [[ "$RESTART_DOCKER" -eq 1 ]]; then 259 | local RESTART=0 260 | [[ -f /etc/init.d/docker ]] && service docker stop 2>&1 >/dev/null || stop -q docker 2>/dev/null 261 | sleep 2 262 | [[ -f /etc/init.d/docker ]] && RESTART=1 && service docker start || die "Docker did not start correctly!" 263 | [[ -f /etc/init/docker.conf ]] && [[ "$RESTART" -eq 0 ]] && start -q docker 264 | echo 265 | PID="$(pgrep -f "docker -d")" 266 | [[ "$PID" ]] && cat /proc/"$PID"/limits 267 | echo 268 | fi 269 | } 270 | 271 | install_sample_configuration(){ 272 | hi " Installing sample training image for Bro!\n" 273 | if ! docker images | grep -q brolive; then 274 | docker pull broplatform/brolive 275 | fi 276 | } 277 | 278 | install_nsm_configurations(){ 279 | 280 | install_sample_configuration 281 | 282 | for file in $(git ls-files extra/*.conf | grep -v brolive.conf); do 283 | F="$(basename $file .conf)" 284 | if ! docker images | grep -q "$F"; then 285 | hi " Installing sample training image for ${F}\n" 286 | docker pull jonschipp/islet-"${F}" 287 | fi 288 | done 289 | } 290 | 291 | install_sample_distributions(){ 292 | DISTRO="ubuntu debian fedora centos" 293 | for image in "$DISTRO"; do 294 | if ! docker images | grep -q "$image"; then 295 | hi " Installing distribution image for ${image}\n" 296 | docker pull "$image" 297 | fi 298 | done 299 | } 300 | 301 | "$@" 302 | -------------------------------------------------------------------------------- /init/isletd.conf: -------------------------------------------------------------------------------- 1 | description "Isletd" 2 | author "Jon Schipp" 3 | start on runlevel [2345] 4 | 5 | exec /opt/islet/bin/isletd 6 | -------------------------------------------------------------------------------- /init/isletd.service: -------------------------------------------------------------------------------- 1 | # 2 | # systemd unit file for CentOS 7, Ubuntu bleeding edge 3 | # 4 | [Unit] 5 | Description=isletd 6 | # start us only once the network and logging subsystems are available 7 | After=syslog.target network.target docker.service 8 | 9 | [Service] 10 | Type=simple 11 | User=root 12 | Group=root 13 | WorkingDirectory=/ 14 | ExecStart=/opt/islet/bin/isletd 15 | 16 | RestartSec=1 17 | Restart=on-failure 18 | 19 | # Use syslog for logging 20 | StandardOutput=syslog 21 | StandardError=syslog 22 | SyslogIdentifier=isletd 23 | 24 | [Install] 25 | WantedBy=multi-user.target 26 | -------------------------------------------------------------------------------- /lib/libislet: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | SPACER1="---------------" 3 | SPACER2=" " 4 | 5 | normal="$(tput sgr0)" 6 | bold="$(tput bold)" 7 | underline="$(tput smul)" 8 | yellow="$(tput setaf 3)" 9 | blackf="$(tput setaf 0)" 10 | blackb="$(tput setab 0)" 11 | redf="$(tput setaf 1)" 12 | redb="$(tput setab 1)" 13 | greenf="$(tput setaf 2)" 14 | greenb="$(tput setab 2)" 15 | bluef="$(tput setaf 4)" 16 | blueb="$(tput setab 4)" 17 | magentaf="$(tput setaf 5)" 18 | magentab="$(tput setab 5)" 19 | cyanf="$(tput setaf 6)" 20 | cyanb="$(tput setab 6)" 21 | whitef="$(tput setaf 7)" 22 | whiteb="$(tput setab 7)" 23 | hidecursor="$(tput civis -- invisible)" 24 | showcursor="$(tput cnorm -- normal)" 25 | clearline="$(tput el)" 26 | 27 | N="${normal}" 28 | B="${bold}" 29 | U="${underline}" 30 | Y="${yellow}" 31 | BLF="${blackf}" 32 | BLB="${blackb}" 33 | RF="${redf}" 34 | RB="${redb}" 35 | GF="${greenf}" 36 | GB="${greenb}" 37 | BF="${bluef}" 38 | BB="${blueb}" 39 | MF="${magentaf}" 40 | MB="${magentab}" 41 | CF="${cyanf}" 42 | CB="${cyanb}" 43 | WF="${whitef}" 44 | WB="${whiteb}" 45 | HC="${hidecursor}" 46 | SC="${showcursor}" 47 | CL="${clearline}" 48 | 49 | ####################################### 50 | # Print text in specific color 51 | # Globals: 52 | # Color codes 53 | # Arguments: 54 | # String of characters 55 | # Returns: 56 | # Message in color 57 | ####################################### 58 | 59 | red() { alert; } 60 | yellow() { notice; } 61 | magenta() { info; } 62 | alert() { printf "${redf}$*${normal}\n" >&2; } 63 | notice() { printf "${yellow}$*${normal}\n"; } 64 | info() { printf "${magentaf}$*${normal}\n"; } 65 | ask() { printf "${whitef}$*${normal}"; } 66 | mention() { printf "${whitef}$*${normal}\n"; } 67 | 68 | ######################################### 69 | # Accept user input with options 70 | # Globals: 71 | # None 72 | # Arguments: 73 | # var - User input will be stored in its value 74 | # secret - Whether input will be echo'd back 75 | # opt1 - Optional argument of options to present to user 76 | # opt2 - Optional argument of options to present to user 77 | # Returns: 78 | # None 79 | ############################################################# 80 | 81 | prompt(){ 82 | local argc="$#" 83 | local var="$1" 84 | local secret="$2" 85 | 86 | if [[ "$argc" > 2 ]]; then 87 | local opt1="$3" 88 | local opt2="$4" 89 | if [[ $opt2 ]]; then 90 | local options="${Y}[${N}${BF}$opt1${N}${Y}/${N}${BF}$opt2${N}${Y}]${N}: " 91 | else 92 | local options="${Y}[${N}${BF}$opt1${N}${Y}]${N}: " 93 | fi 94 | fi 95 | 96 | if [[ "$secret" != "secret" ]]; then 97 | read -e -r -p "$options" "$var" 98 | else 99 | read -s -e -r -p "$options" "$var" 100 | fi 101 | } 102 | 103 | ######################################### 104 | # Print, log, and exit script for errors 105 | # Globals: 106 | # None 107 | # Arguments: 108 | # String of text indicating issue 109 | # Returns: 110 | # Red text and exits 1 111 | ########################################## 112 | 113 | quit(){ local message="$1"; alert "${message:-Exiting session!}"; log "$message"; exit 1; } 114 | 115 | ###################################################### 116 | # Color message MOTD from ISLET config yellow 117 | # Globals: 118 | # MOTD - Message of the day string from config 119 | # Arguments: 120 | # String of text 121 | # Returns: 122 | # Yellow text 123 | ###################################################### 124 | 125 | message(){ local message="$1"; echo; echo "$message"; notice "$MOTD"; echo; } 126 | 127 | ###################################################### 128 | # Sanitize input by removing special characters and 129 | # symbols. Used to normalize usernames and passwords 130 | # Globals: 131 | # None 132 | # Arguments: 133 | # String of text, either username or password 134 | # Returns: 135 | # Sanitized string 136 | ###################################################### 137 | 138 | sanitize(){ local item="$1"; echo "${item//[^a-zA-Z0-9]/}"; } 139 | 140 | ######################################################### 141 | # Check exit code of last command 142 | # Globals: 143 | # None 144 | # Arguments: 145 | # String of text 146 | # Returns: 147 | # If true, calls quit which exits 1 after log and error 148 | ######################################################### 149 | 150 | did_it_work() { test "$?" -ne 0 && quit "$1"; } 151 | 152 | ####################################### 153 | # Print ISLET banner 154 | # Globals: 155 | # Color codes 156 | # Arguments: 157 | # None 158 | # Returns: 159 | # Text of ISLET banner 160 | ####################################### 161 | 162 | islet_banner(){ 163 | printf "${hidecursor}" 164 | cat </dev/null 2>&1 || quit "Fatal: There is an issue with the docker configuration!" 53 | } 54 | 55 | ####################################### 56 | # Verify group settings 57 | # ISLET configuration 58 | # Globals: 59 | # $USER - System user that runs Docker 60 | # Arguments: 61 | # None 62 | # Returns: 63 | # None 64 | ####################################### 65 | 66 | verify_group(){ 67 | getent group docker 1>/dev/null 2>&1 || quit "Fatal: docker group doesn't exist!" 68 | getent group docker 2>/dev/null | grep -q $USER || quit "Fatal: $USER user not in docker group" 69 | } 70 | 71 | ####################################### 72 | # Get storage backend name 73 | # ISLET configuration 74 | # Globals: 75 | # None 76 | # Arguments: 77 | # None 78 | # Returns: 79 | # None 80 | ####################################### 81 | 82 | get_backend(){ 83 | local line="$($SUDO_DOCKER docker info 2>/dev/null | fgrep -i 'storage')" 84 | local backend="${line##* }" 85 | [[ "$backend" ]] || quit "Fatal: Docker storage backend wasn't found" 86 | echo "$backend" 87 | } 88 | 89 | ####################################### 90 | # Handle exit codes 91 | # Globals: 92 | # None 93 | # Arguments: 94 | # result 95 | # Returns: 96 | # None 97 | ####################################### 98 | 99 | exit_handler(){ 100 | local result="$1" 101 | [[ $result -eq 124 ]] && quit "Inactive timer expired in menu, exiting..." 102 | [[ $result -eq 127 ]] && return 0 # Value 127 is last given command is not found 103 | [[ $result -eq 130 ]] && return 0 # Value 130 SIGINT (^C) was sent, probably by user 104 | if [[ $result -ne 0 ]]; then 105 | [[ $DEBUG != "yes" ]] && quit " Fatal: Command returned non-zero status! Turn on debug mode for more info: DEBUG=yes in $CONFIG" 106 | fi 107 | } 108 | 109 | attach(){ 110 | import_configs 111 | local result 112 | # User is re-attaching to previous image 113 | log "${USERNAME}: Returning user from $CLIENT" 114 | notice "Welcome back!" 115 | mention "$MOTD" 116 | is_debug "opt: $SUDO_DOCKER docker start -i ${BASE}.${USERNAME}" 117 | $SUDO_DOCKER docker start -i "${BASE}.${USERNAME}" 118 | exit_handler $? || return 1 119 | # No errors, we made it 120 | return 0 121 | } 122 | 123 | ###################################################################### 124 | # Check if image exists before using it, try pulling it or fail out 125 | # Globals: 126 | # ENVIRONMENT - from ISLET configuration, docker image to launch 127 | # Arguments: 128 | # None 129 | # Returns: 130 | # None 131 | ###################################################################### 132 | 133 | does_image_exist(){ 134 | local tag 135 | local repo="$ENVIRONMENT" 136 | [[ "$repo" == *:* ]] && tag="${repo##*:}" && repo=${repo%%:*} 137 | [[ $tag ]] || tag=latest 138 | if ! docker images | fgrep -w "$repo" | fgrep -w -q "$tag"; then 139 | notice "Image not found, trying Docker Hub..." && echo 140 | $SUDO_DOCKER docker pull "$ENVIRONMENT" 2>/dev/null || quit "Fatal: Image doesn't exist!" 141 | fi 142 | unset tag repo 143 | } 144 | 145 | ################################################################################# 146 | # Create iptables rules for port forwarding to container 147 | # Used to access ports on a user's container to do things 148 | # like web interface training. Use PPID of session (sshd) as 149 | # the port to use for forwarding, that way we can keep track 150 | # of each user's session to iptables rule. 151 | # Globals: 152 | # VIRTUAL_PORT - Port running inside container to access 153 | # HOST_PORT - Port from host that's forwarded to container (VIRTUAL_PORT) 154 | # BIND - IP address to use to access containers 155 | # CLIENT - IP address of client provided by sshd 156 | # INTERFACE - Network interface to apply iptables rule 157 | # USER - Used for logging 158 | # PUBLISH - Combination of above to set the Docker forwarding rule 159 | # Arguments: 160 | # None 161 | # Returns: 162 | # None 163 | ################################################################################# 164 | 165 | port_forwarding_setup(){ 166 | # Use HOST_PORT and CLIENT as a way to associate the user with a container port (VIRTUAL_PORT) 167 | if [[ "$VIRTUAL_PORT" ]]; then 168 | # If host port is in use, find another to bind to 169 | while true; do 170 | if ! netstat -nalt | fgrep -q ":$HOST_PORT"; then 171 | break 172 | fi 173 | let HOST_PORT++ 174 | done 175 | 176 | PUBLISH="--publish $BIND:$HOST_PORT:$VIRTUAL_PORT" 177 | 178 | if [[ "$BIND" == "127.0.0.1" ]]; then 179 | sysctl -w net.ipv4.conf."${INTERFACE}".route_localnet=1 2>/dev/null 180 | did_it_work "sysctl command failed to execute, check ${USER}'s permissions" 181 | fi 182 | # Client will be able to connect to an exposed container port via $SERVER:$PPID 183 | iptables -t nat -I PREROUTING -i "$INTERFACE" \ 184 | -p tcp --source "$CLIENT" --dport "$HOST_PORT" -j DNAT --to "${BIND}:${HOST_PORT}" 2>/dev/null 185 | did_it_work "iptables command failed to execute, check ${USER}'s permissions" 186 | fi 187 | } 188 | 189 | ###################################################################### 190 | # Remove container if set to remove or port forwarding is used. 191 | # Removal means no reattachment and is useful in some training cases 192 | # e.g. limited storage, resource constraints, confidential data, and 193 | # port forwarding where we cannot guarentee the same port or client IP 194 | # Globals: 195 | # REMOVE - Option in ISLET configuration files for removal 196 | # VIRTUAL_PORT - If set pass the remove option to Docker 197 | # DB - Database to write to 198 | # BASE - Add image to database for account if no removal 199 | # Arguments: 200 | # None 201 | # Returns: 202 | # None 203 | ###################################################################### 204 | 205 | removal_setup(){ 206 | if [[ "$REMOVE" == "yes" ]] || [[ "$VIRTUAL_PORT" ]]; then 207 | # Re-attachment is impractical for port forwarding 208 | echo 209 | notice "This container is set to be terminated upon exit, work will not be saved." 210 | REMOVE="--rm" 211 | else 212 | # Don't remove, instead keep track of the user's container for re-attachment 213 | sqlite3 "$DB" "pragma foreign_keys = on; INSERT INTO environments(user, environment) values ('$USERNAME', '$BASE');" 2>/dev/null 214 | REMOVE="" 215 | fi 216 | } 217 | 218 | ##################################################################### 219 | # Build command line options for container capabilities 220 | # Globals: 221 | # CAPABILITIES_OPTIONS - Stores Docker capabilities cmd-line options 222 | # Arguments: 223 | # cap - Capability name 224 | # enabled - Whether capability is enabled or not (yes/no) 225 | # Returns: 226 | # None 227 | ##################################################################### 228 | 229 | set_capabilities(){ 230 | local cap="$1" 231 | local enabled="$2" 232 | 233 | [[ "$enabled" = yes ]] && CAPABILITIES_OPTIONS="${CAPABILITIES_OPTIONS} --cap-add $cap" 234 | [[ "$enabled" = no ]] && CAPABILITIES_OPTIONS="${CAPABILITIES_OPTIONS} --cap-drop $cap" 235 | } 236 | 237 | ################################################################## 238 | # Check and set value of capabilities values 239 | # Globals: 240 | # capabilities variables - Option in ISLET configuration files 241 | # Arguments: 242 | # None 243 | # Returns: 244 | # None 245 | ################################################################## 246 | 247 | check_capabilities(){ 248 | unset CAPABILITIES_OPTIONS 249 | # Set all capabilities per container 250 | [[ "$DROP_ALL" = "yes" ]] && CAPABILITIES_OPTIONS="--cap-drop all" && return 0 251 | [[ "$ADD_ALL" = "yes" ]] && CAPABILITIES_OPTIONS="--cap-add all" && return 0 252 | 253 | 254 | ## Enabled by default in Docker (we disable them for improved security) 255 | AUDIT_WRITE="${CAP_AUDIT_WRITE:-no}" && set_capabilities AUDIT_WRITE $AUDIT_WRITE 256 | CHOWN="${CAP_CHOWN:-no}" && set_capabilities CHOWN $CHOWN 257 | DAC_OVERRIDE="${CAP_DAC_OVERRIDE:-no}" && set_capabilities DAC_OVERRIDE $DAC_OVERRIDE 258 | FOWNER="${CAP_FOWNER:-no}" && set_capabilities FOWNER $FOWNER 259 | FSETID="${CAP_FSETID:-no}" && set_capabilities FSETID $FSETID 260 | MAC_OVERRIDE="${CAP_MAC_OVERRIDE:-no}" && set_capabilities MAC_OVERRIDE $MAC_OVERRIDE 261 | MKNOD="${CAP_MKNOD:-no}" && set_capabilities MKNOD $MKNOD 262 | NET_BIND_SERVICE="${CAP_NET_BIND_SERVICE:-no}" && set_capabilities NET_BIND_SERVICE $NET_BIND_SERVICE 263 | NET_RAW="${CAP_NET_RAW:-no}" && set_capabilities NET_RAW $NET_RAW 264 | SETPCAP="${CAP_SETPCAP:-no}" && set_capabilities SECPCAP $SECPCAP 265 | SYSLOG="${CAP_SYSLOG:-no}" && set_capabilities SYSLOG $SYSLOG 266 | SYS_ADMIN="${CAP_SYS_ADMIN:-no}" && set_capabilities SYS_ADMIN $SYS_ADMIN 267 | SYS_CHROOT="${CAP_SYS_CHROOT:-no}" && set_capabilities SYS_CHROOT $SYS_CHROOT 268 | KILL="${CAP_KILL:-no}" && set_capabilities KILL $KILL 269 | # Enabled by default for ISLET (subset of Docker defaults) for improved security 270 | SETFCAP="${CAP_SETFCAP:-yes}" && set_capabilities SETFCAP $SETFCAP 271 | SETUID="${CAP_SETUID:-yes}" && set_capabilities SETUID $SETUID 272 | SETGID="${CAP_SETGID:-yes}" && set_capabilities SETGID $SETGID 273 | 274 | ## Enabled/Others 275 | AUDIT_CONTROL="${CAP_AUDIT_CONTROL:-no}" && set_capabilities AUDIT_CONTROL $AUDIT_CONTROL 276 | BLOCK_SUSPEND="${CAP_BLOCK_SUSPEND:-no}" && set_capabilities BLOCK_SUSPEND $BLOCK_SUSPEND 277 | DAC_READ_SEARCH="${CAP_DAC_READ_SEARCH:-no}" && set_capabilities DAC_READ_SEARCH $DAC_READ_SEARCH 278 | IPC_LOCK="${CAP_IPC_LOCK:-no}" && set_capabilities IPC_LOCK $IPC_LOCK 279 | IPC_OWNER="${CAP_IPC_OWNER:-no}" && set_capabilities IPC_OWNER $IPC_OWNER 280 | LEASE="${CAP_LEASE:-no}" && set_capabilities LEASE $LEASE 281 | LINUX_IMMUTABLE="${CAP_LINUX_IMMUTABLE:-no}" && set_capabilities LINUX_IMMUTABLE $LINUX_IMMUTABLE 282 | NET_ADMIN="${CAP_NET_ADMIN:-no}" && set_capabilities NET_ADMIN $NET_ADMIN 283 | NET_BROADCAST="${CAP_NET_BROADCAST:-no}" && set_capabilities NET_BROADCAST $NET_BROADCAST 284 | SYS_BOOT="${CAP_SYS_BOOT:-no}" && set_capabilities SYS_BOOT $SYS_BOOT 285 | SYS_MODULE="${CAP_SYS_MODULE:-no}" && set_capabilities SYS_MODULE $SYS_MODULE 286 | SYS_PACCT="${CAP_SYS_PACCT:-no}" && set_capabilities SYS_PACCT $SYS_PACCT 287 | SYS_PTRACE="${CAP_SYS_PTRACE:-no}" && set_capabilities SYS_PTRACE $SYS_PTRACE 288 | SYS_NICE="${CAP_SYS_NICE:-no}" && set_capabilities SYS_NICE $SYS_NICE 289 | SYS_RAWIO="${CAP_SYS_RAWIO:-no}" && set_capabilities SYS_RAWIO $SYS_RAWIO 290 | SYS_RESOURCE="${CAP_SYS_RESOURCE:-no}" && set_capabilities SYS_RESOURCE $SYS_RESOURCE 291 | SYS_TIME="${CAP_SYS_TIME:-no}" && set_capabilities SYS_TIME $SYS_TIME 292 | SYS_TTY_CONFIG="${CAP_SYS_TTY_CONFIG:-no}" && set_capabilities SYS_TTY_CONFIG $SYS_TTY_CONFIG 293 | WAKE_ALARM="${CAP_SYS_PTRACE:-no}" && set_capabilities WAKE_ALARM $WAKE_ALARM 294 | } 295 | 296 | ##################################################################### 297 | # Build command line options for ulimit settings 298 | # Globals: 299 | # ULIMIT_OPTIONS - Stores Docker ulimit cmd-line options 300 | # Arguments: 301 | # limit - Ulimit name 302 | # value - Value of ulimit settings 303 | # Returns: 304 | # None 305 | ##################################################################### 306 | 307 | set_ulimits(){ 308 | local limit="$1" 309 | local value="$2" 310 | 311 | [[ "$value" = "no" ]] || ULIMIT_OPTIONS="${ULIMIT_OPTIONS} --ulimit ${limit}=${value}" 312 | } 313 | 314 | ################################################################## 315 | # Check and set value of ulimits per container 316 | # Globals: 317 | # ulimit variables - Option in ISLET configuration files 318 | # Arguments: 319 | # None 320 | # Returns: 321 | # None 322 | ################################################################## 323 | 324 | check_ulimits(){ 325 | unset ULIMIT_OPTIONS 326 | 327 | # Set ulimits per container 328 | [[ "$ULIMIT_CORE" ]] && set_ulimits core $ULIMIT_CORE 329 | [[ "$ULIMIT_CPU" ]] && set_ulimits cpu $ULIMIT_CPU 330 | [[ "$ULIMIT_DATA" ]] && set_ulimits data $ULIMIT_DATA 331 | [[ "$ULIMIT_FSIZE" ]] && set_ulimits fsize $ULIMIT_FSIZE 332 | [[ "$ULIMIT_LOCKS" ]] && set_ulimits locks $ULIMIT_LOCKS 333 | [[ "$ULIMIT_MEMLOCK" ]] && set_ulimits memlock $ULIMIT_MEMLOCK 334 | [[ "$ULIMIT_MSGQUEUE" ]] && set_ulimits msgqueue $ULIMIT_MSGQUEUE 335 | [[ "$ULIMIT_NICE" ]] && set_ulimits nice $ULIMIT_NICE 336 | [[ "$ULIMIT_NOFILE" ]] && set_ulimits nofile $ULIMIT_NOFILE 337 | [[ "$ULIMIT_NPROC" ]] && set_ulimits nproc $ULIMIT_NPROC 338 | [[ "$ULIMIT_RSS" ]] && set_ulimits rss $ULIMIT_RSS 339 | [[ "$ULIMIT_RTPRIO" ]] && set_ulimits rtprio $ULIMIT_RTPRIO 340 | [[ "$ULIMIT_RTTIME" ]] && set_ulimits rttime $ULIMIT_RTTIME 341 | [[ "$ULIMIT_SIGPENDING" ]] && set_ulimits sigpending $ULIMIT_SIGPENDING 342 | [[ "$ULIMIT_STACK" ]] && set_ulimits stack $ULIMIT_STACK 343 | } 344 | 345 | ################################################################## 346 | # Setup variables for inclusion by Docker 347 | # Globals: 348 | # ENVS - Option in ISLET configuration files 349 | # Arguments: 350 | # None 351 | # Returns: 352 | # None 353 | ################################################################## 354 | 355 | env_setup(){ 356 | for i in $ENVS; do 357 | ENV_CMD="${ENV_CMD} --env $i" 358 | done 359 | } 360 | 361 | ############################################################################################### 362 | # Pass all options to Docker and replace this process with the container 363 | # Globals: 364 | # BASE - Environment base filename, is container prefix used to build container name 365 | # USERNAME - given username for login, container postfix, used to build container name 366 | # HOSTNAME - from ISLET config files, hostname of container 367 | # COMMAND - from ISLET config files, set entrypoint command for container 368 | # CPUSHARES - from ISLET config files, relative cpu share allocation per container 369 | # MEMORY - from ISLET config files, memory allocation per container 370 | # SWAP - from ISLET config files, swap memory allocation per container 371 | # NETWORK - from ISLET config files, network settings for container 372 | # DNS - from ISLET config files, nameservers for container 373 | # GLOBAL_OPTIONS - from ISLET config files, pass docker options to all containers 374 | # LOCAL_OPTIONS - from ISLET config files, pass per-environment docker options 375 | # MOUNT - from ISLET config files, pass mount options to docker 376 | # REMOVE - from ISLET config files, remove container after exit 377 | # ENVIRONMENT - from ISLET config files, docker image to launch 378 | # VIRTUSER - from ISLET config files, user to become in container 379 | # ENVS - from ISLET config files, environment variables to set in container 380 | # WORKDIR - from ISLET config files, working directory in container 381 | # CLIENT - ip address of connecting user 382 | # SRCPORT - source port of connecting user 383 | # SERVER - ip address of islet server 384 | # DSTPORT - ssh destination port of islet server 385 | # SSH_TTY - name of the tty associated with the current shell 386 | # TERM - terminal used 387 | # PPID - pid of the sshd process of the user's session 388 | # TMOUT - shell's timeout value 389 | # TIMEOUT - from ISLET config files, max time container can run 390 | # INFOLEVEL - from ISLET config files, DEBUG'ing information 391 | # Arguments: 392 | # None 393 | # Returns: 394 | # None 395 | ############################################################################################### 396 | 397 | start(){ 398 | import_configs 399 | local result 400 | does_image_exist 401 | removal_setup 402 | port_forwarding_setup 403 | check_capabilities 404 | check_ulimits 405 | env_setup 406 | 407 | local name_opt="--name="${BASE}.${USERNAME}" --tty --hostname $HOSTNAME" 408 | local res_opt="--cpu-shares ${CPUSHARES:-1024} --memory ${MEMORY:-0} --memory-swap ${SWAP:--1}" 409 | local net_opt="$PUBLISH --net $NETWORK --dns $DNS --add-host $HOSTNAME:127.0.0.1" 410 | local glb_opt="$GLOBAL_OPTIONS" 411 | local oth_opt="$LOCAL_OPTIONS" 412 | local cap_opt="$CAPABILITIES_OPTIONS" 413 | local lmt_opt="$ULIMIT_OPTIONS" 414 | local mnt_opt="$MOUNT" 415 | local dir_opt="--workdir ${WORKDIR:-/home/$VIRTUSER}" 416 | local env_opt="--user ${VIRTUSER:-root} $ENV_CMD" 417 | local img_opt="$REMOVE --interactive $ENVIRONMENT" 418 | local cmd_opt="${COMMAND:-bash}" 419 | local tim_opt="timeout -s KILL $TIMEOUT" 420 | 421 | # If debugging is yes 422 | is_debug "shell: CLIENT=$CLIENT SRCPORT=$SRCPORT SERVER=$SERVER DSTPORT=$DSTPORT SSH_TTY=$SSH_TTY TERM=$TERM PPID=$PPID TMOUT=$TMOUT" 423 | is_debug "opt: $SUDO_DOCKER docker run $name_opt $res_opt $net_opt $glb_opt $oth_opt $mnt_opt $cap_opt $lmt_opt $dir_opt $env_opt $img_opt $tim_opt $cmd_opt" 424 | 425 | notice "Enjoy yourself!" 426 | mention "$MOTD" 427 | 428 | # Run container 429 | eval $SUDO_DOCKER docker run "$name_opt $res_opt $net_opt $glb_opt $oth_opt $cap_opt $lmt_opt $mnt_opt $dir_opt $env_opt $img_opt $tim_opt $cmd_opt" "$INFOLEVEL" 430 | exit_handler $? 431 | } 432 | 433 | "$@" 434 | -------------------------------------------------------------------------------- /plugins/clear: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | clear 3 | -------------------------------------------------------------------------------- /plugins/del_container: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | [[ -f "$DB" ]] || alert "$DB cannot be found..contact the administrator" 3 | 4 | get_user_images() { 5 | image_list=$(sqlite3 "$DB" "SELECT environment FROM environments WHERE user='$USERNAME';") 6 | } 7 | 8 | get_image() { 9 | container="$1" 10 | image=$(sqlite3 "$DB" "SELECT environment FROM environments WHERE user='$USERNAME' AND environment='$container';") 11 | } 12 | 13 | delete_image(){ 14 | notice "Removing existing container.." 15 | sqlite3 "$DB" "pragma foreign_keys = on; DELETE FROM environments WHERE user='$USERNAME' AND environment='$container';" 16 | $SUDO_DOCKER docker stop "${i}.$USERNAME" 2>&1 > /dev/null 17 | $SUDO_DOCKER docker rm "${i}.$USERNAME" 2>&1 > /dev/null 18 | alert "Container removed!" 19 | sleep 1 20 | } 21 | 22 | delete_menu(){ 23 | # Check for existing containers 24 | [[ $image_list ]] || { notice "There are no existing containers to delete" && return 0; } 25 | 26 | notice "Choose one of your existing containers to delete (0 for main menu):" 27 | PS3="${Y}[${N}${BF}Choice${N}${Y}]${N}: " 28 | # Here the user chooses which container to delete 29 | local count=0 30 | local failure_count=3 31 | 32 | select i in $image_list 33 | do 34 | # Check user selected image against database 35 | get_image $i 36 | 37 | # Return to main menu if image was not in database (empty) 38 | [[ $image ]] || return 0 39 | 40 | # Execute delete_image if image in database matches user's choice 41 | if [[ "$image" = "$i" ]]; then 42 | delete_image 43 | break 44 | fi 45 | done 46 | } 47 | 48 | if file "$DB" 2>/dev/null | grep -q SQLite; then 49 | get_user_images 50 | delete_menu 51 | else 52 | alert "There is a database issue..contact the administrator" 53 | fi 54 | # Cleanup 55 | unset image image_list 56 | -------------------------------------------------------------------------------- /plugins/del_user: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | [[ -f "$DB" ]] || alert "$DB cannot be found..contact the administrator" 3 | 4 | if file "$DB" 2>/dev/null | grep -q SQLite; then 5 | notice "Removing user ${USERNAME}.." 6 | sqlite3 "$DB" "pragma foreign_keys = on; DELETE FROM accounts where user='$USERNAME';" 7 | alert "Account removed, exiting..." && exit 8 | sleep 1 9 | else 10 | [[ -f "$DB" ]] || alert "There is a database issue..contact the administrator" 11 | fi 12 | -------------------------------------------------------------------------------- /plugins/restart: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | if [[ -f "$SHELL" ]]; then 3 | exec "$SHELL" 4 | alert "Failed to execute ${PLUGIN}..contact the administrator" 5 | fi 6 | --------------------------------------------------------------------------------