diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..ce9ca413e970d897a8db92d8d347c1a0c881ac65 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ +FROM debian:buster-slim + +# https://manpages.debian.org/stretch/openssh-server/sshd.8.en.html +RUN apt-get -y update \ +&& apt-get -y install openssh-server + +RUN mkdir /var/run/sshd + +RUN chmod g+r /etc/ssh/ssh_host_ed25519_key + +# OpenShift pod will run as non-root user, who can't create pid file. +RUN touch /run/sshd.pid \ +&& chmod g+w /run/sshd.pid + +# Create sftpuser. Password authentication is disabled in sshd. +RUN useradd -g root sftpuser -p '*' \ +&& chmod g+w /home + +# Make /etc/passwd writable by root group. So sftpuser can take UID of running pod. +RUN chmod g+w /etc/passwd + +EXPOSE 2022 + +COPY sshd_config /etc/ssh/sshd_config +RUN chmod g+r /etc/ssh/sshd_config + +COPY startup.sh /usr/local/bin +RUN chmod +x /usr/local/bin/startup.sh +CMD ["startup.sh"] diff --git a/openshift-artifacts/bc-umich-sftp.json b/openshift-artifacts/bc-umich-sftp.json index fb4fd06ebca6b697a329c85d7c22d9ea2874165a..f844d832eb2b0ee8d580174da90fdfdba6026854 100644 --- a/openshift-artifacts/bc-umich-sftp.json +++ b/openshift-artifacts/bc-umich-sftp.json @@ -29,16 +29,10 @@ }, "strategy": { "dockerStrategy": { - "buildArgs": [ - { - "name": "SFTP_UID", - "value": "REPLACE_ME" - } - ], "from": { "kind": "ImageStreamTag", - "name": "ubuntu-ssh:latest", - "namespace": "openshift" + "name": "debian:buster-slim", + "namespace": "its-curation" } }, "type": "Docker" @@ -47,7 +41,7 @@ "triggers": [ { "imageChange": { - "lastTriggeredImageID": "docker-registry.default.svc:5000/openshift/ubuntu-ssh:latest" + "lastTriggeredImageID": "docker-registry.default.svc:5000/its-curation/umich-sftp:latest" }, "type": "ImageChange" }, diff --git a/openshift-artifacts/dc-umich-sftp.json b/openshift-artifacts/dc-umich-sftp.json index 2f6e04951668afe791d8b3a75608ce2279966ffb..a3b4978503d494e16ddea48dd79ecc6178bc99dd 100644 --- a/openshift-artifacts/dc-umich-sftp.json +++ b/openshift-artifacts/dc-umich-sftp.json @@ -39,7 +39,7 @@ "spec": { "containers": [ { - "image": "docker-registry.default.svc:5000/NAMESPACE/umich-sftp:latest", + "image": "docker-registry.default.svc:5000/openshift/umich-sftp:latest", "imagePullPolicy": "Always", "name": "umich-sftp", "ports": [ @@ -87,7 +87,7 @@ "from": { "kind": "ImageStreamTag", "name": "umich-sftp:latest", - "namespace": "NAMESPACE" + "namespace": "openshift" } }, "type": "ImageChange" diff --git a/README.md b/readme.md similarity index 60% rename from README.md rename to readme.md index 4d3adbcaf47f8160336d36c4e0c9089cf13d853a..0d3f63605c174572799cb1e6acde0a9475fd1745 100644 --- a/README.md +++ b/readme.md @@ -1,5 +1,5 @@ ## umich-sftp -This runs an sftp/ssh server that runs as a non-root user required for multi-tenanted container hosting systems like OpenShift. The build process creates a user: `sftpuser` that is associated with the uid used by an OpenShift project to run all pods. The range for the uid is declared in a project's annotations. Essentially, the pod runs as the sftpuser. +This runs an sftp/ssh server that runs as a non-root user required for multi-tenanted container hosting systems like OpenShift. The build process makes the /etc/passwd file writable by the root group. And the startup script modifies the UID for the `sftpuser` user, who runs the sshd server, to use that provided to the OpenShift pod. Essentially, the pod runs as the sftpuser. The startup script looks for a mounted volume at /tmp/pvc and symlinks this into the sftpuser's home directory. ### Setup Directions @@ -11,52 +11,36 @@ This runs an sftp/ssh server that runs as a non-root user required for multi-ten #### Instructions for use as a local docker container clone repo - `git clone git@gitlab.umich.edu:its-web-platforms/umich-sftp.git` -- `cd umich-sftp` -There are 2 docker images to build, the first has ubuntu and ssh config: -- `docker build -t ubuntu-ssh ./ubuntu-ssh/` +Build the image: +- `docker build -t umich-sftp .` -The second image contains user-specific instructions. -- `docker build -t umich-sftp ./umich-sftp/` +Pass in the public keys and startup the container: +- `docker run -it -p 2022:2022 -v /path/to/keys/:/tmp/keys umich-sftp` -Pass in the public keys and startup the container -- `docker run -it -p 2022:2022 -u 1000000000 -v /path/to/keys/:/tmp/keys umich-sftp` +Alternatively, pass in public keys and test for mounting volumes: +- `docker run -it -p 2022:2022 -v /path/to/keys/:/tmp/keys umich-sftp` And now sftp to the container. - `sftp -oIdentityFile=./ssh_user_ed25519_key -P 2022 sftpuser@localhost` #### Instructions for use in Openshift -The first build is made in the its-curation namespace. This will be updated whenever ubuntu or the code is updated. +The build is made in the its-curation namespace. This will be updated whenever debian:buster-slim or the code is updated. ##### NOTE: this only needs to be done once. Please check if the image already exists in its-curation and don't run these next two steps if it already exists. ``` oc project its-curation -oc new-build https://gitlab.umich.edu/its-web-platforms/umich-sftp.git --context-dir=ubuntu-ssh --name=ubuntu-ssh -oc tag its-curation/ubuntu-ssh:latest openshift/ubuntu-ssh:latest -``` - -The next build leverages the tag in the openshift namespace and is made in a user's project. Determine the UID in use by your project, and create the umich-sftp image with this: -``` -uid=$(oc get project $(oc project -q) -o custom-columns="uid:.metadata.annotations.openshift\.io\/sa\.scc\.uid-range" | tail -n +2) -uid=$(echo $uid | sed -e "s|/10000||g") -sed -i s/REPLACE_ME/$uid/g openshift-artifacts/bc-umich-sftp.json -oc create -f openshift-artifacts/bc-umich-sftp.json -``` - -Alternative build process: -``` -uid=$(oc get project $(oc project -q) -o custom-columns="uid:.metadata.annotations.openshift\.io\/sa\.scc\.uid-range" | tail -n +2) -uid=$(echo $uid | sed -e "s|/10000||g") -oc new-build openshift/ubuntu-ssh~https://gitlab.umich.edu/its-web-platforms/umich-sftp.git --context-dir=umich-sftp --build-arg SFTP_UID=$uid --strategy=docker +oc new-build https://gitlab.umich.edu/its-web-platforms/umich-sftp.git +oc tag its-curation/umich-sftp:latest openshift/umich-sftp:latest ``` Create a secret with the public key you previously generated: - The makerator will create a blank secret of the same name. You will have to delete the existing secret first in a project generated by the makerator. -- `oc create secret generic public-ssh-keys --from-file=/path/to/keys/ssh_user_ed25519_key.pub` +- `oc create secret generic public-ssh-keys --from-file=/path/to/keys/ssh_user_ed25519_key.pub`, or for multiple keys: +- `oc create secret generic public-ssh-keys --from-file=/path/to/keys/*.pub` Create the dc and svc. The first command updates the dc to retrieve the image from the current project: ``` -sed -i s/NAMESPACE/$(oc project -q)/g openshift-artifacts/dc-umich-sftp.json oc create -f openshift-artifacts/dc-umich-sftp.json oc create -f openshift-artifacts/svc-umich-sftp.json ``` @@ -71,12 +55,16 @@ Connect using to that instance on containersnp (need to be on VPN): - `sftp -oIdentityFile=/path/to/keys/ssh_user_ed25519_key -P 30000 sftpuser@tcp.aws-np.web.umich.edu` - NOTE: you will need to subsitute 30000 with the port from the previous command. And `tcp.aws-np.web.umich.edu` will need to be substituted with `tcp.aws.web.umich.edu` if working in the production environment. + #### Persistent Volumes -The default deployment does not mount a persistent volume. The makerator or kiri will generally create persistent volume claims and modify the deployment configuration for umich-sftp to leverage them. If you wish to test writing to persistent volumes with using makerator or kiri, perform the following operations: +The default deployment does not mount a persistent volume. The makerator or kiri will generally create persistent volume claims and modify the deployment configuration for umich-sftp to leverage them. + +If you wish to test writing to persistent volumes with using makerator or kiri, perform the following operations: ``` -oc set volume dc/umich-sftp --add --name=wps-cms-pvc -t pvc --claim-size=1G --mount-path=/home/sftpuser/wps --overwrite +oc set volume dc/umich-sftp --add --name=mwps-volume -t pvc --claim-size=1G --mount-path=/tmp/pvc --overwrite ``` + #### Troubleshooting 1. You are asked for a password when accessing via sftp. This is because your ssh key is not being recognized. - Have you added your key to the secret and restarted the pod? diff --git a/ubuntu-ssh/sshd_config b/sshd_config similarity index 72% rename from ubuntu-ssh/sshd_config rename to sshd_config index 2858b4701f1bbc545e49eaccc10f2a8dd14d37f0..92cab587b627d61f5d7d2de798d0a0c38854060e 100644 --- a/ubuntu-ssh/sshd_config +++ b/sshd_config @@ -3,6 +3,9 @@ Port 2022 # Key for running sshd HostKey /etc/ssh/ssh_host_ed25519_key +#PidFile /home/sftpuser/sshd.pid +PasswordAuthentication no + # Limited access PermitRootLogin no @@ -13,8 +16,5 @@ AllowTcpForwarding no Subsystem sftp internal-sftp ForceCommand internal-sftp -# Regardless of explicit dir or var, os pod cannot chroot to chroot dir -#ChrootDirectory /home/sftpuser - # Logging LogLevel VERBOSE diff --git a/ubuntu-ssh/startup.sh b/startup.sh similarity index 51% rename from ubuntu-ssh/startup.sh rename to startup.sh index d30e705918e9730844cf953b3b25c727313ddbea..46413aa43dd72a54c0288bac0351ade0e3cf9dcb 100644 --- a/ubuntu-ssh/startup.sh +++ b/startup.sh @@ -1,17 +1,30 @@ #!/bin/bash # The following commands belong in this script, rather than in # the dockerfile, in order to run as the sftpuser. +if [ "$(id -u)" -ge 1000 ] ; then + sed -e "/^sftpuser:/c sftpuser:x:$(id -u):$(id -g)::/home/sftpuser:/usr/sbin/nologin" /etc/passwd > /tmp/passwd + cat /tmp/passwd > /etc/passwd + rm /tmp/passwd +fi + +mkdir -p /home/sftpuser/.ssh +#chown sftpuser:root /home/sftpuser /home/sftpuser/.ssh + +# If there is a mounted pvc, symlink to it within the user's home dir. +if [ -d /tmp/pvc ]; +then + ln -s /tmp/pvc /home/sftpuser/mwps +fi # If the user has specified keys either from a docker volume or openshift secret, # place those in the authorized_keys file at container start-up. if [ -f /tmp/keys/*.pub ]; then cat /tmp/keys/*.pub > /home/sftpuser/.ssh/authorized_keys + chown sftpuser /home/sftpuser/.ssh/authorized_keys + chmod 400 /home/sftpuser/.ssh/authorized_keys fi -# Ensure public keys have correct permissions. -chmod 400 /home/sftpuser/.ssh/authorized_keys - # https://www.ssh.com/ssh/sshd#command-line-options # -e option is useful for logging to stderr. # -D don't run as daemon, -d debugging mode diff --git a/ubuntu-ssh/Dockerfile b/ubuntu-ssh/Dockerfile deleted file mode 100644 index 5000c0cb99309428a81589254e99402f6b071ea9..0000000000000000000000000000000000000000 --- a/ubuntu-ssh/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM ubuntu:18.04 - -RUN apt-get -y update \ -&& apt-get -y install openssh-server -# https://help.ubuntu.com/lts/serverguide/openssh-server.html - -RUN mkdir /var/run/sshd - -COPY sshd_config /etc/ssh/sshd_config -RUN chmod g+r /etc/ssh/sshd_config - -# Allow access to server keys for sftpuser -RUN chmod g+r /etc/ssh/ssh_host_ed25519_key - -EXPOSE 2022 - -ADD startup.sh /usr/local/bin -RUN chmod +x /usr/local/bin/startup.sh -CMD ["startup.sh"] diff --git a/umich-sftp/Dockerfile b/umich-sftp/Dockerfile deleted file mode 100644 index 949cb0c669494f4e24ea9babf87ccd5f276f30ac..0000000000000000000000000000000000000000 --- a/umich-sftp/Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -FROM ubuntu-ssh:latest - -# This default is overwritten a variable passed into build process -# $ docker build --build-arg SFTP_UID=1000110000 -t umich-sftp . -ARG SFTP_UID=1000000000 - -# http://manpages.ubuntu.com/manpages/bionic/man8/useradd.8.html -# d: which home dir, g: group, l: don't add to lastlog and faillog, m: create home -# s: which shell, o: non-unique, u: uid, -RUN useradd -g root -m -d /home/sftpuser -s /bin/bash -l -o -u $SFTP_UID sftpuser - -RUN su - sftpuser -c "mkdir -p /home/sftpuser/.ssh" - -# Workaround issue where non-root user can't create pid file. -RUN touch /run/sshd.pid -RUN chown sftpuser:root /run/sshd.pid diff --git a/utility-scripts/update-umich-sftp.sh b/utility-scripts/update-umich-sftp.sh deleted file mode 100755 index 8e9c9a126f53a22bc96625605c6df38ffbdaacd1..0000000000000000000000000000000000000000 --- a/utility-scripts/update-umich-sftp.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash -for project in wps000009 wps000010 wps000012 wps000016 wps000021 wps000023 wps000025 wps000026 wps000027 wps000029 wps000031 wps000032 wps000033 wps000034 -do - echo "project is $project" - oc delete bc,dc,is -l app=umich-sftp -n ${project} - oc delete bc,dc,is -l build=umich-sftp -n ${project} - uid=$(oc get project $project -o custom-columns="uid:.metadata.annotations.openshift\.io/sa\.scc\.uid-range" | tail -n +2) - #echo "uid is $uid" - uid=$(echo $uid | sed -e "s|/10000||g") - echo "uid is $uid" - #oc policy add-role-to-user system:image-puller system-serviceaccount:${project}:builder -n its-curation - #oc policy add-role-to-user system:image-puller system-serviceaccount:${project}:default -n its-curation - oc new-build openshift/ubuntu-ssh~https://gitlab.umich.edu/its-web-platforms/umich-sftp.git --context-dir=umich-sftp --build-arg SFTP_UID=${uid} --strategy=docker -n ${project} - oc create secret generic public-ssh-keys -n ${project} - oc create -f pvc.yaml -n ${project} - cp dc-umich-sftp.yaml dc.yaml - sed -i s/NAMESPACE/${project}/g dc.yaml - oc create -f dc.yaml -n ${project} - rm dc.yaml -done