From c36d773953a6fd504589bd2e0dd5ffeb39a0058a Mon Sep 17 00:00:00 2001 From: Saul Paredes Date: Mon, 5 Aug 2024 10:37:30 -0700 Subject: [PATCH] genpolicy: add utility script for containerd pull Add script that helps adapt containerd and docker config for containerd pull feature to work as expected. Signed-off-by: Saul Paredes --- ...policy-advanced-command-line-parameters.md | 20 ++- .../genpolicy/setup_containerd_docker.sh | 127 ++++++++++++++++++ 2 files changed, 143 insertions(+), 4 deletions(-) create mode 100755 src/tools/genpolicy/setup_containerd_docker.sh diff --git a/src/tools/genpolicy/genpolicy-advanced-command-line-parameters.md b/src/tools/genpolicy/genpolicy-advanced-command-line-parameters.md index 5e240f833ad1..397ab84bd58c 100644 --- a/src/tools/genpolicy/genpolicy-advanced-command-line-parameters.md +++ b/src/tools/genpolicy/genpolicy-advanced-command-line-parameters.md @@ -57,17 +57,29 @@ To enable caching, use the `-u` command line parameter - e.g., $ RUST_LOG=info genpolicy -u -y test.yaml ``` -# Use containerd to pull and manage images -You may specify `-d` to use existing `containerd` installation as image manager. This method supports a wider set of images (e.g., older images with `v1` manifest). Needs `sudo` permission to access socket - e.g., +# Use containerd to pull and manage images (required for managed identity based authentication) + +Prereq: This features needs to run the following script to adapt your docker and containerd config (needs `sudo` access): + +```bash +$ ./setup_containerd_docker.sh +``` + +Optional: Authenticate to private registry. For example in azure: +```bash +$ az acr login -n my_acr_name +``` + +You may specify `-d` to use existing `containerd` installation as image manager. This method supports a wider set of images (e.g., older images with `v1` manifest) - e.g., ```bash -$ sudo genpolicy -d -y test.yaml +$ genpolicy -d -y test.yaml ``` This will use `/var/contaienrd/containerd.sock` as default socket path. Or you may specify your own socket path - e.g., ```bash -$ sudo genpolicy -d=/my/path/containerd.sock -y test.yaml +$ genpolicy -d=/my/path/containerd.sock -y test.yaml ``` # Print the Policy text diff --git a/src/tools/genpolicy/setup_containerd_docker.sh b/src/tools/genpolicy/setup_containerd_docker.sh new file mode 100755 index 000000000000..8e186d684c43 --- /dev/null +++ b/src/tools/genpolicy/setup_containerd_docker.sh @@ -0,0 +1,127 @@ +#!/bin/bash + +# Copyright (c) 2023 Microsoft Corporation + +# This script aims to adapt the system for the genpolicy tool to be able to use containerd pull function properly. +# This is needed for managed identity based authentication to private registries using an identity token. + +# This script needs 'sudo' access. It will: +# - install containerd if not installed already. Genpolicy tool uses containerd to pull image when using -d option +# - ensure cri plugin is NOT disabled in containerd config. This is needed for policy tool to pull image +# - restart containerd or start it if not running already. +# - print containerd socket file location. Use this when running genpolicy tool. Eg genpolicy -d=$SOCKET_FILE_LOCATION -y foo.yaml +# - fix containerd socket file permissions if needed. This is so genpolicy tool is able to access containerd socket file without 'sudo' +# - adapt docker config.json if needed. This is done so 'az acr login' command saves identity token to the docker config + +set -e -x + +# Function to check if a command exists +command_exists() { + command -v "$1" &> /dev/null +} + +# Utility function for error messages and exit +error_exit() { + echo "$1" 1>&2 + exit 1 +} + +# Function to ensure a command is installed +ensure_command_installed() { + if ! command_exists "$1"; then + echo "$1 could not be found, installing..." + sudo apt-get install -y "$1" + if ! command_exists "$1"; then + error_exit "Failed to install $1" + fi + else + echo "$1 is already installed" + fi +} + +sudo apt-get update + +ensure_command_installed containerd + +# Modify containerd config if needed +CONTAINERD_CONFIG_FILE="/etc/containerd/config.toml" + +if [ ! -f "$CONTAINERD_CONFIG_FILE" ]; then + error_exit "Containerd config file not found: $CONTAINERD_CONFIG_FILE. Please update CONTAINERD_CONFIG_FILE in this script to point to the correct containerd config file." +fi + +if grep -q "disabled_plugins.*\['cri'\]" "$CONTAINERD_CONFIG_FILE"; then + echo "Modifying containerd config to enable cri plugin..." + sudo sed -i "s/disabled_plugins.*\['cri'\]/disabled_plugins = []/g" "$CONTAINERD_CONFIG_FILE" +else + echo "CRI plugin is already enabled in containerd config" +fi + +# Restart containerd using systemctl +echo "Restarting containerd service..." +if systemctl is-active --quiet containerd; then + sudo systemctl restart containerd +else + sudo systemctl start containerd +fi + +# Print containerd status +echo "Containerd status:" +sudo systemctl status containerd --no-pager + +# Print containerd socket file location found in config +SOCKET_FILE_LOCATION=$(awk '/\[grpc\]/ {found=1} found && /address *= */ {print $3; exit}' "$CONTAINERD_CONFIG_FILE" | tr -d '"') + +if [ -z "$SOCKET_FILE_LOCATION" ]; then + error_exit "Socket file location not found in config" +fi +echo "Containerd socket file location: $SOCKET_FILE_LOCATION" + +# Wait for the socket file to be created +echo "Waiting for containerd socket file to be created..." +for i in {1..10}; do + if [ -e "$SOCKET_FILE_LOCATION" ]; then + echo "Containerd socket file found: $SOCKET_FILE_LOCATION" + break + fi + echo "Attempt $i: Socket file not found, waiting..." + sleep 1 +done + +if [ ! -e "$SOCKET_FILE_LOCATION" ]; then + error_exit "Socket file not found after waiting: $SOCKET_FILE_LOCATION" +fi + +# Fix containerd socket file permissions +echo "Ensuring containerd socket file permissions are set correctly..." +sudo chmod a+rw "$SOCKET_FILE_LOCATION" + +if ! command_exists docker; then + echo "$1 could not be found, installing..." + sudo apt-get install -y docker.io + if ! command_exists docker; then + error_exit "Failed to install docker.io" + fi +else + echo "docker is already installed" +fi + +ensure_command_installed jq + +# Adapt Docker config if needed +DOCKER_CONFIG_FILE="$HOME/.docker/config.json" +echo "Checking Docker config file: $DOCKER_CONFIG_FILE" + +if [ -f "$DOCKER_CONFIG_FILE" ]; then + if grep -q '"credstore":' "$DOCKER_CONFIG_FILE"; then + echo "Modifying Docker config to remove 'credstore' key..." + jq 'del(.credstore)' "$DOCKER_CONFIG_FILE" > "$DOCKER_CONFIG_FILE.tmp" && mv "$DOCKER_CONFIG_FILE.tmp" "$DOCKER_CONFIG_FILE" + else + echo "'credstore' key not found in Docker config" + fi +else + error_exit "Docker config file not found. Please update DOCKER_CONFIG_FILE in this script to point to the correct Docker config file." +fi + +echo "Script execution completed. Please use $SOCKET_FILE_LOCATION as socker file location." +echo "Eg. genpolicy -d=$SOCKET_FILE_LOCATION -y foo.yaml" \ No newline at end of file