Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
zeriyoshi committed Jul 10, 2024
1 parent 4d9bf24 commit cef3aec
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.git
.github
*.DS_Store
LICENSE
README.md
37 changes: 37 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: CI

on:
workflow_dispatch:
pull_request_target:
push:
branches:
- main

jobs:
ci:
runs-on: ubuntu-latest
strategy:
matrix:
arch: ["amd64", "arm64/v8", "arm/v7"]
busybox: ["glibc", "musl", "uclibc"]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: arm64,arm
- name: Setup buildx
uses: docker/setup-buildx-action@v3
- name: Build container
uses: docker/build-push-action@v6
with:
build-args: ARCH=${{ matrix.arch }}
context: .
file: ./Dockerfile
load: true
push: false
tags: test-${{ matrix.arch }}-${{ matrix.busybox }}
- name: Test
run: |
test "$(docker run --rm -i "test-${{ matrix.arch }}-${{ matrix.busybox }}" -c "php -r 'echo shell_exec(\"whoami\");'")" = "nonroot"
41 changes: 41 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
ARG _DEB_VERSION="12"

ARG ARCH="arm64/v8"

ARG BASE="debian:${_DEB_VERSION}"
ARG BASE_PKGS="php"
ARG BASE_BINS="php"
ARG BASE_PKG_INSTALL_CMD="apt-get update && apt-get install -y"

ARG BUSYBOX="busybox:latest"

ARG TARGET="gcr.io/distroless/base-nossl-debian${_DEB_VERSION}:latest"

FROM --platform="linux/${ARCH}" ${BUSYBOX} AS busybox

FROM --platform="linux/${ARCH}" ${BASE} AS base

ARG BASE_PKGS
ARG BASE_BINS
ARG BASE_PKG_INSTALL_CMD

COPY --chmod=755 "dependency_resolve" "/usr/local/bin/dependency_resolve"

RUN /bin/sh -c "${BASE_PKG_INSTALL_CMD} ${BASE_PKGS}" \
&& /usr/local/bin/dependency_resolve \
"$(which "ldd")" \
$(echo "${BASE_BINS}" | xargs which) \
| xargs -I {} sh -c 'mkdir -p /root/rootfs/$(dirname "{}") && cp -apP "{}" "/root/rootfs/{}"'

FROM --platform="linux/${ARCH}" ${TARGET} AS target

ARG BASE_BINS

COPY --from=base "/root/rootfs" "/"

COPY --from=busybox "/bin/busybox" "/bin/busybox"
RUN ["/bin/busybox", "--install", "-s"]

USER nonroot

ENTRYPOINT ["/bin/sh"]
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# dependency_resolve - distroless packaging support

Binary packaging support tool for distroless / alpine.

## Usage

```Dockerfile
FROM debian:12 AS builder
COPY --chmod=755 "dependency_resolve" "/usr/local/bin/dependency_resolve"
RUN apt-get update && apt-get install -y "php"
RUN dependency_resolve "$(which "ldd")" "$(which "php")" | xargs -I {} sh -c 'mkdir -p /root/rootfs/$(dirname "{}") && cp -apP "{}" "/root/rootfs/{}"'

FROM gcr.io/distroless/base-nossl-debian12:latest
COPY --from=builder "/root/rootfs" "/"

ENTRYPOINT ["/usr/bin/php"]
```

See `Dockerfile` for more details.
115 changes: 115 additions & 0 deletions dependency_resolve
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#!/bin/sh

DRSLV_VERSION="2.0.0"

DRSLV_SUCCESS=0
DRSLV_ERROR_WRONG_PARAMS=1
DRSLV_ERROR_PROCESS_FAILED=2
DRSLV_ERROR_LDD_NOT_FOUND=3
DRSLV_ERROR_LDD_NOT_SUPPORTED=4
DRSLV_ERROR_BINARY_NOT_FOUND=5

usage() {
echo "dependency resolve - distroless packaging support v${DRSLV_VERSION}
usage: ${0} [ldd_binary_path] ...[target_binary_paths]
"
}

version() {
echo "${DRSLV_VERSION}"
}

check_ldd() {
if [ ! -f "${1}" ]; then
echo "ldd not found: ${1}" >&2
exit ${DRSLV_ERROR_LDD_NOT_FOUND}
fi

ldd_version=$("${1}" --version 2>&1)
if ! echo "${ldd_version}" | grep -qE '(GLIBC|musl libc)'; then
echo "ldd executable not supported: ${1}" >&2
exit ${DRSLV_ERROR_LDD_NOT_SUPPORTED}
fi
}

check_binary() {
if [ ! -e "${1}" ]; then
echo "binary not found: ${1}" >&2
exit ${DRSLV_ERROR_BINARY_NOT_FOUND}
fi
}

resolve_symlink() {
path="${1}"
result="${path}"
while [ -L "${path}" ]; do
link_target=$(readlink "${path}")
if echo "${link_target}" | grep -q '^/'; then
path="${link_target}"
else
path="$(cd "$(dirname "${path}")" && pwd)/${link_target}"
fi
result="${result} ${path}"
done
echo "${result}"
}

dependency_resolve() {
ldd_path="${1}"
binary_path="${2}"
result=""

resolved_paths=$(resolve_symlink "${binary_path}")
for path in ${resolved_paths}; do
result="${result} ${path}"
if [ -f "${path}" ]; then
ldd_output=$("${ldd_path}" "${path}" 2>&1)
if ! echo "${ldd_output}" | grep -qE '(not a dynamic executable|Not a valid dynamic program)'; then
while read -r line; do
library=$(echo "${line}" | awk '{print $3}')
if [ -n "${library}" ] && [ "${library}" != "not" ]; then
result="${result} $(dependency_resolve "${ldd_path}" "${library}")"
fi
done << EOF
${ldd_output}
EOF
fi
fi
done

echo "${result}"
}

if [ $# -lt 2 ]; then
case "${1}" in
-v|--version)
version
exit ${DRSLV_SUCCESS}
;;
-h|--help)
usage
exit ${DRSLV_SUCCESS}
;;
*)
usage
exit ${DRSLV_ERROR_WRONG_PARAMS}
;;
esac
fi

ldd_path="${1}"
check_ldd "${ldd_path}"

shift
for binary_path in "$@"; do
check_binary "${binary_path}"
done

dependencies=""
for binary_path in "$@"; do
dependencies="${dependencies} $(dependency_resolve "${ldd_path}" "${binary_path}")"
done

echo "${dependencies}" | tr ' ' '\n' | sort | uniq | sed '/^$/d'
exit ${DRSLV_SUCCESS}

0 comments on commit cef3aec

Please sign in to comment.