diff options
author | Mike Crute <mike@crute.us> | 2017-11-27 02:02:55 +0000 |
---|---|---|
committer | Mike Crute <mike@crute.us> | 2017-11-27 02:02:55 +0000 |
commit | fe2b6a1eacadafb517a71d1d30ca044333e302aa (patch) | |
tree | e687c943c2d8535771877e171c5d6d217dd423df /ssh-bastion | |
parent | dfff68a50cab4a590d196b95cb7276aac484f6a7 (diff) | |
download | dockerfiles-fe2b6a1eacadafb517a71d1d30ca044333e302aa.tar.bz2 dockerfiles-fe2b6a1eacadafb517a71d1d30ca044333e302aa.tar.xz dockerfiles-fe2b6a1eacadafb517a71d1d30ca044333e302aa.zip |
Convert ssh bastion to alpine
Diffstat (limited to 'ssh-bastion')
-rw-r--r-- | ssh-bastion/Dockerfile | 29 | ||||
-rw-r--r-- | ssh-bastion/Makefile | 19 | ||||
-rwxr-xr-x | ssh-bastion/entrypoint.sh | 30 | ||||
-rw-r--r-- | ssh-bastion/etc/pam.d/sshd | 5 | ||||
-rw-r--r-- | ssh-bastion/etc/ssh/sshd_config (renamed from ssh-bastion/etc/sshd_config) | 16 | ||||
-rw-r--r-- | ssh-bastion/etc/sshd-pam | 60 |
6 files changed, 63 insertions, 96 deletions
diff --git a/ssh-bastion/Dockerfile b/ssh-bastion/Dockerfile index 05dade3..c9ded23 100644 --- a/ssh-bastion/Dockerfile +++ b/ssh-bastion/Dockerfile | |||
@@ -1,22 +1,17 @@ | |||
1 | FROM ubuntu:14.04 | 1 | FROM alpine:edge |
2 | MAINTAINER Michael Crute <mike@crute.us> | 2 | LABEL maintainer="Mike Crute <mike@crute.us>" |
3 | |||
4 | RUN export DEBIAN_FRONTEND=noninteractive && \ | ||
5 | apt-get update && \ | ||
6 | apt-get install -y openssh-server libpam-google-authenticator && \ | ||
7 | mkdir /var/run/sshd && \ | ||
8 | chmod 700 /var/run/sshd | ||
9 | |||
10 | ADD etc/sshd_config /etc/ssh/sshd_config | ||
11 | ADD etc/sshd-pam /etc/pam.d/sshd | ||
12 | ADD entrypoint.sh /entrypoint.sh | ||
13 | 3 | ||
4 | # https://wiki.alpinelinux.org/wiki/Two_Factors_Authentication_With_OpenSSH | ||
14 | RUN \ | 5 | RUN \ |
15 | apt-get clean && \ | 6 | apk add --no-cache \ |
16 | rm -rf /var/lib/apt/lists/* && \ | 7 | openssh-server-pam \ |
17 | rm -rf /tmp/* | 8 | google-authenticator \ |
9 | && cp /etc/ssh/sshd_config /etc/ssh/sshd_config.alpine \ | ||
10 | && mkdir /var/run/sshd \ | ||
11 | && chmod 700 /var/run/sshd | ||
12 | |||
13 | ADD etc/ /etc/ | ||
14 | ADD entrypoint.sh / | ||
18 | 15 | ||
19 | EXPOSE 4321 | ||
20 | VOLUME "/srv/ssh" | ||
21 | ENTRYPOINT [ "/entrypoint.sh" ] | 16 | ENTRYPOINT [ "/entrypoint.sh" ] |
22 | CMD [ "/usr/sbin/sshd", "-D", "-e" ] | 17 | CMD [ "/usr/sbin/sshd", "-D", "-e" ] |
diff --git a/ssh-bastion/Makefile b/ssh-bastion/Makefile index 9090c53..ffb1275 100644 --- a/ssh-bastion/Makefile +++ b/ssh-bastion/Makefile | |||
@@ -1,8 +1,19 @@ | |||
1 | REPO=575365190010.dkr.ecr.us-west-2.amazonaws.com | ||
2 | IMAGE=ssh-bastion:latest-alpine | ||
3 | |||
1 | all: | 4 | all: |
2 | docker build -t ssh-bastion . | 5 | docker build -t $(IMAGE) . |
6 | |||
7 | all-no-cache: | ||
8 | docker build --no-cache -t $(IMAGE) . | ||
3 | 9 | ||
4 | run: | 10 | run: |
5 | docker run -d \ | 11 | docker run \ |
6 | -p 4321:4321 \ | 12 | -p 4321:4321 \ |
7 | -v /srv/ssh-bastion:/srv/ssh \ | 13 | -v /home/mcrute/tmp/ssh:/srv/ssh \ |
8 | ssh-bastion | 14 | $(IMAGE) |
15 | |||
16 | publish: | ||
17 | eval $$(aws ecr get-login --region us-west-2) | ||
18 | docker tag $(IMAGE) $(REPO)/$(IMAGE) | ||
19 | docker push $(REPO)/$(IMAGE) | ||
diff --git a/ssh-bastion/entrypoint.sh b/ssh-bastion/entrypoint.sh index aa8a8e6..f48a3c3 100755 --- a/ssh-bastion/entrypoint.sh +++ b/ssh-bastion/entrypoint.sh | |||
@@ -1,9 +1,28 @@ | |||
1 | #!/bin/bash | 1 | #!/bin/sh |
2 | 2 | ||
3 | cd /srv/ssh/users | 3 | if [ ! -d /srv/ssh/hostkeys ]; then |
4 | echo "No host keys found... generating" | ||
5 | mkdir -p /srv/ssh/hostkeys | ||
4 | 6 | ||
5 | for user in *; do | 7 | ssh-keygen -f /srv/ssh/hostkeys/rsa_key -N '' -t rsa |
6 | if getent passwd $user 2>&1>/dev/null; then | 8 | ssh-keygen -f /srv/ssh/hostkeys/ed25519_key -N '' -t ed25519 |
9 | ssh-keygen -f /srv/ssh/hostkeys/ecdsa_key -N '' -t ecdsa | ||
10 | |||
11 | rm *.pub | ||
12 | fi | ||
13 | |||
14 | if [ ! -d /srv/ssh/users ]; then | ||
15 | echo "No users directory found... creating" | ||
16 | mkdir -p /srv/ssh/users | ||
17 | fi | ||
18 | |||
19 | for path in /srv/ssh/users/*; do | ||
20 | user=$(basename $path) | ||
21 | if [ "$user" = "*" ]; then | ||
22 | break | ||
23 | fi | ||
24 | |||
25 | if getent passwd $user 2>&1 >/dev/null; then | ||
7 | echo "User $user already exists" | 26 | echo "User $user already exists" |
8 | continue | 27 | continue |
9 | fi | 28 | fi |
@@ -14,7 +33,8 @@ for user in *; do | |||
14 | exit 1 | 33 | exit 1 |
15 | fi | 34 | fi |
16 | 35 | ||
17 | useradd -MN -s /usr/sbin/nologin -u $uid $user | 36 | echo "Creating user ${user}(${uid})" |
37 | adduser -DH -s /sbin/nologin -u $uid $user | ||
18 | done | 38 | done |
19 | 39 | ||
20 | exec "$@" | 40 | exec "$@" |
diff --git a/ssh-bastion/etc/pam.d/sshd b/ssh-bastion/etc/pam.d/sshd new file mode 100644 index 0000000..b0f90a4 --- /dev/null +++ b/ssh-bastion/etc/pam.d/sshd | |||
@@ -0,0 +1,5 @@ | |||
1 | account include base-account | ||
2 | |||
3 | auth required pam_google_authenticator.so secret=/srv/ssh/users/${USER}/totp user=root no_strict_owner | ||
4 | |||
5 | session required pam_unix.so | ||
diff --git a/ssh-bastion/etc/sshd_config b/ssh-bastion/etc/ssh/sshd_config index 3177765..e46b5c6 100644 --- a/ssh-bastion/etc/sshd_config +++ b/ssh-bastion/etc/ssh/sshd_config | |||
@@ -3,11 +3,16 @@ | |||
3 | HostKey /srv/ssh/hostkeys/rsa_key | 3 | HostKey /srv/ssh/hostkeys/rsa_key |
4 | HostKey /srv/ssh/hostkeys/ed25519_key | 4 | HostKey /srv/ssh/hostkeys/ed25519_key |
5 | 5 | ||
6 | # By default SSH attempts to chdir to the logged-in user's home directory. The | 6 | # By default SSH attempts to chdir to the logged-in user's home directory. The |
7 | # vast majority of users won't have a home directory on the machine, so | 7 | # vast majority of users won't have a home directory on the machine, so |
8 | # suppress the warning with a chroot. | 8 | # suppress the warning with a chroot. |
9 | ChrootDirectory / | 9 | ChrootDirectory / |
10 | 10 | ||
11 | # No users will have home directories and all configs are under control of the | ||
12 | # admin who mounts them from outside of this docker container so there is no | ||
13 | # need to check modes and in-fact enabling this will cause failures. | ||
14 | StrictModes no | ||
15 | |||
11 | Protocol 2 | 16 | Protocol 2 |
12 | 17 | ||
13 | # Bind a port above 1024 so we can run ssh as an unpriviledged user | 18 | # Bind a port above 1024 so we can run ssh as an unpriviledged user |
@@ -15,8 +20,6 @@ Port 4321 | |||
15 | 20 | ||
16 | SyslogFacility AUTH | 21 | SyslogFacility AUTH |
17 | LogLevel INFO | 22 | LogLevel INFO |
18 | PrintLastLog yes | ||
19 | StrictModes yes | ||
20 | PidFile /var/run/sshd.pid | 23 | PidFile /var/run/sshd.pid |
21 | 24 | ||
22 | PubkeyAuthentication yes | 25 | PubkeyAuthentication yes |
@@ -24,11 +27,9 @@ HostbasedAuthentication no | |||
24 | IgnoreRhosts yes | 27 | IgnoreRhosts yes |
25 | PasswordAuthentication no | 28 | PasswordAuthentication no |
26 | PermitEmptyPasswords no | 29 | PermitEmptyPasswords no |
27 | RhostsRSAAuthentication no | ||
28 | AuthorizedKeysFile /srv/ssh/users/%u/ssh | 30 | AuthorizedKeysFile /srv/ssh/users/%u/ssh |
29 | 31 | ||
30 | UsePAM yes | 32 | UsePAM yes |
31 | UseLogin no | ||
32 | PermitRootLogin no | 33 | PermitRootLogin no |
33 | ChallengeResponseAuthentication yes | 34 | ChallengeResponseAuthentication yes |
34 | AuthenticationMethods publickey,keyboard-interactive:pam | 35 | AuthenticationMethods publickey,keyboard-interactive:pam |
@@ -44,11 +45,6 @@ ForceCommand /usr/bin/nologin | |||
44 | # the host but not be allowed to login or run any commands. | 45 | # the host but not be allowed to login or run any commands. |
45 | MaxSessions 0 | 46 | MaxSessions 0 |
46 | 47 | ||
47 | # Use an unprivileged child process to accept connections and | ||
48 | # authenticate the user before spinning up another process as | ||
49 | # the user. | ||
50 | UsePrivilegeSeparation yes | ||
51 | |||
52 | # This turns off reverse lookups of the originating host which hang sshd | 48 | # This turns off reverse lookups of the originating host which hang sshd |
53 | # on DNS timeouts when DNS is down. This also breaks "from=" lines in | 49 | # on DNS timeouts when DNS is down. This also breaks "from=" lines in |
54 | # authorizd_keys files which must be converted to dotted quad ip addrs. | 50 | # authorizd_keys files which must be converted to dotted quad ip addrs. |
diff --git a/ssh-bastion/etc/sshd-pam b/ssh-bastion/etc/sshd-pam deleted file mode 100644 index a62ba2b..0000000 --- a/ssh-bastion/etc/sshd-pam +++ /dev/null | |||
@@ -1,60 +0,0 @@ | |||
1 | # PAM configuration for the Secure Shell service | ||
2 | |||
3 | # Standard Un*x authentication. | ||
4 | # Exclude common auth and prefer google authenticator only | ||
5 | #@include common-auth | ||
6 | auth [success=1 default=ignore] pam_google_authenticator.so secret=/srv/ssh/users/${USER}/totp user=root | ||
7 | auth requisite pam_deny.so | ||
8 | auth required pam_permit.so | ||
9 | auth optional pam_cap.so | ||
10 | |||
11 | # Disallow non-root logins when /etc/nologin exists. | ||
12 | account required pam_nologin.so | ||
13 | |||
14 | # Uncomment and edit /etc/security/access.conf if you need to set complex | ||
15 | # access limits that are hard to express in sshd_config. | ||
16 | # account required pam_access.so | ||
17 | |||
18 | # Standard Un*x authorization. | ||
19 | @include common-account | ||
20 | |||
21 | # SELinux needs to be the first session rule. This ensures that any | ||
22 | # lingering context has been cleared. Without this it is possible that a | ||
23 | # module could execute code in the wrong domain. | ||
24 | session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so close | ||
25 | |||
26 | # Set the loginuid process attribute. | ||
27 | session required pam_loginuid.so | ||
28 | |||
29 | # Create a new session keyring. | ||
30 | session optional pam_keyinit.so force revoke | ||
31 | |||
32 | # Standard Un*x session setup and teardown. | ||
33 | @include common-session | ||
34 | |||
35 | # Print the message of the day upon successful login. | ||
36 | # This includes a dynamically generated part from /run/motd.dynamic | ||
37 | # and a static (admin-editable) part from /etc/motd. | ||
38 | session optional pam_motd.so motd=/run/motd.dynamic noupdate | ||
39 | session optional pam_motd.so # [1] | ||
40 | |||
41 | # Print the status of the user's mailbox upon successful login. | ||
42 | session optional pam_mail.so standard noenv # [1] | ||
43 | |||
44 | # Set up user limits from /etc/security/limits.conf. | ||
45 | session required pam_limits.so | ||
46 | |||
47 | # Read environment variables from /etc/environment and | ||
48 | # /etc/security/pam_env.conf. | ||
49 | session required pam_env.so # [1] | ||
50 | # In Debian 4.0 (etch), locale-related environment variables were moved to | ||
51 | # /etc/default/locale, so read that as well. | ||
52 | session required pam_env.so user_readenv=1 envfile=/etc/default/locale | ||
53 | |||
54 | # SELinux needs to intervene at login time to ensure that the process starts | ||
55 | # in the proper default security context. Only sessions which are intended | ||
56 | # to run in the user's context should be run after this. | ||
57 | session [success=ok ignore=ignore module_unknown=ignore default=bad] pam_selinux.so open | ||
58 | |||
59 | # Standard Un*x password updating. | ||
60 | @include common-password | ||