├── .dockerignore ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── docker-compose.yml ├── init └── webmin-miniserv-user /.dockerignore: -------------------------------------------------------------------------------- 1 | .dockerignore 2 | .git 3 | .gitignore 4 | docker-compose.yml 5 | LICENSE 6 | README.md 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.yml 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM centos:7 2 | MAINTAINER Ira W. Snyder 3 | 4 | ENV WEBMIN_VERSION 1.810 5 | ENV WEBMIN_RELEASE 1 6 | ENV TINI_VERSION v0.10.0 7 | 8 | ENTRYPOINT [ "/init" ] 9 | EXPOSE 10000 10 | 11 | RUN yum -y install http://downloads.sourceforge.net/project/webadmin/webmin/${WEBMIN_VERSION}/webmin-${WEBMIN_VERSION}-${WEBMIN_RELEASE}.noarch.rpm \ 12 | && yum -y install openldap-servers perl-LDAP \ 13 | && yum -y update \ 14 | && yum -y clean all 15 | 16 | RUN curl -L https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini > /usr/bin/tini \ 17 | && chmod +x /usr/bin/tini 18 | 19 | COPY webmin-miniserv-user /usr/bin/ 20 | COPY init / 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Ira W. Snyder 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | 4 | This is a containerized version of Webmin, developed specifically to provide a 5 | web interface to manage LDAP users and groups. No other server management 6 | features are exposed to the users. It is designed to be used as a frontend so 7 | that non-administrator users can add and remove LDAP users and groups without 8 | knowing all the intricacies of LDAP itself. 9 | 10 | The container is designed to be completely stateless. You *should not* need to 11 | save any of the files from within the container to maintain the desired 12 | functionality. 13 | 14 | An example `docker-compose.yml` is provided for easy startup. 15 | 16 | Environment Variables 17 | ===================== 18 | 19 | This section describes all of the environment variables that can be used to 20 | customize the behavior of this container. Please override them with values 21 | specific to your configuration. 22 | 23 | Users and Passwords 24 | ------------------- 25 | 26 | - `WEBMIN_ROOT_PASSWORD` - The Webmin root password (default: "root") 27 | - `WEBMIN_LDAP_ADMINISTRATORS` - The Webmin LDAP Administrator user/password combos (default: "admin1:password1,admin2:password2") 28 | - `WEBMIN_SSL` - Enable or disable SSL mode in Webmin (default: "1") 29 | 30 | LDAP Server Settings 31 | -------------------- 32 | 33 | - `LDAP_URI` - LDAP Server URI (default: "ldap://ldap.example.com") 34 | - `LDAP_BINDDN` - LDAP Bind DN (default: "cn=admin,dc=example,dc=com") 35 | - `LDAP_BINDPW` - LDAP Bind Password (default: "password") 36 | - `LDAP_BASE` - LDAP Base DN (default: "dc=example,dc=com") 37 | 38 | Webmin ldap-useradmin Module Settings 39 | ------------------------------------- 40 | 41 | - `LDAP_BASE_UID` - Starting user id for new users (default: "500") 42 | - `LDAP_BASE_GID` - Starting group id for new groups (default: "500") 43 | - `LDAP_DEFAULT_SHELL` - Default shell for new users (default: "/bin/sh") 44 | - `LDAP_DEFAULT_GROUP` - Default group for new users (default: "ldapgroup") 45 | - `LDAP_HOME_BASE` - Default base of home directories (default: "/home") 46 | - `LDAP_USER_BASE` - Default organizational unit for users (default: "ou=Users,dc=example,dc=com") 47 | - `LDAP_GROUP_BASE` - Default organizational unit for groups (default: "ou=Groups,dc=example,dc=com") 48 | - `LDAP_SHELLS` - Set the shells that are available in the UI (default: "/bin/bash,/bin/tcsh,/bin/zsh") 49 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | webmin: 2 | image: irasnyd/webmin-ldap 3 | ports: 4 | - "10000:10000" 5 | environment: 6 | - "WEBMIN_ROOT_PASSWORD=supersecret" 7 | - "WEBMIN_LDAP_ADMINISTRATORS=user1:pass1,user2:pass2" 8 | - "WEBMIN_SSL=1" 9 | - "LDAP_URI=ldap://ldap.example.com" 10 | - "LDAP_BINDDN=cn=admin,dc=example,dc=com" 11 | - "LDAP_BINDPW=adminpassword" 12 | - "LDAP_BASE=dc=example,dc=com" 13 | - "LDAP_BASE_UID=10000" 14 | - "LDAP_BASE_GID=10000" 15 | - "LDAP_DEFAULT_SHELL=/bin/bash" 16 | - "LDAP_DEFAULT_GROUP=ldapusers" 17 | - "LDAP_USER_BASE=ou=Users,dc=example,dc=com" 18 | - "LDAP_GROUP_BASE=ou=Groups,dc=example,dc=com" 19 | mem_limit: "1g" 20 | restart: "always" 21 | -------------------------------------------------------------------------------- /init: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # webmin root password 4 | WEBMIN_ROOT_PASSWORD="${WEBMIN_ROOT_PASSWORD:-root}" 5 | 6 | # webmin ldap administrators 7 | WEBMIN_LDAP_ADMINISTRATORS="${WEBMIN_LDAP_ADMINISTRATORS:-admin1:password1,admin2:password2}" 8 | 9 | # enable ssl 10 | WEBMIN_SSL="${WEBMIN_SSL:-1}" 11 | 12 | # webmin ldap server settings 13 | LDAP_URI="${LDAP_URI:-ldap://ldap.example.com}" 14 | LDAP_BINDDN="${LDAP_BINDDN:-cn=admin,dc=example,dc=com}" 15 | LDAP_BINDPW="${LDAP_BINDPW:-password}" 16 | LDAP_BASE="${LDAP_BASE:-dc=example,dc=com}" 17 | 18 | # webmin ldap useradmin module settings 19 | LDAP_BASE_UID="${LDAP_BASE_UID:-500}" 20 | LDAP_BASE_GID="${LDAP_BASE_GID:-500}" 21 | LDAP_DEFAULT_SHELL="${LDAP_DEFAULT_SHELL:-/bin/sh}" 22 | LDAP_DEFAULT_GROUP="${LDAP_DEFAULT_GROUP:-ldapgroup}" 23 | LDAP_HOME_BASE="${LDAP_HOME_BASE:-/home}" 24 | LDAP_USER_BASE="${LDAP_USER_BASE:-ou=Users,dc=example,dc=com}" 25 | LDAP_GROUP_BASE="${LDAP_GROUP_BASE:-ou=Groups,dc=example,dc=com}" 26 | LDAP_SHELLS="${LDAP_SHELLS:-/bin/bash,/bin/tcsh,/bin/zsh}" 27 | 28 | # set root password 29 | echo "$WEBMIN_ROOT_PASSWORD" | passwd --stdin root 30 | 31 | # Create /etc/nslcd.conf for automatic LDAP setup of the 32 | # webmin ldap-useradmin module. We use this method rather than 33 | # setting the configuration directly, because it allows us to specify 34 | # the LDAP bind password. 35 | cat > /etc/nslcd.conf << EOF 36 | uri ${LDAP_URI} 37 | binddn ${LDAP_BINDDN} 38 | bindpw ${LDAP_BINDPW} 39 | base ${LDAP_BASE} 40 | EOF 41 | 42 | # Set a value in a webmin configuration file 43 | # $1: configuration file name 44 | # $2: key 45 | # $3: value 46 | webmin_config_set() { 47 | local CONF="$1" KEY="$2" VALUE="$3" 48 | sed -i -e "/^${KEY}=.*$/d" "${CONF}" 49 | echo "${KEY}=${VALUE}" >> "${CONF}" 50 | } 51 | 52 | # Set a Webmin ldap-useradmin module setting 53 | # $1: key 54 | # $2: value 55 | ldapuseradmin_set() { 56 | webmin_config_set "/etc/webmin/ldap-useradmin/config" "$1" "$2" 57 | } 58 | 59 | # add webmin settings for ldap-useradmin module 60 | ldapuseradmin_set "base_uid" "$LDAP_BASE_UID" 61 | ldapuseradmin_set "base_gid" "$LDAP_BASE_GID" 62 | ldapuseradmin_set "default_shell" "$LDAP_DEFAULT_SHELL" 63 | ldapuseradmin_set "home_base" "$LDAP_HOME_BASE" 64 | ldapuseradmin_set "user_base" "$LDAP_USER_BASE" 65 | ldapuseradmin_set "group_base" "$LDAP_GROUP_BASE" 66 | 67 | # set "Create and update in other modules" -> "No" 68 | ldapuseradmin_set "default_other" "0" 69 | 70 | # set "Encryption methods for passwords" -> "LDAP SSHA" 71 | ldapuseradmin_set "md5" "4" 72 | 73 | [[ -n "$LDAP_DEFAULT_GROUP" ]] && ldapuseradmin_set "default_group" "$LDAP_DEFAULT_GROUP" 74 | 75 | # webmin ssl configuration 76 | webmin_config_set "/etc/webmin/miniserv.conf" "ssl" "$WEBMIN_SSL" 77 | 78 | # create ldap administrator users which only have permissions to access the 79 | # ldap-useradmin module and nothing else 80 | IFS=$',' read -ra WEBMIN_LDAP_ADMINISTRATORS_ARRAY <<< "$WEBMIN_LDAP_ADMINISTRATORS" 81 | for i in "${WEBMIN_LDAP_ADMINISTRATORS_ARRAY[@]}"; do 82 | # create user and grant permissions 83 | /usr/bin/webmin-miniserv-user "$i" >> /etc/webmin/miniserv.users 84 | echo "${i%%:*}: ldap-useradmin system-status" >> /etc/webmin/webmin.acl 85 | 86 | # disable categories in the sidebar 87 | echo "notabs_${i%%:*}=2" >> /etc/webmin/config 88 | done 89 | 90 | # truncate /etc/shells 91 | cat > /etc/shells << EOF 92 | EOF 93 | 94 | # create /etc/shells with the user specified list 95 | IFS=$',' read -ra LDAP_SHELLS_ARRAY <<< "$LDAP_SHELLS" 96 | for i in "${LDAP_SHELLS_ARRAY[@]}"; do 97 | echo "$i" >> /etc/shells 98 | done 99 | 100 | # start webmin underneath tini init 101 | exec /usr/bin/tini -- /etc/webmin/start --nofork 102 | -------------------------------------------------------------------------------- /webmin-miniserv-user: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import crypt 4 | import sys 5 | import os 6 | 7 | def main(): 8 | ''' 9 | Take any number of parameters of colon-separated username/password pairs, 10 | and convert them into Webmin style MD5 crypted password output, suitable 11 | for use in the miniserv.users file. 12 | 13 | A random salt is used for each user. 14 | 15 | Input: 16 | username1:password1 17 | 18 | Output: 19 | The username/password crypted correctly for /etc/webmin/miniserv.users, 20 | for example: 21 | 22 | username1:$1$MPaWN4nA$9M7HDLek9c.yRbcJmQ.y5.::::::::0:::: 23 | ''' 24 | for elem in sys.argv[1:]: 25 | username, password = elem.split(':', 1) 26 | 27 | # md5 crypt with random salt 28 | salt = '$1$%s$' % (os.urandom(32).encode('base_64'), ) 29 | crypted_pw = crypt.crypt(password, salt) 30 | 31 | # correct number of colons for webmin miniserv.users format 32 | print '%s:%s::::::::0::::' % (username, crypted_pw, ) 33 | 34 | # exit successfully 35 | return 0 36 | 37 | if __name__ == '__main__': 38 | main() 39 | --------------------------------------------------------------------------------