-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bin/podman-cloud: add a container to access Kubernetes, GCloud and AWS
- Loading branch information
Showing
3 changed files
with
323 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,319 @@ | ||
#!/bin/bash | ||
# SPDX-License-Identifier: MIT | ||
# | ||
# Copyright (c) 2024 Nicolas Iooss | ||
# | ||
# 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. | ||
# | ||
# Run various cloud-related tools in a container | ||
# | ||
# - Kubectl from https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/ | ||
# - to view the configuration: kubectl config view | ||
# - to get current cluster-wide permissions: kubectl auth can-i --list | ||
# - to list namespaces: kubectl get ns | ||
# | ||
# - AWS (Amazon Web Service) CLI from | ||
# https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html#cliv2-linux-install | ||
# - to get active user: aws sts get-caller-identity | ||
# - to authenticate with a MFA (Multi-Factor Authentication) token: | ||
# export AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... | ||
# aws sts get-session-token --serial-number "arn:aws:iam::$AWS_ACCOUNT_ID:mfa/$AWS_USER" --token-code 112233 | ||
# - to list files in an AWS S3 bucket: aws s3 ls s3://bucket | ||
# - to get IAM policy: aws iam get-account-authorization-details | ||
# - to list Compute instances: aws ec2 describe-instances | ||
# | ||
# - Google Cloud CLI from https://cloud.google.com/sdk/docs/install#deb | ||
# This provides gcloud and gsutil. | ||
# - to list active sessions: gcloud auth list | ||
# - to authenticate with service credentials in a JSON file: | ||
# gcloud auth login --no-browser --cred-file google-workspace-credentials.json | ||
# gcloud config set account ... | ||
# - to list files in a Google Storage: gsutil ls gs://bucket | ||
# - to list projects: gcloud projects list | ||
# - to get IAM policy for a project: gcloud projects get-iam-policy $PROJECT_ID | ||
# - to list Compute instances: gcloud compute instances list | ||
# - to get SSH config: gcloud compute config-ssh | ||
|
||
set -e | ||
|
||
build_container() { | ||
# Update the base image | ||
mapfile -t OLD_BASE_IMAGES < <(podman image list '--format={{.Id}}' docker.io/library/debian:bookworm-slim) | ||
podman pull docker.io/library/debian:bookworm-slim | ||
for OLD_BASE_IMAGE in "${OLD_BASE_IMAGES[@]}" ; do | ||
if [ "$(podman image list '--format={{.Dangling}}' --filter "id=${OLD_BASE_IMAGE}")" = 'true' ] ; then | ||
echo "Removing old podman base image ${OLD_BASE_IMAGE}" | ||
podman image rm -- "${OLD_BASE_IMAGE}" | ||
fi | ||
done | ||
|
||
# Build a container with cloud-related tools | ||
podman build --no-cache -t localhost/podman-cloud -f /dev/stdin << EOF | ||
FROM docker.io/library/debian:bookworm-slim | ||
RUN export DEBIAN_FRONTEND=noninteractive && \ | ||
apt-get update && \ | ||
apt-get install --no-install-recommends --no-install-suggests -y \ | ||
ca-certificates \ | ||
curl \ | ||
gnupg \ | ||
jq \ | ||
less \ | ||
mandoc \ | ||
openssh-client \ | ||
python3 \ | ||
python-is-python3 \ | ||
unzip \ | ||
vim && \ | ||
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg && \ | ||
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' > /etc/apt/sources.list.d/kubernetes.list && \ | ||
echo 'Package: kubectl' > /etc/apt/preferences.d/k8s && \ | ||
echo 'Pin: release o=obs://build.opensuse.org/isv:kubernetes:core:stable:v1.29/deb,n=deb,l=isv:kubernetes:core:stable:v1.29,c=' >> /etc/apt/preferences.d/k8s && \ | ||
echo 'Pin-Priority: 1000' >> /etc/apt/preferences.d/k8s && \ | ||
curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor -o /etc/apt/keyrings/cloud.google.gpg && \ | ||
echo 'deb [signed-by=/etc/apt/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main' > /etc/apt/sources.list.d/google-cloud-sdk.list && \ | ||
apt-get update && \ | ||
apt-get install --no-install-recommends --no-install-suggests -y google-cloud-cli google-cloud-cli-gke-gcloud-auth-plugin kubectl && \ | ||
apt-get clean && \ | ||
rm -rf /var/lib/apt/lists/ /var/log/* && \ | ||
cd /opt && \ | ||
curl https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o awscliv2.zip && \ | ||
unzip -q awscliv2.zip && \ | ||
./aws/install --bin-dir /usr/bin && \ | ||
rm -r awscliv2.zip aws | ||
EOF | ||
} | ||
|
||
# Option --update updates the container if it already exists | ||
if [ $# -ge 1 ] && [ "$1" = '--update' ] ; then | ||
shift | ||
mapfile -t OLD_IMAGES < <(podman image list '--format={{.Id}}' localhost/podman-cloud) | ||
build_container | ||
for OLD_IMAGE in "${OLD_IMAGES[@]}" ; do | ||
if [ "$(podman image list '--format={{.Dangling}}' --filter "id=${OLD_IMAGE}")" = 'true' ] ; then | ||
echo "Removing old podman image ${OLD_IMAGE}" | ||
podman image rm -- "${OLD_IMAGE}" | ||
fi | ||
done | ||
elif ! podman image exists localhost/podman-cloud ; then | ||
build_container | ||
fi | ||
|
||
# Option --no-start can be used to build the container without starting it | ||
if [ $# -ge 1 ] && [ "$1" = '--no-start' ] ; then | ||
exit | ||
fi | ||
|
||
PODMAN_ARGS=() | ||
|
||
# Share files provided by environment variables | ||
if [ -n "${AWS_CA_BUNDLE:-}" ]; then | ||
PODMAN_ARGS+=(-v "${AWS_CA_BUNDLE}:${AWS_CA_BUNDLE}") | ||
fi | ||
if [ -n "${AWS_CONFIG_FILE:-}" ]; then | ||
PODMAN_ARGS+=(-v "${AWS_CONFIG_FILE}:${AWS_CONFIG_FILE}") | ||
fi | ||
if [ -n "${AWS_WEB_IDENTITY_TOKEN_FILE:-}" ]; then | ||
PODMAN_ARGS+=(-v "${AWS_WEB_IDENTITY_TOKEN_FILE}:${AWS_WEB_IDENTITY_TOKEN_FILE}") | ||
fi | ||
if [ -n "${KUBECONFIG:-}" ]; then | ||
PODMAN_ARGS+=(-v "${KUBECONFIG}:${KUBECONFIG}") | ||
fi | ||
|
||
while [ $# -ge 1 ] ; do | ||
case "$1" in | ||
-v|--volume) | ||
if [ $# -lt 2 ] ; then | ||
break | ||
fi | ||
# Configure a shared volume | ||
PODMAN_ARGS+=(-v "$2") | ||
shift 2 | ||
;; | ||
*) | ||
# Propagate the command line to the subcommand | ||
break | ||
;; | ||
esac | ||
done | ||
|
||
# Use SCMP_ACT_LOG to record the denied syscalls | ||
SECCOMP_PROFILE=' | ||
{ | ||
"defaultAction": "SCMP_ACT_ERRNO", | ||
"syscalls": [ | ||
{ | ||
"names": [ | ||
"access", | ||
"arch_prctl", | ||
"bind", | ||
"brk", | ||
"capset", | ||
"chdir", | ||
"chmod", | ||
"chown", | ||
"clone", | ||
"clone3", | ||
"close", | ||
"connect", | ||
"dup", | ||
"dup2", | ||
"dup3", | ||
"epoll_create", | ||
"epoll_create1", | ||
"epoll_ctl", | ||
"epoll_pwait", | ||
"execve", | ||
"exit", | ||
"exit_group", | ||
"faccessat2", | ||
"fadvise64", | ||
"fchdir", | ||
"fchmod", | ||
"fchmodat", | ||
"fchown", | ||
"fchownat", | ||
"fcntl", | ||
"fdatasync", | ||
"flock", | ||
"fstat", | ||
"fstatfs", | ||
"fsync", | ||
"ftruncate", | ||
"futex", | ||
"getcwd", | ||
"getdents64", | ||
"getegid", | ||
"geteuid", | ||
"getgid", | ||
"getgroups", | ||
"getpeername", | ||
"getpgrp", | ||
"getpid", | ||
"getppid", | ||
"getrandom", | ||
"getresgid", | ||
"getresuid", | ||
"getrlimit", | ||
"getsockname", | ||
"getsockopt", | ||
"gettid", | ||
"getuid", | ||
"ioctl", | ||
"kill", | ||
"lchown", | ||
"lgetxattr", | ||
"link", | ||
"lseek", | ||
"lstat", | ||
"madvise", | ||
"mkdir", | ||
"mkdirat", | ||
"mmap", | ||
"mprotect", | ||
"mremap", | ||
"munmap", | ||
"nanosleep", | ||
"newfstatat", | ||
"openat", | ||
"pipe2", | ||
"poll", | ||
"prctl", | ||
"pread64", | ||
"prlimit64", | ||
"pselect6", | ||
"pwrite64", | ||
"read", | ||
"readlink", | ||
"readlinkat", | ||
"recvfrom", | ||
"recvmsg", | ||
"rename", | ||
"renameat", | ||
"rmdir", | ||
"rseq", | ||
"rt_sigaction", | ||
"rt_sigprocmask", | ||
"rt_sigreturn", | ||
"sched_getaffinity", | ||
"sched_yield", | ||
"sendmmsg", | ||
"sendmsg", | ||
"sendto", | ||
"set_robust_list", | ||
"set_tid_address", | ||
"setgroups", | ||
"setpgid", | ||
"setresgid", | ||
"setresuid", | ||
"setsid", | ||
"setsockopt", | ||
"sigaltstack", | ||
"socket", | ||
"stat", | ||
"statfs", | ||
"statx", | ||
"symlink", | ||
"sync_file_range", | ||
"sysinfo", | ||
"tgkill", | ||
"umask", | ||
"uname", | ||
"unlink", | ||
"unlinkat", | ||
"utimensat", | ||
"vfork", | ||
"wait4", | ||
"waitid", | ||
"write", | ||
"writev" | ||
], | ||
"action": "SCMP_ACT_ALLOW" | ||
} | ||
] | ||
}' | ||
|
||
# Propage authentication variables from the environment too | ||
# - AWS: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html | ||
exec podman run --rm \ | ||
--env AWS_ACCESS_KEY_ID \ | ||
--env AWS_CA_BUNDLE \ | ||
--env AWS_CONFIG_FILE \ | ||
--env AWS_CLI_AUTO_PROMPT \ | ||
--env AWS_CLI_FILE_ENCODING \ | ||
--env AWS_DEFAULT_OUTPUT \ | ||
--env AWS_DEFAULT_REGION \ | ||
--env "AWS_EC2_METADATA_DISABLED=${AWS_EC2_METADATA_DISABLED:-true}" \ | ||
--env AWS_ENDPOINT_URL \ | ||
--env AWS_IGNORE_CONFIGURED_ENDPOINT_URLS \ | ||
--env AWS_MAX_ATTEMPTS \ | ||
--env AWS_PAGER \ | ||
--env AWS_PROFILE \ | ||
--env AWS_REGION \ | ||
--env AWS_RETRY_MODE \ | ||
--env AWS_ROLE_ARN \ | ||
--env AWS_ROLE_SESSION_NAME \ | ||
--env AWS_SECRET_ACCESS_KEY \ | ||
--env AWS_SESSION_TOKEN \ | ||
--env AWS_USE_DUALSTACK_ENDPOINT \ | ||
--env AWS_USE_FIPS_ENDPOINT \ | ||
--env AWS_WEB_IDENTITY_TOKEN_FILE \ | ||
--env KUBECONFIG \ | ||
"${PODMAN_ARGS[@]}" \ | ||
--security-opt seccomp=<(printf %s "$SECCOMP_PROFILE") \ | ||
-ti localhost/podman-cloud "$@" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters