initial commit

This commit is contained in:
amorozov 2025-03-03 00:42:00 +03:00
commit 3849aab9b5
15 changed files with 802 additions and 0 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Force checkout as Unix endline style
text eol=lf

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
.DS_Store
bats-core/
bats/
target/
/.vscode/
build-windows.yaml

265
AGENT.README.md Normal file
View File

@ -0,0 +1,265 @@
# Docker image for Jenkins agents connected over SSH
[![Join the chat at https://gitter.im/jenkinsci/docker](https://badges.gitter.im/jenkinsci/docker.svg)](https://gitter.im/jenkinsci/docker?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![GitHub stars](https://img.shields.io/github/stars/jenkinsci/docker-ssh-agent?label=GitHub%20stars)](https://github.com/jenkinsci/docker-ssh-agent)
[![Docker Pulls](https://img.shields.io/docker/pulls/jenkins/ssh-agent.svg)](https://hub.docker.com/r/jenkins/ssh-agent/)
[![GitHub release](https://img.shields.io/github/release/jenkinsci/docker-ssh-agent.svg?label=changelog)](https://github.com/jenkinsci/docker-ssh-agent/releases)
A [Jenkins](https://jenkins.io) agent image which allows using SSH to establish the connection.
It can be used together with the [SSH Build Agents plugin](https://plugins.jenkins.io/ssh-slaves) or other similar plugins.
See [Jenkins Distributed builds](https://wiki.jenkins-ci.org/display/JENKINS/Distributed+builds) for more info.
## Running
### Running with the SSH Build Agents plugin
To run a Docker container
```bash
docker run -d --rm --name=agent --publish 2200:22 -e "JENKINS_AGENT_SSH_PUBKEY=<public_key>" jenkins/ssh-agent
```
- `-d`: To start a container in detached mode, use the `-d` option. Containers started in detached mode exit when the root process used to run the container exits, unless you also specify the --rm option.
- `--rm`: If you use -d with --rm, the container is removed when it exits or when the daemon exits, whichever happens first.
- `--name`: Assigns a name to the container. If you do not specify a name, Docker generates a random name.
- `--publish 2200:22`: Publishes the host port 2200 to the agent container port 22 (SSH) to allow connection from the host with `ssh jenkins@localhost -p 2200`
Please note none of these options are mandatory, they are just examples.
You will then be able to connect this agent using the [SSH Build Agents plugin](https://plugins.jenkins.io/ssh-slaves) as "jenkins" with the matching private key.
When using the Linux image, you have to set the value of the `Remote root directory` to `/home/jenkins/agent` in the agent configuration UI.
![Remote root directory with a Linux agent](docs/ssh-plugin-remote-root-directory-linux.png "Remote root directory with a Linux agent")
When using the Windows image, you have to set the value of the `Remote root directory` to `C:/Users/jenkins/Work` in the agent configuration UI.
![Remote root directory with a Windows agent](docs/ssh-plugin-remote-root-directory-windows.png "Remote root directory with a Windows agent")
If you intend to use another directory than `/home/jenkins/agent` under Linux or `C:/Users/jenkins/Work` under Windows, don't forget to add it as a data volume.
```bash
docker run -v docker-volume-for-jenkins-ssh-agent:/home/jenkins/agent:rw jenkins/ssh-agent "<public key>"
```
### How to use this image with Docker Plugin
To use this image with [Docker Plugin](https://plugins.jenkins.io/docker-plugin), you need to pass the public SSH key using environment variable `JENKINS_AGENT_SSH_PUBKEY` and not as a startup argument.
In _Environment_ field of the Docker Template (advanced section), just add:
JENKINS_AGENT_SSH_PUBKEY=<YOUR PUBLIC SSH KEY HERE>
Don't put quotes around the public key.
Please note that you have to set the value of the `Remote File System Root` to `/home/jenkins/agent` in the Docker Agent Template configuration UI.
![Remote File System Root](docs/docker-plugin-remote-filesystem-root.png "Remote File System Root directory")
If you intend to use another directory than `/home/jenkins/agent`, don't forget to add it as a data volume.
![Docker Volumes mounts](docs/docker-plugin-volumes.png "Docker Volumes mounts")
You should be all set.
## Extending the image
Should you need to extend the image, you could use something along those lines:
```Dockerfile
FROM jenkins/ssh-agent:debian-jdk17 as ssh-agent
# [...]
COPY --chown=jenkins mykey "${JENKINS_AGENT_HOME}"/.ssh/mykey
# [...]
```
## Configurations
The image has several supported configurations, which can be accessed via the following tags:
`${IMAGE_VERSION}` can be found on the [releases](https://github.com/jenkinsci/docker-ssh-agent/releases) page.
* `latest`, `latest-jdk11`, `jdk11`, `latest-bookworm-jdk11`, `bookworm-jdk11`, `latest-debian-jdk11`, `debian-jdk11`, `${IMAGE_VERSION}`, `${IMAGE_VERSION}-jdk11`, ([Dockerfile](debian/Dockerfile))
* `latest-jdk17`, `jdk17`, `latest-bookworm-jdk17`, `bookworm-jdk17`, `latest-debian-jdk17`, `debian-jdk17`, `${IMAGE_VERSION}-jdk17`, ([Dockerfile](debian/Dockerfile))
* `nanoserver-1809`, `nanoserver-ltsc2019`, `nanoserver-1809-jdk11`, `nanoserver-ltsc2019-jdk11`, `${IMAGE_VERSION}-nanoserver-1809`, `${IMAGE_VERSION}-nanoserver-ltsc2019`, `${IMAGE_VERSION}-nanoserver-1809-jdk11`, `${IMAGE_VERSION}-nanoserver-ltsc2019-jdk11` ([Dockerfile](windows/nanoserver-ltsc2019/Dockerfile))
* `windowsservercore-1809`, `windowsservercore-ltsc2019`, `windowsservercore-1809-jdk11`, `windowsservercore-ltsc2019-jdk11`, `${IMAGE_VERSION}-windowsservercore-1809`, `${IMAGE_VERSION}-windowsservercore-ltsc2019`, `${IMAGE_VERSION}-windowsservercore-1809-jdk11`, `${IMAGE_VERSION}-windowsservercore-ltsc2019-jdk11` ([Dockerfile](windows/windowsservercore-ltsc2019/Dockerfile))
## Building instructions
### Pre-requisites
Should you want to build this image on your machine (before submitting a pull request for example), please have a look at the pre-requisites:
* A GNU/Linux machine with [Docker](https://docs.docker.com/engine/install/), a macOS machine with [Docker Desktop](https://docs.docker.com/desktop/install/mac-install/), or a Windows machine with [Docker for Windows](https://docs.docker.com/docker-for-windows/) installed
* Docker BuildX plugin [installed](https://github.com/docker/buildx#installing) on older versions of Docker (from `19.03`). Docker Buildx is included in recent versions of Docker Desktop for Windows, macOS, and Linux. Docker Linux packages also include Docker Buildx when installed using the DEB or RPM packages.
* [GNU Make](https://www.gnu.org/software/make/) [installed](https://command-not-found.com/make)
* jq [installed](https://command-not-found.com/jq)
* yq [installed](https://github.com/mikefarah/yq) (for Windows)
* [GNU Bash](https://www.gnu.org/software/bash/) [installed](https://command-not-found.com/bash)
* git [installed](https://command-not-found.com/git)
* curl [installed](https://command-not-found.com/curl)
### Building
#### Target images
If you want to see the target images that will be built, you can issue the following command:
```bash
make list
alpine_jdk11
alpine_jdk17
debian_jdk11
debian_jdk17
```
#### Building a specific image
If you want to build a specific image, you can issue the following command:
```bash
make build-<OS>_<JDK_VERSION>
```
That would give for JDK 17 on Alpine Linux:
```bash
make build-alpine_jdk17
```
#### Building images supported by your current architecture
Then, you can build the images supported by your current architecture by running:
```bash
make build
```
#### Testing all images
If you want to test these images, you can run:
```bash
make test
```
#### Testing a specific image
If you want to test a specific image, you can run:
```bash
make test-<OS>_<JDK_VERSION>
```
That would give for JDK 17 on Alpine Linux:
```bash
make test-alpine_jdk17
```
#### Building all images
You can build all images (even those unsupported by your current architecture) by running:
```bash
make every-build
```
#### Other `make` targets
`show` gives us a detailed view of the images that will be built, with the tags, platforms, and Dockerfiles.
```bash
make show
{
"group": {
"default": {
"targets": [
"alpine_jdk17",
"alpine_jdk11",
"debian_jdk11",
"debian_jdk17",
]
}
},
"target": {
"alpine_jdk11": {
"context": ".",
"dockerfile": "alpine/Dockerfile",
"tags": [
"docker.io/jenkins/ssh-agent:alpine-jdk11",
"docker.io/jenkins/ssh-agent:latest-alpine-jdk11"
],
"platforms": [
"linux/amd64"
],
"output": [
"type=docker"
]
},
[...]
```
`bats` is a dependency target. It will update the [`bats` submodule](https://github.com/bats-core/bats-core) and run the tests.
```bash
make bats
make: 'bats' is up to date.
```
`publish` allows the publication of all images targeted by 'linux' to a registry.
`docker-init` is dedicated to Jenkins infrastructure for initializing docker and isn't required in other contexts.
### Building and testing on Windows
#### Building all images
Run `.\build.ps1` to launch the build of the images corresponding to the "windows" target of docker-bake.hcl.
Internally, the first time you'll run this script and if there is no build-windows.yaml file in your repository, it will use a combination of `docker buildx bake` and `yq` to generate a build-windows.yaml docker compose file containing all Windows image definitions from docker-bake.hcl. Then it will run `docker compose` on this file to build these images.
You can modify this docker compose file as you want, then rerun `.\build.ps1`.
It won't regenerate the docker compose file from docker-bake.hcl unless you add the `-OverwriteDockerComposeFile` build.ps1 parameter: `.\build.ps1 -OverwriteDockerComposeFile`.
Note: you can generate this docker compose file from docker-bake.hcl yourself with the following command (require `docker buildx` and `yq`):
```console
# - Use docker buildx bake to output image definitions from the "windows" bake target
# - Convert with yq to the format expected by docker compose
# - Store the result in the docker compose file
$ docker buildx bake --progress=plain --file=docker-bake.hcl windows --print `
| yq --prettyPrint '.target[] | del(.output) | {(. | key): {\"image\": .tags[0], \"build\": .}}' | yq '{\"services\": .}' `
| Out-File -FilePath build-windows.yaml
```
Note that you don't need build.ps1 to build (or to publish) your images from this docker compose file, you can use `docker compose --file=build-windows.yaml build`.
#### Testing all images
Run `.\build.ps1 test` if you also want to run the tests harness suit.
Run `.\build.ps1 test -TestsDebug 'debug'` to also get commands & stderr of tests, displayed on top of them.
You can set it to `'verbose'` to also get stdout of every test command.
Note that instead of passing `-TestsDebug` parameter to build.ps1, you can set the $env:TESTS_DEBUG environment variable to the desired value.
Also note that contrary to the Linux part, you have to build the images before testing them.
#### Dry run
Add the `-DryRun` parameter to print out any build, publish or tests commands instead of executing them: `.\build.ps1 test -DryRun`
#### Building and testing a specific image
You can build (and test) only one image type by setting `-ImageType` to a combination of Windows flavors ("nanoserver" & "windowsservercore") and Windows versions ("1809", "ltsc2019", "ltsc2022").
Ex: `.\build.ps1 -ImageType 'nanoserver-ltsc2019'`
Warning: trying to build `windowsservercore-1809` will fail as there is no corresponding image from Microsoft.
## Changelog
See [GitHub Releases](https://github.com/jenkinsci/docker-ssh-agent/releases/latest).
Note that the changelogs and release tags were introduced in Dec 2019, and there are no entries for previous releases.
Please consult with the commit history if needed.

136
Dockerfile Normal file
View File

@ -0,0 +1,136 @@
# MIT License
#
# Copyright (c) 2019-2022 Fabio Kruger and other contributors
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
ARG JAVA_VERSION=17.0.14_7
FROM docker:dind AS jre-build
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
# This Build ARG is populated by Docker
# Ref. https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope
ARG TARGETPLATFORM
COPY jdk-download-url.sh /usr/bin/local/jdk-download-url.sh
COPY jdk-download.sh /usr/bin/local/jdk-download.sh
RUN chmod +x /usr/bin/local/jdk-download.sh && \
chmod +x /usr/bin/local/jdk-download-url.sh && \
cat /usr/bin/local/jdk-download.sh && \
cat /usr/bin/local/jdk-download-url.sh && \
echo "ASH HERE: $(which ash)"
ARG JAVA_VERSION=17.0.14_7
# hadolint ignore=DL3018
RUN apk add --no-cache \
ca-certificates \
jq \
curl
RUN /usr/bin/local/jdk-download.sh alpine
ENV PATH="/opt/jdk-${JAVA_VERSION}/bin:${PATH}"
RUN case "$(jlink --version 2>&1)" in \
"17."*) set -- "--compress=2" ;; \
# the compression argument is different for JDK21
"21."*) set -- "--compress=zip-6" ;; \
*) echo "ERROR: unmanaged jlink version pattern" && exit 1 ;; \
esac; \
jlink \
--strip-java-debug-attributes \
"$1" \
--add-modules ALL-MODULE-PATH \
--no-man-pages \
--no-header-files \
--output /javaruntime
FROM docker:dind AS build
ARG user=jenkins
ARG group=jenkins
ARG uid=1000
ARG gid=1000
ARG JENKINS_AGENT_HOME=/home/${user}
ENV JENKINS_AGENT_HOME=${JENKINS_AGENT_HOME}
ARG AGENT_WORKDIR="${JENKINS_AGENT_HOME}"/agent
# Persist agent workdir path through an environment variable for people extending the image
ENV AGENT_WORKDIR=${AGENT_WORKDIR}
RUN addgroup -g "${gid}" "${group}" \
# Set the home directory (h), set user and group id (u, G), set the shell, don't ask for password (D)
&& adduser -h "${JENKINS_AGENT_HOME}" -u "${uid}" -G "${group}" -s /bin/bash -D "${user}" \
# Unblock user
&& passwd -u "${user}" \
# Prepare subdirectories
&& mkdir -p "${JENKINS_AGENT_HOME}/.ssh/" "${JENKINS_AGENT_HOME}/.jenkins/" "${AGENT_WORKDIR}" \
&& chown -R "${uid}":"${gid}" "${JENKINS_AGENT_HOME}" "${AGENT_WORKDIR}"
RUN addgroup docker || true && \
addgroup ${user} docker
RUN apk add --no-cache \
bash \
git-lfs \
less \
musl-locales \
netcat-openbsd \
openssh \
patch
# setup SSH server
RUN sed -i /etc/ssh/sshd_config \
-e 's/#PermitRootLogin.*/PermitRootLogin no/' \
-e 's/#PasswordAuthentication.*/PasswordAuthentication no/' \
-e 's/#SyslogFacility.*/SyslogFacility AUTH/' \
-e 's/#LogLevel.*/LogLevel INFO/' \
-e 's/#PermitUserEnvironment.*/PermitUserEnvironment yes/' \
&& mkdir /var/run/sshd
# Install JDK
ENV JAVA_HOME=/opt/java/openjdk
COPY --from=jre-build /javaruntime "$JAVA_HOME"
ENV PATH="${JAVA_HOME}/bin:${PATH}"
# VOLUME directive must happen after setting up permissions and content
VOLUME "${AGENT_WORKDIR}" "${JENKINS_AGENT_HOME}"/.jenkins "/tmp" "/run" "/var/run"
WORKDIR "${JENKINS_AGENT_HOME}"
# Alpine's ssh doesn't use $PATH defined in /etc/environment, so we define `$PATH` in `~/.ssh/environment`
# The file path has been created earlier in the file by `mkdir -p` and we also have configured sshd so that it will
# allow environment variables to be sourced (see `sed` command related to `PermitUserEnvironment`)
RUN echo "PATH=${PATH}" >> ${JENKINS_AGENT_HOME}/.ssh/environment
COPY setup-sshd /usr/local/bin/setup-sshd
EXPOSE 22
ENTRYPOINT ["setup-sshd"]
LABEL \
org.opencontainers.image.vendor="Jenkins project" \
org.opencontainers.image.title="Official Jenkins SSH Agent Docker image" \
org.opencontainers.image.description="A Jenkins agent image which allows using SSH to establish the connection" \
org.opencontainers.image.url="https://www.jenkins.io/" \
org.opencontainers.image.source="https://github.com/jenkinsci/docker-ssh-agent" \
org.opencontainers.image.licenses="MIT"

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2015-2019 Jenkins project contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

15
README.md Normal file
View File

@ -0,0 +1,15 @@
# Склейка DinD и Jenkins SSH Agent.
- Берем [Jenkins SSH Agent](https://github.com/jenkinsci/docker-ssh-agent), а именно [Alpine Dockerfile](https://github.com/jenkinsci/docker-ssh-agent/blob/master/alpine/Dockerfile)
- Изменяем базовый образ на `docker:dind` (по-умолчанию он на базе alpine)
- Добавляем в `Dockerfile` под создание пользователя `jenkins` строки:
```Dockerfile
RUN addgroup docker || true && \
addgroup ${user} docker
```
- В `setup-sshd` вписываем строки:
```shell
# dockerd's patch
dockerd-entrypoint.sh
```
- Собираем, тэгаем и пушим

View File

@ -0,0 +1,5 @@
dockerd-entrypoint.sh
addgroup docker || true
addgroup jenkins docker
setup-sshd $@

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

106
jdk-download-url.sh Normal file
View File

@ -0,0 +1,106 @@
#!/bin/sh
# Check if at least one argument was passed to the script
# If one argument was passed and JAVA_VERSION is set, assign the argument to OS
# If two arguments were passed, assign them to JAVA_VERSION and OS respectively
# If three arguments were passed, assign them to JAVA_VERSION, OS and ARCHS respectively
# If not, check if JAVA_VERSION and OS are already set. If they're not set, exit the script with an error message
if [ $# -eq 1 ] && [ -n "$JAVA_VERSION" ]; then
OS=$1
elif [ $# -eq 2 ]; then
JAVA_VERSION=$1
OS=$2
elif [ $# -eq 3 ]; then
JAVA_VERSION=$1
OS=$2
ARCHS=$3
elif [ -z "$JAVA_VERSION" ] && [ -z "$OS" ]; then
echo "Error: No Java version and OS specified. Please set the JAVA_VERSION and OS environment variables or pass them as arguments." >&2
exit 1
elif [ -z "$JAVA_VERSION" ]; then
echo "Error: No Java version specified. Please set the JAVA_VERSION environment variable or pass it as an argument." >&2
exit 1
elif [ -z "$OS" ]; then
OS=$1
if [ -z "$OS" ]; then
echo "Error: No OS specified. Please set the OS environment variable or pass it as an argument." >&2
exit 1
fi
fi
# Check if ARCHS is set. If it's not set, assign the current architecture to it
if [ -z "$ARCHS" ]; then
ARCHS=$(uname -m | sed -e 's/x86_64/x64/' -e 's/armv7l/arm/')
else
# Convert ARCHS to an array
OLD_IFS=$IFS
IFS=','
set -- "$ARCHS"
ARCHS=""
for arch in "$@"; do
ARCHS="$ARCHS $arch"
done
IFS=$OLD_IFS
fi
# Check if jq and curl are installed
# If they are not installed, exit the script with an error message
if ! command -v jq >/dev/null 2>&1 || ! command -v curl >/dev/null 2>&1; then
echo "jq and curl are required but not installed. Exiting with status 1." >&2
exit 1
fi
# Replace underscores with plus signs in JAVA_VERSION
ARCHIVE_DIRECTORY=$(echo "$JAVA_VERSION" | tr '_' '+')
# URL encode ARCHIVE_DIRECTORY
ENCODED_ARCHIVE_DIRECTORY=$(echo "$ARCHIVE_DIRECTORY" | xargs -I {} printf %s {} | jq "@uri" -jRr)
# Determine the OS type for the URL
OS_TYPE="linux"
if [ "$OS" = "alpine" ]; then
OS_TYPE="alpine-linux"
fi
if [ "$OS" = "windows" ]; then
OS_TYPE="windows"
fi
# Initialize a variable to store the URL for the first architecture
FIRST_ARCH_URL=""
# Loop over the array of architectures
for ARCH in $ARCHS; do
# Fetch the download URL from the Adoptium API
URL="https://api.adoptium.net/v3/binary/version/jdk-${ENCODED_ARCHIVE_DIRECTORY}/${OS_TYPE}/${ARCH}/jdk/hotspot/normal/eclipse?project=jdk"
if ! RESPONSE=$(curl -fsI "$URL"); then
echo "Error: Failed to fetch the URL for architecture ${ARCH} from ${URL}. Exiting with status 1." >&2
echo "Response: $RESPONSE" >&2
exit 1
fi
# Extract the redirect URL from the HTTP response
REDIRECTED_URL=$(echo "$RESPONSE" | grep -i location | awk '{print $2}' | tr -d '\r')
# If no redirect URL was found, exit the script with an error message
if [ -z "$REDIRECTED_URL" ]; then
echo "Error: No redirect URL found for architecture ${ARCH} from ${URL}. Exiting with status 1." >&2
echo "Response: $RESPONSE" >&2
exit 1
fi
# Use curl to check if the URL is reachable
# If the URL is not reachable, print an error message and exit the script with status 1
if ! curl -v -fs "$REDIRECTED_URL" >/dev/null 2>&1; then
echo "${REDIRECTED_URL}" is not reachable for architecture "${ARCH}". >&2
exit 1
fi
# If FIRST_ARCH_URL is empty, store the current URL
if [ -z "$FIRST_ARCH_URL" ]; then
FIRST_ARCH_URL=$REDIRECTED_URL
fi
done
# If all downloads are successful, print the URL for the first architecture
echo "$FIRST_ARCH_URL"

51
jdk-download.sh Normal file
View File

@ -0,0 +1,51 @@
#!/bin/sh
set -x
# Check if curl and tar are installed
if ! command -v curl >/dev/null 2>&1 || ! command -v tar >/dev/null 2>&1 ; then
echo "curl and tar are required but not installed. Exiting with status 1." >&2
exit 1
fi
# Set the OS to "standard" by default
OS="standard"
# If a second argument is provided, use it as the OS
if [ $# -eq 1 ]; then
OS=$1
fi
# Call jdk-download-url.sh with JAVA_VERSION and OS as arguments
# The two scripts should be in the same directory.
# That's why we're trying to find the directory of the current script and use it to call the other script.
SCRIPT_DIR=$(cd "$(dirname "$0")" || exit; pwd)
if ! DOWNLOAD_URL=$("${SCRIPT_DIR}"/jdk-download-url.sh "${JAVA_VERSION}" "${OS}"); then
echo "Error: Failed to fetch the URL. Exiting with status 1." >&2
exit 1
fi
# Use curl to download the JDK archive from the URL
if ! curl --silent --location --output /tmp/jdk.tar.gz "${DOWNLOAD_URL}"; then
echo "Error: Failed to download the JDK archive. Exiting with status 1." >&2
exit 1
fi
# Extract the archive to the /opt/ directory
if ! tar -xzf /tmp/jdk.tar.gz -C /opt/; then
echo "Error: Failed to extract the JDK archive. Exiting with status 1." >&2
exit 1
fi
# Get the name of the extracted directory
EXTRACTED_DIR=$(tar -tzf /tmp/jdk.tar.gz | head -n 1 | cut -f1 -d"/")
# Rename the extracted directory to /opt/jdk-${JAVA_VERSION}
if ! mv "/opt/${EXTRACTED_DIR}" "/opt/jdk-${JAVA_VERSION}"; then
echo "Error: Failed to rename the extracted directory. Exiting with status 1." >&2
exit 1
fi
# Remove the downloaded archive
if ! rm -f /tmp/jdk.tar.gz; then
echo "Error: Failed to remove the downloaded archive. Exiting with status 1." >&2
exit 1
fi

85
setup-sshd Normal file
View File

@ -0,0 +1,85 @@
#!/usr/bin/env bash
set -ex
# The MIT License
#
# Copyright (c) 2015, CloudBees, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Usage:
# docker run jenkins/ssh-agent <public key>
# or
# docker run -e "JENKINS_AGENT_SSH_PUBKEY=<public key>" jenkins/ssh-agent
write_key() {
local ID_GROUP
# As user, group, uid, gid and JENKINS_AGENT_HOME can be overridden at build,
# we need to find the values for JENKINS_AGENT_HOME
# ID_GROUP contains the user:group of JENKINS_AGENT_HOME directory
ID_GROUP=$(stat -c '%U:%G' "${JENKINS_AGENT_HOME}")
mkdir -p "${JENKINS_AGENT_HOME}/.ssh"
echo "$1" > "${JENKINS_AGENT_HOME}/.ssh/authorized_keys"
chown -Rf "${ID_GROUP}" "${JENKINS_AGENT_HOME}/.ssh"
chmod 0700 -R "${JENKINS_AGENT_HOME}/.ssh"
}
if [[ ${JENKINS_AGENT_SSH_PUBKEY} == ssh-* ]]; then
write_key "${JENKINS_AGENT_SSH_PUBKEY}"
fi
if [[ ${JENKINS_SLAVE_SSH_PUBKEY} == ssh-* ]]; then
write_key "${JENKINS_SLAVE_SSH_PUBKEY}"
fi
# ensure variables passed to docker container are also exposed to ssh sessions
env | grep _ >> /etc/environment
if [[ $# -gt 0 ]]; then
echo "${0##*/} params: $@"
if [[ $1 == ssh-* ]]; then
echo "Authorizing ssh pubkey found in params."
write_key "$1"
shift 1
elif [[ "$@" == "/usr/sbin/sshd -D -p 22" ]]; then
# neutralize default jenkins docker-plugin command
# we will run sshd at the end anyway
echo "Ignoring provided sshd command."
# if unquoted (4 tokens) shift extra 3
[[ "$2" == "-D" ]] && shift 3
shift 1
else
echo "Executing params: '$@'"
exec "$@"
fi
fi
# generate host keys if not present
ssh-keygen -A
# theswayfarer's patch
dockerd-entrypoint.sh
# do not detach (-D), log to stderr (-e), passthrough other arguments
exec /usr/sbin/sshd -D -e "${@}"

110
setup-sshd.ps1 Normal file
View File

@ -0,0 +1,110 @@
# The MIT License
#
# Copyright (c) 2019-2020, Alex Earl
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Usage:
# docker run jenkins/ssh-agent <public key>
# or
# docker run -e "JENKINS_AGENT_SSH_PUBKEY=<public key>" jenkins/ssh-agent
# or
# docker run -e "JENKINS_AGENT_SSH_PUBKEY=<public key>" -e "JENKINS_AGENT_SSH_KNOWNHOST_0=<known host entry>" -e "JENKINS_AGENT_SSH_KNOWNHOST_n=<known host entry>" jenkins/ssh-agent
[CmdletBinding()]
Param(
[Parameter(Position = 0, ValueFromRemainingArguments = $true)]
[string] $Cmd
)
function Get-SSHDir {
return Join-Path "C:/Users/$env:JENKINS_AGENT_USER" '.ssh'
}
function Check-SSHDir {
$sshDir = Get-SSHDir
if(-not (Test-Path $sshDir)) {
New-Item -Type Directory -Path $sshDir | Out-Null
icacls.exe $sshDir /setowner $env:JENKINS_AGENT_USER | Out-Null
icacls.exe $sshDir /grant $('{0}:(CI)(OI)(F)' -f $env:JENKINS_AGENT_USER) /grant "administrators:(CI)(OI)(F)" | Out-Null
icacls.exe $sshDir /inheritance:r | Out-Null
}
}
function Write-Key($Key) {
# this writes the key and sets the permissions correctly for pubkey auth
$authorizedKeys = Join-Path (Get-SSHDir) 'authorized_keys'
Set-Content -Path $authorizedKeys -Value "$Key" -Encoding UTF8
icacls.exe $authorizedKeys /setowner $env:JENKINS_AGENT_USER | Out-Null
}
function Write-HostKey($Key) {
# this writes the key and sets the permissions
$knownHosts = Join-Path (Get-SSHDir) 'known_hosts'
Set-Content -Path $knownHosts -Value "$Key" -Encoding UTF8
icacls.exe $knownHosts /setowner $env:JENKINS_AGENT_USER | Out-Null
}
# Give the user Full Access to the home directory
icacls.exe "C:/Users/$env:JENKINS_AGENT_USER" /grant "${env:JENKINS_AGENT_USER}:(CI)(OI)(F)" | Out-Null
# check the .ssh dir permissions
Check-SSHDir
if($env:JENKINS_AGENT_SSH_PUBKEY -match "^ssh-.*") {
Write-Key $env:JENKINS_AGENT_SSH_PUBKEY
}
$index = 0
$knownHostKeyVar = Get-ChildItem -Path "env:JENKINS_AGENT_SSH_KNOWNHOST_$index" -ErrorAction 'SilentlyContinue'
while($null -ne $knownHostKeyVar) {
Write-HostKey $knownHostKeyVar.Value
$index++
$knownHostKeyVar = Get-ChildItem env: -Name "JENKINS_AGENT_SSH_KNOWNHOST_$index"
}
# ensure variables passed to docker container are also exposed to ssh sessions
Get-ChildItem env: | ForEach-Object { setx /m $_.Name $_.Value | Out-Null }
if(![System.String]::IsNullOrWhiteSpace($Cmd)) {
Write-Host "$($MyInvocation.MyCommand.Name) param: '$Cmd'"
if($Cmd -match "^ssh-.*") {
Write-Host "Authorizing ssh pubkey found in params."
Write-Key $Cmd
} elseif($Cmd -match "^/usr/sbin/sshd") {
# neutralize default jenkins docker-plugin command
# we will run sshd at the end anyway
Write-Host "Ignoring provided (linux) sshd command."
} else {
Write-Host "Executing param: $Cmd"
& $Cmd
exit
}
}
Start-Service sshd
# dump network information
ipconfig
netstat -a
# aside from forwarding ssh logs, this keeps the container open
Get-Content -Path "C:\ProgramData\ssh\logs\sshd.log" -Wait