Using SSH inside docker with correct file permissions? - linux

There are a few posts on how to use Docker + SSH. There are also posts on how to edit files mounted in a docker container, such that editing them won't cause the permissions to become root.
I'm trying to combine the 2 things, so I can SSH into a docker container and edit files without messing up their permissions.
For, using the correct file permissions, I use:
- /etc/passwd:/etc/passwd:ro
- /etc/group:/etc/group:ro
in my docker-compose.yml and
docker compose -f commands/dev/docker-compose.yml run \
--service-ports \
--user $(id -u) \
develop \
bash
so that when I start the docker container, my user is the same user as my local computer.
However, this breaks up my SSH setup inside the Docker container:
useradd -rm -d /home/ubuntu -s /bin/bash -g root -G sudo ubuntu
echo 'ubuntu:ubuntu' | chpasswd
# passwd -d ubuntu
apt install -y --no-install-recommends openssh-server vim-tiny sudo
# See: https://stackoverflow.com/questions/22886470/start-sshd-automatically-with-docker-container
sed 's#session\s*required\s*pam_loginuid.so#session optional pam_loginuid.so#g' -i /etc/pam.d/sshd
mkdir /var/run/sshd
bash -c 'install -m755 <(printf "#!/bin/sh\nexit 0") /usr/sbin/policy-rc.d'
ex +'%s/^#\zeListenAddress/\1/g' -scwq /etc/ssh/sshd_config
ex +'%s/^#\zeHostKey .*ssh_host_.*_key/\1/g' -scwq /etc/ssh/sshd_config
RUNLEVEL=1 dpkg-reconfigure openssh-server
ssh-keygen -A -v
update-rc.d ssh defaults
# Configure sudo
ex +"%s/^%sudo.*$/%sudo ALL=(ALL:ALL) NOPASSWD:ALL/g" -scwq! /etc/sudoers
Here I'm creating a user called ubuntu with password ubuntu for SSH-ing. This lets me SSH in ubuntu#localhost using the password ubuntu.
The issue is that by mounting the /etc/passwd file into my container, I erase the ubuntu user inside the container. This means when I try to ssh in with ssh -p 9002 ubuntu#localhost, the authentication fails (9002 is what I bind port 22 in the container to on the host).
Does anyone have a solution?

Here's a first pass answer.
I can use:
useradd -rm -d /home/yourusername -s /bin/bash -g root -G sudo yourusername
instead of
useradd -rm -d /home/ubuntu -s /bin/bash -g root -G sudo ubuntu
echo 'ubuntu:ubuntu' | chpasswd
then, I:
Run the ssh server in the container with:
su root
/usr/sbin/sshd -D -o ListenAddress=0.0.0.0 -o PermitRootLogin=yes
I can ssh into the container as root (using the root password "root", which I set with RUN echo 'root:root' | chpasswd in the Dockerfile).
Then, I can do su yourusername, to switch my user.
While this works, it is pretty annoying since I need to bake the user name into the Docker container.

Related

Unable to run command chsh -s /bin/bash ${USERNAME}

I have a docker file where I have customized image myimage derived from some-debian-image (which derived from debian upstream.)
FROM some-debian-image myimge
USERNAME root:root
...........................
RUN chsh -s /bin/bash ${USERNAME}
docker build fails saying :
Password: chsh: PAM: Authentication failure
However, it does not fail with upstream
FROM bebain:bullseye myimage
USERNAME root:root
...........................
RUN chsh -s /bin/bash ${USERNAME}
Developers who have build the some-debian-image have done something add on with /etc/passwd , and it is having content
root:x:0:0:root:/root:/usr/sbin/nologin
May I please know how to successfully run this command :
RUN chsh -s /bin/bash ${USERNAME}
I am comparing docker images setup where it is working and where it is not working , and I found that:
The setup where the above command RUN chsh -s /bin/bash ${USERNAME} is working sudo su can be expected without any password
$ sudo su
#
In contrast in setup where I am facing issue ask for password when run the command sudo su
May I pleas know what changes I should do so that sudo su shall not ask for password?

Add User RHEL ubi8/openjdk-8 Docker Image fails

While updating some Docker Baseimages (which previously were based on this image openjdk/openjdk-8-rhel8) to this image: ubi8/openjdk-8 I (suspect that I) was unable to add a user with the useradd cammand.
It appears inside the /etc/shadow file, but when I try to login into the container I get that messenge:
NWRAP_ERROR(4677) - nwrap_files_cache_reload: Unable to open '/home/jboss/passwd' readonly -1:Permission denied
NWRAP_ERROR(4677) - nwrap_files_getpwuid: Error loading passwd file
the Dockerfile, which worked well with the previous Image is:
FROM xxxx.azurecr.io/ubi8/openjdk-8:1.3-9
ARG uid=60000
ARG gid=60000
ARG user=testuser
ARG group=testuser
ARG shell=/bin/bash
ARG home=/home/$user
ARG port=8080
USER root
RUN mkdir -p $home \
&& chown ${uid}:${gid} $home \
&& groupadd -g ${gid} ${group} \
&& useradd --uid ${uid} --gid ${gid} --shell ${shell} --home ${home} $user
I don't know what could cause that problem, and searching for NWRAP_ERROR(4677) gave me no results. Dis someone had similar problems and could tell what went wrong and if there is a different way to add the user with the Dockerfile?
I had a similar issue with this image when I tried to :
[root#3ee1b7206f33 ~]# useradd -m -u 15001 myaccount_azpcontainer
[root#3ee1b7206f33 ~]# groupadd azure_pipelines_sudo
[root#3ee1b7206f33 ~]# usermod -a -G azure_pipelines_sudo myaccount_azpcontainer
usermod: user 'myaccount_azpcontainer' does not exist
if I look in /ect/passwd, the user is present :
[root#3ee1b7206f33 ~]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin
jboss:x:185:0:JBoss user:/home/jboss:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
systemd-coredump:x:999:997:systemd Core Dumper:/:/sbin/nologin
systemd-resolve:x:193:193:systemd Resolver:/:/sbin/nologin
unbound:x:998:996:Unbound DNS resolver:/etc/unbound:/sbin/nologin
myaccount_azpcontainer:x:15001:15001::/home/myaccount_azpcontainer:/bin/bash
but usermod doesn't work and getent passwd doesn't work
[root#3ee1b7206f33 ~]# getent passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:65534:65534:Kernel Overflow User:/:/sbin/nologin
jboss:x:185:0:JBoss user:/home/jboss:/sbin/nologin
I have no problem with others redhat images, only with openjdk
By looking the image DockerFile I found :
USER root
RUN [ "sh", "-x", "/tmp/scripts/jboss.container.user/configure.sh" ]
and the content of file :
https://github.com/jboss-openshift/cct_module/blob/master/jboss/container/user/configure.sh
groupadd -r jboss -g 185 && useradd -u 185 -r -g root -G jboss -m -d /home/jboss -s /sbin/nologin -c "JBoss user" jboss
cp /etc/passwd /home/jboss/passwd
chmod ug+rwX /home/jboss /home/jboss/passwd
I tested it in mydockerfile and add cp /etc/passwd /home/jboss/passwd after useradd and It works !!
My colleague explained me the problem is the usage of nss_wrapper :https://cwrap.org/nss_wrapper.html
Maybe, there is another way to manage the useradd, but not yet tested
Thanks,

Script or tool for adding users to server with ssh keypair login

Is there a tool or a common script for adding users to a linux server that also configures the ssh keys?
For example, I found I can automate creation of users with useradd or adduser, and it is even possible to setup an account with password login with e.g. adduser --password my_password. However, that still leaves me having to add the .ssh folders and files and set the correct permissions, which in my case leaves plenty of room for typos.
What I am looking for is something like
adduser --ssh user_public_key
where user_public_key is key provided to me by the new user.
I imagine there might be an existing tool for this, but my duckducking didn't turn up anything useful.
Try this (for centos, plus enables docker)
set -euo pipefail
DEV_GROUP="somegroup"
sudo groupadd --force "${DEV_GROUP}"
function adduser() {
local var_user="$1"
shift
local var_ssh_pub_key="$*"
id --user "${var_user}" &>/dev/null || sudo useradd --gid "${DEV_GROUP}" --groups wheel,docker "${var_user}"
echo "${var_user} ALL=(ALL) NOPASSWD:ALL" | sudo tee "/etc/sudoers.d/${var_user}"
sudo --user "${var_user}" mkdir -p "/home/${var_user}/.ssh"
sudo --user "${var_user}" touch "/home/${var_user}/.ssh/authorized_keys"
echo "${var_ssh_pub_key}" | sudo --user "${var_user}" tee "/home/${var_user}/.ssh/authorized_keys"
}
adduser someuser ssh-rsa AAAAB3NzaC1.... user#host
You can do this in a script as root:
$ mkdir ~username/.ssh
$ cat user_public_key >> ~username/.ssh/authorized_keys
$ chown -R username ~username/.ssh

correct method to create user in alpine docker container so that sudo works correctly

When attempting to execute sudo in a docker container using alpine 3.8 I get the following output.
I am logged into the container using docker exec -i -t MYIMAGE /bin/bash
bash-4.4$ whoami
payara
bash-4.4$ sudo -s
bash-4.4$ whoami
payara
bash-4.4$ su root
su: incorrect password
bash-4.4$
My docker file contains the following user related commands to try and setup a user specifically for payara. I want sudo to work correctly though, if possible.
DockerFile
FROM "alpine:latest"
ENV LANG C.UTF-8
ENV http_proxy 'http://u:p#160.48.234.129:80'
ENV https_proxy 'http://u:p#160.48.234.129:80'
RUN apk add --no-cache bash gawk sed grep bc coreutils git openssh-client libarchive libarchive-tools busybox-suid sudo
RUN addgroup -S payara && adduser -S -G payara payara
RUN echo "payara ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
# CHANGE TO PAYARA USER
USER payara
... rest of setup.
From man sudo:
-s, --shell
Run the shell specified by the SHELL environment variable if it is set or the shell specified by the invoking user's password database entry.
You have neither SHELL variable set, nor correct (interactive) default shell set in /etc/passwd for user payara. This is because you are creating a system user (-S) - this user has a default shell /bin/false (which just exits with exit code 1 - you may check with echo $? after unsuccessfull sudo -s).
You may overcome this in different ways:
a) specify the SHELL variable:
bash-4.4$ SHELL=/bin/bash sudo -s
bed662af470d:~#
b) use su, which will use the default root's shell:
bash-4.4$ sudo su -
bed662af470d:~#
c) just run the required privileged commands with sudo directly, without spawning an interactive shell.

Set docker image username at container creation time?

I have an OpenSuse 42.3 docker image that I've configured to run a code. The image has a single user(other than root) called "myuser" that I create during the initial Image generation via the Dockerfile. I have three script files that generate a container from the image based on what operating system a user is on.
Question: Can the username "myuser" in the container be set to the username of the user that executes the container generation script?
My goal is to let a user pop into the container interactively and be able to run the code from within the container. The code is just a single binary that executes and has some IO, so I want the user's directory to be accessible from within the container so that they can navigate to a folder on their machine and run the code to generate output in their filesystem.
Below is what I have constructed so far. I tried setting the USER environment variable during the linux script's call to docker run, but that didn't change the user from "myuser" to say "bob" (the username on the host machine that started the container). The mounting of the directories seems to work fine. I'm not sure if it is even possible to achieve my goal.
Linux Container script:
username="$USER"
userID="$(id -u)"
groupID="$(id -g)"
home="${1:-$HOME}"
imageName="myImage:ImageTag"
containerName="version1Image"
docker run -it -d --name ${containerName} -u $userID:$groupID \
-e USER=${username} --workdir="/home/myuser" \
--volume="${home}:/home/myuser" ${imageName} /bin/bash \
Mac Container script:
username="$USER"
userID="$(id -u)"
groupID="$(id -g)"
home="${1:-$HOME}"
imageName="myImage:ImageTag"
containerName="version1Image"
docker run -it -d --name ${containerName} \
--workdir="/home/myuser" \
--v="${home}:/home/myuser" ${imageName} /bin/bash \
Windows Container script:
ECHO OFF
SET imageName="myImage:ImageTag"
SET containerName="version1Image"
docker run -it -d --name %containerName% --workdir="/home/myuser" -v="%USERPROFILE%:/home/myuser" %imageName% /bin/bash
echo "Container %containerName% was created."
echo "Run the ./startWindowsLociStream script to launch container"
The below code has been checked into https://github.com/bmitch3020/run-as-user.
I would handle this in an entrypoint.sh that checks the ownership of /home/myuser and updates the uid/gid of the user inside your container. It can look something like:
#!/bin/sh
set -x
# get uid/gid
USER_UID=`ls -nd /home/myuser | cut -f3 -d' '`
USER_GID=`ls -nd /home/myuser | cut -f4 -d' '`
# get the current uid/gid of myuser
CUR_UID=`getent passwd myuser | cut -f3 -d: || true`
CUR_GID=`getent group myuser | cut -f3 -d: || true`
# if they don't match, adjust
if [ ! -z "$USER_GID" -a "$USER_GID" != "$CUR_GID" ]; then
groupmod -g ${USER_GID} myuser
fi
if [ ! -z "$USER_UID" -a "$USER_UID" != "$CUR_UID" ]; then
usermod -u ${USER_UID} myuser
# fix other permissions
find / -uid ${CUR_UID} -mount -exec chown ${USER_UID}.${USER_GID} {} \;
fi
# drop access to myuser and run cmd
exec gosu myuser "$#"
And here's some lines from a relevant Dockerfile:
FROM debian:9
ARG GOSU_VERSION=1.10
# run as root, let the entrypoint drop back to myuser
USER root
# install prereq debian packages
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
apt-transport-https \
ca-certificates \
curl \
vim \
wget \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Install gosu
RUN dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" \
&& wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch" \
&& chmod 755 /usr/local/bin/gosu \
&& gosu nobody true
RUN useradd -d /home/myuser -m myuser
WORKDIR /home/myuser
# entrypoint is used to update uid/gid and then run the users command
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD /bin/sh
Then to run it, you just need to mount /home/myuser as a volume and it will adjust permissions in the entrypoint. e.g.:
$ docker build -t run-as-user .
$ docker run -it --rm -v $(pwd):/home/myuser run-as-user /bin/bash
Inside that container you can run id and ls -l to see that you have access to /home/myuser files.
Usernames are not important. What is important are the uid and gid values.
User myuser inside your container will have a uid of 1000 (first non-root user id). Thus when you start your container and look at the container process from the host machine, you will see that the container is owned by whatever user having a uid of 1000 on the host machine.
You can override this by specifying the user once you run your container using:
docker run --user 1001 ...
Therefore if you want the user inside the container, to be able to access files on the host machine owned by a user having a uid of 1005 say, just run the container using --user 1005.
To better understand how users map between the container and host take a look at this wonderful article. https://medium.com/#mccode/understanding-how-uid-and-gid-work-in-docker-containers-c37a01d01cf
First of all (https://docs.docker.com/engine/reference/builder/#arg):
Warning: It is not recommended to use build-time variables for passing
secrets like github keys, user credentials etc. Build-time variable
values are visible to any user of the image with the docker history
command.
But if you still need to do this, read https://docs.docker.com/engine/reference/builder/#arg:
A Dockerfile may include one or more ARG instructions. For example,
the following is a valid Dockerfile:
FROM busybox
ARG user1
ARG buildno
...
and https://docs.docker.com/engine/reference/builder/#user:
The USER instruction sets the user name (or UID) and optionally the
user group (or GID) to use when running the image and for any RUN, CMD
and ENTRYPOINT instructions that follow it in the Dockerfile.
USER <user>[:<group>] or
USER <UID>[:<GID>]

Resources