diff --git a/docker-bake.hcl b/docker-bake.hcl index 725929fbd4..94a737aa2b 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -217,8 +217,6 @@ target "ssh" { "org.opencontainers.image.title": "lagoon-core/ssh - the ssh service for Lagoon" } tags = ["${IMAGE_REPO}/ssh:${TAG}"] - // Note not currently arm64 compatible, libnss is waaaay too old - platforms = ["linux/amd64"] } target "tests" { diff --git a/services/ssh/Dockerfile b/services/ssh/Dockerfile index 51ccc61409..136bc3d127 100644 --- a/services/ssh/Dockerfile +++ b/services/ssh/Dockerfile @@ -1,7 +1,7 @@ ARG UPSTREAM_REPO ARG UPSTREAM_TAG FROM ${UPSTREAM_REPO:-uselagoon}/commons:${UPSTREAM_TAG:-latest} as commons -FROM ubuntu:20.04 +FROM ubuntu:22.04 ARG LAGOON_VERSION ENV LAGOON_VERSION=$LAGOON_VERSION @@ -26,40 +26,32 @@ ENV TMPDIR=/tmp \ ARG DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install -y curl build-essential ssh curl vim jq python3-jwt + ENV LAGOON=ssh \ - OC_VERSION=v3.11.0 \ - OC_HASH=0cbc58b \ - OC_SHA256=4b0f07428ba854174c58d2e38287e5402964c9a9355f6c359d1242efd0990da3 \ - KUBECTL_VERSION=v1.20.0 \ + KUBECTL_VERSION=v1.25.0 \ TZ=UTC -COPY services/ssh/libnss-mysql-1.5.tar.gz /tmp/libnss-mysql-1.5.tar.gz +RUN architecture=$(case $(uname -m) in x86_64 | amd64) echo "amd64" ;; aarch64 | arm64 | armv8) echo "arm64" ;; *) echo "amd64" ;; esac) \ + && curl -Lo kubectl "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/${architecture}/kubectl" \ + && chmod +x kubectl \ + && mv kubectl /usr/bin/kubectl -RUN apt-get update \ - && apt-get install -y curl build-essential libmysqlclient-dev ssh curl vim jq python3-jwt \ - && ln -s /usr/lib/x86_64-linux-gnu/libmysqlclient.so /usr/lib/libmysqlclient.so \ - && mkdir /tmp/libnss-mysql \ - && tar -xzf /tmp/libnss-mysql-1.5.tar.gz -C /tmp/libnss-mysql --strip-components=1 \ - && cd /tmp/libnss-mysql \ - && ./configure \ - && make \ - && make install \ - && apt-get remove --purge -y build-essential \ - && apt-get autoremove -y \ - && rm -rf /var/lib/apt/lists/* /tmp/libnss-mysql-1.5.tar.gz /tmp/libnss-mysql +RUN architecture=$(case $(uname -m) in x86_64 | amd64) echo "amd64" ;; aarch64 | arm64 | armv8) echo "arm64" ;; *) echo "amd64" ;; esac) \ + && curl -sL https://github.com/krallin/tini/releases/download/v0.19.0/tini-${architecture} -o /sbin/tini && chmod a+x /sbin/tini -RUN mkdir -p /openshift-origin-client-tools && \ - curl -Lo /tmp/openshift-origin-client-tools.tar https://github.com/openshift/origin/releases/download/${OC_VERSION}/openshift-origin-client-tools-${OC_VERSION}-${OC_HASH}-linux-64bit.tar.gz && \ - echo "$OC_SHA256 /tmp/openshift-origin-client-tools.tar" | sha256sum -c - && \ - mkdir /tmp/openshift-origin-client-tools && \ - tar -xzf /tmp/openshift-origin-client-tools.tar -C /tmp/openshift-origin-client-tools --strip-components=1 && \ - install /tmp/openshift-origin-client-tools/oc /usr/bin/oc && rm -rf /tmp/openshift-origin-client-tools && rm -rf /tmp/openshift-origin-client-tools.tar +COPY services/ssh/libnss-ato-master.tar.gz /tmp/libnss-ato-master.tar.gz -RUN curl -Lo kubectl "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl" && \ - chmod +x kubectl && \ - mv kubectl /usr/bin/kubectl +RUN mkdir /tmp/libnss-ato \ + && tar -xzf /tmp/libnss-ato-master.tar.gz -C /tmp/libnss-ato --strip-components=1 \ + && cd /tmp/libnss-ato/ \ + && make \ + && make install \ + && rm -rf /tmp/libnss-ato-master.tar.gz /tmp/libnss-ato -RUN curl -L https://github.com/krallin/tini/releases/download/v0.18.0/tini -o /sbin/tini && chmod a+x /sbin/tini +RUN apt-get remove --purge -y build-essential \ + && apt-get autoremove -y \ + && rm -rf /var/lib/apt/lists/* # Reproduce behavior of Alpine: Run Bash as sh RUN rm -f /bin/sh && ln -s /bin/bash /bin/sh @@ -72,9 +64,7 @@ RUN fix-permissions /home/token.sh RUN fix-permissions /home/grant.sh RUN fix-permissions /etc/ssh/ && \ - fix-permissions /run/ && \ - fix-permissions /etc/libnss-mysql.cfg && \ - fix-permissions /etc/libnss-mysql-root.cfg + fix-permissions /run/ RUN mkdir -p /var/run/sshd && chmod 700 /var/run/sshd diff --git a/services/ssh/README.md b/services/ssh/README.md index 5d65bf7400..cd94d5423c 100644 --- a/services/ssh/README.md +++ b/services/ssh/README.md @@ -23,6 +23,7 @@ workflows. * Bash * Python +* https://github.com/donapieppo/libnss-ato ## Related Services diff --git a/services/ssh/create_60_sec_jwt.py b/services/ssh/create_60_sec_jwt.py index d994b104ab..aeb3078ead 100755 --- a/services/ssh/create_60_sec_jwt.py +++ b/services/ssh/create_60_sec_jwt.py @@ -8,4 +8,4 @@ exp = iat + timedelta(minutes=1) payload = {'exp': exp, 'iat': iat, 'role': 'admin', 'aud': os.environ['JWTAUDIENCE'], 'sub': 'ssh'} -print(jwt.encode(payload, os.environ['JWTSECRET'], algorithm='HS256').decode()) +print(jwt.encode(payload, os.environ['JWTSECRET'], algorithm='HS256')) diff --git a/services/ssh/docker-entrypoint.sh b/services/ssh/docker-entrypoint.sh index a9bdbfe490..42e5a4f451 100755 --- a/services/ssh/docker-entrypoint.sh +++ b/services/ssh/docker-entrypoint.sh @@ -6,8 +6,7 @@ ep /home/token.sh ep /home/grant.sh ep /home/token-debug.sh -ep /etc/libnss-mysql.cfg -ep /etc/libnss-mysql-root.cfg +ep /etc/libnss-ato.conf # filling /authorize.env with all our current env variables, this file # will be sourced by /authorize.sh in order to have all environment variables. diff --git a/services/ssh/etc/libnss-ato.conf b/services/ssh/etc/libnss-ato.conf new file mode 100644 index 0000000000..9941ecea18 --- /dev/null +++ b/services/ssh/etc/libnss-ato.conf @@ -0,0 +1 @@ +lagoon-environment-user:x:${USER_ID}:1000:Lagoon User:/home:/bin/bash \ No newline at end of file diff --git a/services/ssh/etc/libnss-mysql-root.cfg b/services/ssh/etc/libnss-mysql-root.cfg deleted file mode 100644 index 7c50814264..0000000000 --- a/services/ssh/etc/libnss-mysql-root.cfg +++ /dev/null @@ -1,2 +0,0 @@ -username ${API_DB_USERNAME:-api} -password ${API_DB_PASSWORD:-api} \ No newline at end of file diff --git a/services/ssh/etc/libnss-mysql.cfg b/services/ssh/etc/libnss-mysql.cfg deleted file mode 100644 index eabb116159..0000000000 --- a/services/ssh/etc/libnss-mysql.cfg +++ /dev/null @@ -1,21 +0,0 @@ -getpwnam SELECT openshift_project_name,'x','${USER_ID}','1000','Lagoon User', '/home','/bin/bash' \ - FROM environment \ - WHERE openshift_project_name='%1$s' \ - LIMIT 1 -getpwuid SELECT openshift_project_name,'x','${USER_ID}','1000','Lagoon User', '/home','/bin/bash' \ - FROM environment \ - WHERE openshift_project_name='%1$u' \ - LIMIT 1 -getspnam SELECT openshift_project_name,'x','1','0','99999','0','0','-1','0' \ - FROM environment \ - WHERE openshift_project_name='%1$s' \ - LIMIT 1 -getpwent SELECT openshift_project_name,'x','${USER_ID}','1000','Lagoon User', '/home','/bin/bash' \ - FROM environment -getspent SELECT openshift_project_name,'x','1','0','99999','0','0','-1','0' \ - FROM environment - -host ${API_DB_HOST:-api-db} -database ${API_DB_DATABASE:-infrastructure} -username ${API_DB_USERNAME:-api} -password ${API_DB_PASSWORD:-api} \ No newline at end of file diff --git a/services/ssh/etc/nsswitch.conf b/services/ssh/etc/nsswitch.conf index 448d809319..b46284e334 100644 --- a/services/ssh/etc/nsswitch.conf +++ b/services/ssh/etc/nsswitch.conf @@ -4,7 +4,7 @@ # If you have the `glibc-doc-reference' and `info' packages installed, try: # `info libc "Name Service Switch"' for information about this file. -passwd: compat mysql +passwd: compat ato group: compat shadow: compat gshadow: files diff --git a/services/ssh/home/rsh.sh b/services/ssh/home/rsh.sh index 53a866c28d..fb4887ca25 100755 --- a/services/ssh/home/rsh.sh +++ b/services/ssh/home/rsh.sh @@ -122,14 +122,10 @@ if [[ $CLUSTER_TOKEN == "null" ]]; then CLUSTER_TOKEN=$(KUBECONFIG="/tmp/kube" oc --insecure-skip-tls-verify whoami -t) fi -OC="/usr/bin/oc --insecure-skip-tls-verify -n ${PROJECT} --token=${CLUSTER_TOKEN} --server=${CLUSTER_CONSOLE} " KUBECTL="/usr/bin/kubectl --insecure-skip-tls-verify -n ${PROJECT} --token=${CLUSTER_TOKEN} --server=${CLUSTER_CONSOLE} " -IS_KUBERNETES=false - # If there is a deployment for the given service searching for lagoon.sh labels if [[ $($KUBECTL get deployment -l "lagoon.sh/service=${SERVICE}" 2> /dev/null) ]]; then - IS_KUBERNETES=true # get any other deployments that may have been idled and unidle them if required # this only needs to be done for kubernetes # we do this first to give the services a bit of time to unidle before starting the one that was requested @@ -147,7 +143,7 @@ if [[ $($KUBECTL get deployment -l "lagoon.sh/service=${SERVICE}" 2> /dev/null) REPLICAS=1 fi echo "${UUID}: Attempting to scale deployment='${DEP}' for project='${PROJECT}' cluster='${CLUSTER_NAME}' service='${SERVICE}'" >> /proc/1/fd/1 - $OC scale --replicas=${REPLICAS} ${DEP} >/dev/null 2>&1 + $KUBECTL scale --replicas=${REPLICAS} ${DEP} >/dev/null 2>&1 fi done # then if we have to wait for them to start, do that here @@ -182,7 +178,7 @@ if [[ $($KUBECTL get deployment -l "lagoon.sh/service=${SERVICE}" 2> /dev/null) # .status.replicas doesn't exist on a scaled to 0 deployment in k8s so assume it is 0 if nothing is returned if [[ $($KUBECTL get ${DEPLOYMENT} -o json | jq -r '.status.replicas // 0') == "0" ]]; then echo "${UUID}: Attempting to scale deployment='${DEPLOYMENT}' for project='${PROJECT}' cluster='${CLUSTER_NAME}' service='${SERVICE}'" >> /proc/1/fd/1 - $OC scale --replicas=1 ${DEPLOYMENT} >/dev/null 2>&1 + $KUBECTL scale --replicas=1 ${DEPLOYMENT} >/dev/null 2>&1 fi # Wait until the scaling is done SSH_CHECK_COUNTER=0 @@ -199,32 +195,10 @@ if [[ $($KUBECTL get deployment -l "lagoon.sh/service=${SERVICE}" 2> /dev/null) echo "${UUID}: Deployment is running deployment='${DEPLOYMENT}' for project='${PROJECT}' cluster='${CLUSTER_NAME}' service='${SERVICE}'" >> /proc/1/fd/1 fi -# If there is a deploymentconfig for the given service, then it isn't kubernetes, it is openshift. -if [[ "${IS_KUBERNETES}" == "false" ]]; then - if [[ $($OC get deploymentconfigs -l service=${SERVICE} 2> /dev/null) ]]; then - DEPLOYMENTCONFIG=$($OC get deploymentconfigs -l service=${SERVICE} -o name) - # If the deploymentconfig is scaled to 0, scale to 1 - if [[ $($OC get ${DEPLOYMENTCONFIG} -o go-template --template='{{.status.replicas}}') == "0" ]]; then - echo "${UUID}: Attempting to scale deploymentconfig='${DEPLOYMENTCONFIG}' for project='${PROJECT}' cluster='${CLUSTER_NAME}' service='${SERVICE}'" >> /proc/1/fd/1 - $OC scale --replicas=1 ${DEPLOYMENTCONFIG} >/dev/null 2>&1 - - # Wait until the scaling is done - while [[ ! $($OC get ${DEPLOYMENTCONFIG} -o go-template --template='{{.status.readyReplicas}}') == "1" ]] - do - sleep 1 - done - fi - echo "${UUID}: Deployment is running deploymentconfig='${DEPLOYMENTCONFIG}' for project='${PROJECT}' cluster='${CLUSTER_NAME}' service='${SERVICE}'" >> /proc/1/fd/1 - fi -fi # Check for newer Helm chart "lagoon.sh" labels echo "${UUID}: Getting pod name for exec for project='${PROJECT}' cluster='${CLUSTER_NAME}' service='${SERVICE}'" >> /proc/1/fd/1 -if [[ "${IS_KUBERNETES}" == "true" ]]; then - POD=$($KUBECTL get pods -l "lagoon.sh/service=${SERVICE}" -o json | jq -r '[.items[] | select(.metadata.deletionTimestamp == null) | select(.status.phase == "Running")] | first | .metadata.name // empty') -else - POD=$($OC get pods -l service=${SERVICE} -o json | jq -r '[.items[] | select(.metadata.deletionTimestamp == null) | select(.status.phase == "Running")] | first | .metadata.name // empty') -fi +POD=$($KUBECTL get pods -l "lagoon.sh/service=${SERVICE}" -o json | jq -r '[.items[] | select(.metadata.deletionTimestamp == null) | select(.status.phase == "Running")] | first | .metadata.name // empty') if [[ ! $POD ]]; then echo "${UUID}: No running pod found for service ${SERVICE}" @@ -233,11 +207,7 @@ fi # If no container defined, load the name of the first container if [[ -z ${CONTAINER} ]]; then - if [[ "${IS_KUBERNETES}" == "true" ]]; then - CONTAINER=$($KUBECTL get pod ${POD} -o json | jq --raw-output '.spec.containers[0].name') - else - CONTAINER=$($OC get pod ${POD} -o json | jq --raw-output '.spec.containers[0].name') - fi + CONTAINER=$($KUBECTL get pod ${POD} -o json | jq --raw-output '.spec.containers[0].name') fi if [ -t 1 ]; then @@ -248,17 +218,8 @@ fi echo "${UUID}: Exec to pod='${POD}' for project='${PROJECT}' cluster='${CLUSTER_NAME}' service='${SERVICE}'" >> /proc/1/fd/1 -if [[ "${IS_KUBERNETES}" == "true" ]]; then - if [[ -z "$*" ]]; then - exec $KUBECTL exec ${POD} -c ${CONTAINER} -i ${TTY_PARAMETER} -- sh - else - exec $KUBECTL exec ${POD} -c ${CONTAINER} -i ${TTY_PARAMETER} -- sh -c "$*" - fi +if [[ -z "$*" ]]; then + exec $KUBECTL exec ${POD} -c ${CONTAINER} -i ${TTY_PARAMETER} -- sh else - if [[ -z "$*" ]]; then - exec $OC exec ${POD} -c ${CONTAINER} -i ${TTY_PARAMETER} -- sh - else - exec $OC exec ${POD} -c ${CONTAINER} -i ${TTY_PARAMETER} -- sh -c "$*" - fi - -fi \ No newline at end of file + exec $KUBECTL exec ${POD} -c ${CONTAINER} -i ${TTY_PARAMETER} -- sh -c "$*" +fi diff --git a/services/ssh/libnss-ato-master.tar.gz b/services/ssh/libnss-ato-master.tar.gz new file mode 100644 index 0000000000..2dcbd8f102 Binary files /dev/null and b/services/ssh/libnss-ato-master.tar.gz differ diff --git a/services/ssh/libnss-mysql-1.5.tar.gz b/services/ssh/libnss-mysql-1.5.tar.gz deleted file mode 100644 index 6bd326ff79..0000000000 Binary files a/services/ssh/libnss-mysql-1.5.tar.gz and /dev/null differ