Initial commit

This commit is contained in:
2024-07-02 13:09:46 +02:00
commit 11e0f786fe
15 changed files with 302 additions and 0 deletions

9
Dockerfile Normal file
View File

@ -0,0 +1,9 @@
FROM alpine:3.20
RUN apk --update add openssh bash
WORKDIR /gitea/workspace
COPY entrypoint.sh .
ENTRYPOINT ["/gitea/workspace/entrypoint.sh"]

33
LICENSE Normal file
View File

@ -0,0 +1,33 @@
BSD 4-Clause License
Copyright (c) 2020, Aleksandr Derbenev
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software must
display the following acknowledgement:
This product includes software developed by Aleksandr Derbenev.
4. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

1
README.org Normal file
View File

@ -0,0 +1 @@
#+title: Action to login to a private registry on a remote host

40
action.yml Normal file
View File

@ -0,0 +1,40 @@
name: Docker-Private-Registry-SSH-login
description: Action to log in to a private docker registry on a host reachable via SSH.
author: "Allan Eising"
branding:
icon: "unlock"
color: "yellow"
inputs:
ssh_private_key:
description: "Private SSH key used for logging into remote system."
required: true
ssh_host:
description: Host to deploy to.
required: true
ssh_port:
description: SSH Port
default: 22
required: true
ssh_user:
description: Remote user name.
required: true
registry:
description: Registry hostname
required: true
registry_username:
description: User to log in with on the registry.
registry_password:
description: Password or API token for the registry.
runs:
using: docker
image: Dockerfile
env:
SSH_PRIVATE_KEY: ${{ inputs.ssh_private_key }}
SSH_HOST: ${{ inputs.ssh_host }}
SSH_PORT: ${{ inputs.ssh_port }}
SSH_USER: ${{ inputs.ssh_user }}
REGISTRY_HOST: ${{ inputs.registry }}
REGISTRY_USER: ${{ inputs.registry_username }}
REGISTRY_PASSWORD: ${{ inputs.registry_password }}

15
entrypoint.sh Executable file
View File

@ -0,0 +1,15 @@
#!/usr/bin/env bash
set -eu
echo "Launching SSH agent"
eval $(ssh-agent -s)
ssh-add <(echo "$SSH_PRIVATE_KEY")
echo "Logging in on remote host..."
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
"$SSH_USER@$SSH_HOST" -p "$SSH_PORT" \
"docker login -u ${REGISTRY_USER} --password-stdin ${REGISTRY_HOST}" \
<<< "$REGISTRY_PASSWORD"

23
test/Dockerfile Normal file
View File

@ -0,0 +1,23 @@
# Simple SSH server for testing
FROM alpine:3.20
RUN <<EOF
apk --update add dropbear docker
adduser -D test
mkdir /home/test/.ssh
chown test:test /home/test/.ssh
EOF
COPY cert/domain.crt /usr/local/share/ca-certificates
RUN update-ca-certificates
COPY --chown=test:test test-container-files/authorized_keys /home/test/.ssh
# Non-standard ssh port
EXPOSE 22140
CMD ["dropbear", "-R", "-E", "-F", "-p", "22140"]

63
test/Makefile Normal file
View File

@ -0,0 +1,63 @@
# Simple makefile to test the action.
test: setup start run-test teardown
network:
@docker network create test_network
start-registry:
@echo "Starting docker registry"
@docker run -d \
-p 5000:5000 \
--name test-registry \
--network test_network \
-v ./htpasswd:/htpasswd \
-v ./cert:/cert \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/htpasswd \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/cert/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/cert/domain.key \
registry:2
build:
@echo "Building images..."
@docker build -t docker-private-registry-ssh-test:latest -q .
@docker build -t docker-private-registry-ssh-action:latest -q ..
start-client:
@echo "Starting ssh server"
@docker run -d -p 22140:22140 --name test-server --network test_network docker-private-registry-ssh-test:latest
cert:
openssl x509 -signkey cert/domain.key -in domain.csr -req -days 365 -out cert/domain.crt -extfile domain.ext
stop-registry:
@echo "Removing registry container"
@docker rm -f test-registry
stop-client:
@echo "Removing ssh server container"
@docker rm -f test-server
stop: stop-registry stop-client
start: start-registry start-client
clean: stop
@echo "Removing network"
@docker network rm test_network
setup: build network
teardown: stop clean
run-test:
@echo "Running test..."
@echo
@bash test.sh
.PHONY: start-registry stop-registry stop-client network clean cert start-client start teardown test all

23
test/cert/domain.crt Normal file
View File

@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID0jCCArqgAwIBAgIUb/PA8uB6NVDS+6F+RpzcneKupT8wDQYJKoZIhvcNAQEL
BQAwfzELMAkGA1UEBhMCTk8xDTALBgNVBAgMBFRlc3QxDTALBgNVBAcMBFRlc3Qx
DTALBgNVBAoMBFRlc3QxDTALBgNVBAsMBFRlc3QxFjAUBgNVBAMMDXRlc3QtcmVn
aXN0cnkxHDAaBgkqhkiG9w0BCQEWDXRlc3RAdGVzdC5jb20wHhcNMjQwNzAyMTA0
NzE1WhcNMjUwNzAyMTA0NzE1WjB/MQswCQYDVQQGEwJOTzENMAsGA1UECAwEVGVz
dDENMAsGA1UEBwwEVGVzdDENMAsGA1UECgwEVGVzdDENMAsGA1UECwwEVGVzdDEW
MBQGA1UEAwwNdGVzdC1yZWdpc3RyeTEcMBoGCSqGSIb3DQEJARYNdGVzdEB0ZXN0
LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPA/T686l78igXC8
Gy+XkizOImwwSOv6h4GBT5A/tfpH6MUw5oVHS4EoTwHuQoONOgjZEs07cM8IKceX
YjS75/0cKMHYbVifxopgU8R/aLQmmU5AcgXqIjyexT0LHEuA+LDGOI6H3lDY9T04
jvuz21TZiTSkrMpcjdekc9pUGLwk6J0KtuRjW1w+J/i+sneXgWC8ZH5YYPVA8nEc
FdZC+CWRsaXLiWKwgUBLjKzc/Ku6163c4DpfsSFhxoMoRj3OoGAWfSYZBo5nhNc2
9jzLwTZUYOLm2igY7cMyii31G1LcsZkBM1UqOHGwNGuGMGmZuqZFuUHUAGAxViib
o6Q/bV8CAwEAAaNGMEQwCQYDVR0TBAIwADAYBgNVHREEETAPgg10ZXN0LXJlZ2lz
dHJ5MB0GA1UdDgQWBBSVSqxfNR9qbUOdvmcSX3IjEYZupzANBgkqhkiG9w0BAQsF
AAOCAQEAGHFkIH3IAQ8+sGctglIBDv6DzxfzajS/F+C0V0/9MmZk0VAv3CpvOqCj
R2DmKNupfWuBKdZAqXSS2lIcNWB8q2ehWteubRlyogjNGBkSjcj471KNPHO5qGc/
MWse0myQA8lhSYRMmXZrWgVisIPY7TdO0wD9hkLCiek9MF7feTznt/tT5rppU0lw
hMlCTdSnOmFkekK8+HDL+7pr+S0wDBr1mURnMvp5PvygzSjfMj+sTyyu5M6r5R7+
aUFSmhUBenCC3r4kOEGNO40+101Dc4rqXZTcW+14yXnBlld3B5lbAl3V9djjWa80
P7zv4XKLlMvK4YezWZJRD849v5M+kQ==
-----END CERTIFICATE-----

28
test/cert/domain.key Normal file
View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDwP0+vOpe/IoFw
vBsvl5IsziJsMEjr+oeBgU+QP7X6R+jFMOaFR0uBKE8B7kKDjToI2RLNO3DPCCnH
l2I0u+f9HCjB2G1Yn8aKYFPEf2i0JplOQHIF6iI8nsU9CxxLgPiwxjiOh95Q2PU9
OI77s9tU2Yk0pKzKXI3XpHPaVBi8JOidCrbkY1tcPif4vrJ3l4FgvGR+WGD1QPJx
HBXWQvglkbGly4lisIFAS4ys3Pyrutet3OA6X7EhYcaDKEY9zqBgFn0mGQaOZ4TX
NvY8y8E2VGDi5tooGO3DMoot9RtS3LGZATNVKjhxsDRrhjBpmbqmRblB1ABgMVYo
m6OkP21fAgMBAAECggEAAwn5+xB1rPBFzOREP8TeD30ICHBP69Q+dI/rLrrvlVvl
gOEOeW8ecGLPJQobg0h9DHGagEgZNDU5OhIbJumdlKEPjuwq7e0PeN6hEKI/889t
LwU3rAV7K2MiwZPrZrUZ8DqBqqPjVwh3ia+2d06eHqOlzamrmd+z159367IWogKb
PHjdd7wclCD/FmXDTpEcB91MFs1hXH6XnAQxKWXprfyAFGn24OghvuJWZgBwFyJ1
7zicJBn5yqJZgbeWqHQhR4YigmULkem/DiI4wbtz3MOD1mJbAfNd461JK5DHwMJJ
efA2iV80bPrPWPx94k/tAz7nF/s1RraDqNw9qh/SWQKBgQD46B8uR7opailFry1U
KiP+hessWFuYt36JnZyBcP61DLcmv0t4t2HYcpW2ZaRSuyxahJCBY3XyanRVZ+nr
wH0vOdgfI1SafgyP1V9JL/12RqlsJw77zs0oudIkEYVemEYfg4y1EgyYxbRLLLwZ
GBE3+psSlxCIRi78ySP+y/80GwKBgQD3GAPyp+hnS3UqHhKKXCUy4dGK4KuECKi/
GpXCObO3jEqeYbM8jzPmj05MwUAL9pAC+PTd2Qnk0XDzF9E6q2VJuqa7uWi3u/Qi
cE83t9HQlRI4ZLNO9+gTJqi05wdDM6CwRvW8ddb4Pfn1CvWsOTJA14sMTMscGhLo
2hgPlCnYDQKBgQCCBO7UxA8Qty3cAsfQ4TpwKBBS18zxF1j4Fea9DwNeG8hIa0DH
TDPGVwSxhKKzvKZMmlbJ3+SqvsUKH//ncGN0Gek1SsVU9mclczYVCwaBlCPIJRcE
nmA41+hXgveCFFT8/UCxDT6bRxsI8dNH4HSOI1CCA3tVVCQTVBaDcJhc5QKBgQDu
UviD1JWhA7PXUrgZQXUTlaERLU/hAqUX5eFqO1NvBt510tAY6hpqF/CysXY/06nl
ZBBx5cPYMnaZ0XAaAXSpX2EwEU3CYYPAr8iIekDhyNaRE/eqhAwQZKo2CdsEY0hq
nZapFpOoTcbIJbD9UxF4Xy0bSPpieXehpbGtXP/bBQKBgAT1wDB/TOKy7yS+LZv4
/4gcJDcnehpqbT56mSiW/wPAuK4b5HA0Fe8fbhp6Hufu/O7qEzBLD0/uaU+5DhA6
sX2vXyzYFArdbuReAPL+YOCGRdOs3ztGTl3ddLxEeXl1I2YTQ/NiFSRLWnFGCSLe
YTJWK5hRWlVy6oEJ0aqkHHxN
-----END PRIVATE KEY-----

17
test/domain.csr Normal file
View File

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICxDCCAawCAQAwfzELMAkGA1UEBhMCTk8xDTALBgNVBAgMBFRlc3QxDTALBgNV
BAcMBFRlc3QxDTALBgNVBAoMBFRlc3QxDTALBgNVBAsMBFRlc3QxFjAUBgNVBAMM
DXRlc3QtcmVnaXN0cnkxHDAaBgkqhkiG9w0BCQEWDXRlc3RAdGVzdC5jb20wggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDwP0+vOpe/IoFwvBsvl5IsziJs
MEjr+oeBgU+QP7X6R+jFMOaFR0uBKE8B7kKDjToI2RLNO3DPCCnHl2I0u+f9HCjB
2G1Yn8aKYFPEf2i0JplOQHIF6iI8nsU9CxxLgPiwxjiOh95Q2PU9OI77s9tU2Yk0
pKzKXI3XpHPaVBi8JOidCrbkY1tcPif4vrJ3l4FgvGR+WGD1QPJxHBXWQvglkbGl
y4lisIFAS4ys3Pyrutet3OA6X7EhYcaDKEY9zqBgFn0mGQaOZ4TXNvY8y8E2VGDi
5tooGO3DMoot9RtS3LGZATNVKjhxsDRrhjBpmbqmRblB1ABgMVYom6OkP21fAgMB
AAGgADANBgkqhkiG9w0BAQsFAAOCAQEAjstPsip2hZPFYqBsMuyLg6pAGFwiIvCT
vlEvxdO41LB+DGIMqGuaYrp0MVOee9yNT23eqK0cLuByK/oIB27v5uCuyxZGpjjm
6F6uht+hHb1XcuPYopF7KmXZWVHIOp1Aeb4+kI5wsQcYVhEDj8UwAhKyDmcc06Jx
//0wjg7W6iITPkAcEPGV0ctLIBikm04KBGV59ta/ge36SigV7YYxJD4N9wueK5zP
2H9pO3t3OL2qjEXIvzb6zLNlFa+fQLjaNJshdU5IV84juQqw7nFthQuQ0FZow3Q1
XdC4bFEVOHIeHtOclEMJerH0Rd4Hy2vJl17kn+/xWGQxE/E5pE/HjQ==
-----END CERTIFICATE REQUEST-----

5
test/domain.ext Normal file
View File

@ -0,0 +1,5 @@
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
subjectAltName = @alt_names
[alt_names]
DNS.1 = test-registry

2
test/htpasswd Normal file
View File

@ -0,0 +1,2 @@
test:$2y$05$m6aWJNmssjgoblKPgaGPp.uRVhyC26RszqZXlQ6G2yCQvUZ/UEtim

8
test/private-key Normal file
View File

@ -0,0 +1,8 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACDOhJbjLroQpRs5+dwkoiZm1DCLIUQnV3mRM9C8cW3W7wAAAKhz4bW9c+G1
vQAAAAtzc2gtZWQyNTUxOQAAACDOhJbjLroQpRs5+dwkoiZm1DCLIUQnV3mRM9C8cW3W7w
AAAEARpZAPUPbntoxUn2HpiwZul+rnNbdxnJJ1ZSaSWF+dV86EluMuuhClGzn53CSiJmbU
MIshRCdXeZEz0LxxbdbvAAAAH2Vpc2luZ0BBbGxhbnMtTWFjQm9vay1BaXIubG9jYWwBAg
MEBQY=
-----END OPENSSH PRIVATE KEY-----

View File

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM6EluMuuhClGzn53CSiJmbUMIshRCdXeZEz0Lxxbdbv eising@Allans-MacBook-Air.local

34
test/test.sh Executable file
View File

@ -0,0 +1,34 @@
#!/usr/bin/env bash
# Test the action
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color
script_dir="$(dirname "$(readlink -f "$0")")"
private_key=$(cat ${script_dir}/private-key)
output=$(docker run \
-it --rm \
--name test-action \
-e SSH_PRIVATE_KEY="$private_key" \
-e SSH_HOST="test-server" \
-e SSH_PORT="22140" \
-e SSH_USER="test" \
-e REGISTRY_HOST="test-registry:5000" \
-e REGISTRY_USER="test" \
-e REGISTRY_PASSWORD="test" \
--network test_network \
docker-private-registry-ssh-action:latest)
if echo $output | grep "Login Succeeded" > /dev/null; then
echo -e "${GREEN}Test passed.${NC}"
else
echo -e "${RED}Test failed.${NC}"
echo -e "Output: \n"
echo "${output}"
fi
echo -e "\n"