Private docker registry enhancements. (#142)

Got private docker registry working without secure mode. Feature disabled by default.
This commit is contained in:
Ravin Perera
2022-05-20 17:04:20 +05:30
committed by GitHub
parent 0f9eae8c8c
commit 8e0d18bad3
12 changed files with 91 additions and 74 deletions

View File

@@ -78,7 +78,7 @@ target_precompile_headers(sagent PUBLIC src/pchheader.hpp)
add_custom_target(installer
COMMAND mkdir -p ./build/installer
COMMAND bash -c "cp -r ./build/{sagent,sashi,hpfs,user-install.sh,user-uninstall.sh,contract_template} ./build/installer/"
COMMAND bash -c "cp -r ./installer/{docker-install.sh,registry-install.sh,registry-uninstall.sh,prereq.sh,sashimono-install.sh,sashimono-uninstall.sh} ./build/installer/"
COMMAND bash -c "cp -r ./installer/{docker-install.sh,docker-registry-install.sh,docker-registry-uninstall.sh,prereq.sh,sashimono-install.sh,sashimono-uninstall.sh} ./build/installer/"
COMMAND bash -c "cp -r ./dependencies/{user-cgcreate.sh,libblake3.so,licence.txt} ./build/installer/"
COMMAND bash -c "cp -r ./mb-xrpl/dist ./build/installer/mb-xrpl"
COMMAND tar cfz ./build/installer.tar.gz --directory=./build/ installer

View File

@@ -13,8 +13,10 @@ contract_gid=$7
peer_port=$8
user_port=$9
docker_image=${10}
if [ -z "$cpu" ] || [ -z "$memory" ] || [ -z "$swapmem" ] || [ -z "$disk" ] || [ -z "$contract_dir" ] || [ -z "$contract_uid" ] || [ -z "$contract_gid" ] || [ -z "$peer_port" ] || [ -z "$user_port" ]; then
echo "Expected: user-install.sh <cpu quota microseconds> <memory quota kbytes> <swap quota kbytes> <disk quota kbytes> <contract dir> <contract uid> <contract gid> <peer_port> <user_port>"
docker_registry=${11}
if [ -z "$cpu" ] || [ -z "$memory" ] || [ -z "$swapmem" ] || [ -z "$disk" ] || [ -z "$contract_dir" ] ||
[ -z "$contract_uid" ] || [ -z "$contract_gid" ] || [ -z "$peer_port" ] || [ -z "$user_port" ] ||
[ -z "$docker_image" ] || [ -z "$docker_registry" ]; then
echo "INVALID_PARAMS,INST_ERR" && exit 1
fi
@@ -160,6 +162,8 @@ echo "[Service]
echo "Applying $docker_service extra args."
exec_original="ExecStart=$docker_bin/dockerd-rootless.sh"
exec_replace="$exec_original --max-concurrent-downloads 1"
# Add private docker registry information.
[ "$docker_registry" != "-" ] && exec_replace="$exec_replace --registry-mirror http://$docker_registry --insecure-registry $docker_registry"
sed -i "s%$exec_original%$exec_replace%" $user_dir/.config/systemd/user/$docker_service
# Reload the docker service.

View File

@@ -1,11 +1,10 @@
#!/bin/bash
# Sashimono docker registry installation script.
# Sashimono private docker registry installation script.
# This acts as a pull-through cache to the public docker hub registry.
docker_bin=$1
user=$2
port=$3
hubacc="evernodedev"
images=("sashimono:hp.latest-ubt.20.04" "sashimono:hp.latest-ubt.20.04-njs.16")
user=$DOCKER_REGISTRY_USER
port=$DOCKER_REGISTRY_PORT
hubregistry="https://index.docker.io"
user_dir=/home/$user
# Waits until a service becomes ready up to 3 seconds.
@@ -37,7 +36,7 @@ dockerd_socket="unix://$user_runtime_dir/docker.sock"
# Setup env variables for the user.
echo "
export XDG_RUNTIME_DIR=$user_runtime_dir
export PATH=$docker_bin:\$PATH
export PATH=$DOCKER_BIN:\$PATH
export DOCKER_HOST=$dockerd_socket" >>"$user_dir"/.bashrc
echo "Updated user .bashrc."
@@ -51,22 +50,13 @@ done
[ "$user_systemd" != "running" ] && rollback "NO_SYSTEMD"
echo "Installing rootless dockerd for user."
sudo -H -u "$user" PATH="$docker_bin":"$PATH" XDG_RUNTIME_DIR="$user_runtime_dir" "$docker_bin"/dockerd-rootless-setuptool.sh install
sudo -H -u "$user" PATH="$DOCKER_BIN":"$PATH" XDG_RUNTIME_DIR="$user_runtime_dir" "$DOCKER_BIN"/dockerd-rootless-setuptool.sh install
service_ready "docker.service" || rollback "NO_DOCKERSVC"
echo "Installed rootless dockerd for docker registry."
# Run the docker registry container on port 4444
DOCKER_HOST=$dockerd_socket $docker_bin/docker run -d -p $port:5000 --restart=always --name registry registry:2
# Run the docker registry container on specified port.
DOCKER_HOST=$dockerd_socket $DOCKER_BIN/docker run -d -p $port:5000 --restart=always --name registry -e REGISTRY_PROXY_REMOTEURL=$hubregistry registry:2
echo "Docker registry listening at $port"
# Prefetch the required docker images.
echo "Pulling Sashimono base contract images..."
for img in ${images[@]}; do
DOCKER_HOST=$dockerd_socket $docker_bin/docker pull $hubacc/$img
DOCKER_HOST=$dockerd_socket $docker_bin/docker tag $hubacc/$img localhost:$port/$img
DOCKER_HOST=$dockerd_socket $docker_bin/docker push localhost:$port/$img
DOCKER_HOST=$dockerd_socket $docker_bin/docker rmi $hubacc/$img
done
exit 0

View File

@@ -1,15 +1,14 @@
#!/bin/bash
# Sashimono docker registry installation script.
docker_bin=$1
user=$2
user=$DOCKER_REGISTRY_USER
# Check if users exists.
if [[ $(id -u "$user" 2>/dev/null || echo -1) -ge 0 ]]; then
:
:
else
echo "$user does not exist."
exit 1
echo "$user does not exist."
exit 0
fi
user_dir=/home/$user
@@ -18,8 +17,7 @@ user_runtime_dir="/run/user/$user_id"
# Uninstall rootless dockerd.
echo "Uninstalling rootless dockerd."
sudo -H -u "$user" PATH="$docker_bin":"$PATH" XDG_RUNTIME_DIR="$user_runtime_dir" "$docker_bin"/dockerd-rootless-setuptool.sh uninstall
sudo -H -u "$user" PATH="$DOCKER_BIN":"$PATH" XDG_RUNTIME_DIR="$user_runtime_dir" "$DOCKER_BIN"/dockerd-rootless-setuptool.sh uninstall
# Gracefully terminate user processes.
echo "Terminating user processes."

View File

@@ -104,7 +104,7 @@ rm -r "$SASHIMONO_DATA"/{contract_template,licence.txt} >/dev/null 2>&1
cp -r "$script_dir"/{contract_template,licence.txt} $SASHIMONO_DATA
# Install Sashimono agent binaries into sashimono bin dir.
cp "$script_dir"/{sagent,hpfs,user-cgcreate.sh,user-install.sh,user-uninstall.sh} $SASHIMONO_BIN
cp "$script_dir"/{sagent,hpfs,user-cgcreate.sh,user-install.sh,user-uninstall.sh,docker-registry-uninstall.sh} $SASHIMONO_BIN
chmod -R +x $SASHIMONO_BIN
# Copy Blake3 and update linker library cache.
@@ -123,11 +123,14 @@ mkdir -p $DOCKER_BIN
[ -z "$(ls -A $DOCKER_BIN 2>/dev/null)" ] && echo "Rootless Docker installation failed." && rollback
# Install private docker registry.
# stage "Installing private docker registry"
# (Disabled until secure registry configuration)
# ./registry-install.sh $DOCKER_BIN $DOCKER_REGISTRY_USER $DOCKER_REGISTRY_PORT
# [ "$?" == "1" ] && rollback
# registry_addr=$inetaddr:$DOCKER_REGISTRY_PORT
if [ "$DOCKER_REGISTRY_PORT" != "0" ]; then
stage "Installing private docker registry"
# TODO: secure registry configuration
"$script_dir"/docker-registry-install.sh
[ "$?" == "1" ] && echo "Private docker registry installation failed." && rollback
else
echo "Private docker registry installation skipped"
fi
# If installing with sudo, add current logged-in user to Sashimono admin group.
[ -n "$SUDO_USER" ] && usermod -a -G $SASHIADMIN_GROUP $SUDO_USER
@@ -168,7 +171,7 @@ if [ -f $SASHIMONO_DATA/sa.cfg ]; then
echo "Existing Sashimono data directory found. Updating..."
! $SASHIMONO_BIN/sagent upgrade $SASHIMONO_DATA && rollback
else
! $SASHIMONO_BIN/sagent new $SASHIMONO_DATA $inetaddr $inst_count $cpuMicroSec $ramKB $swapKB $diskKB && rollback
! $SASHIMONO_BIN/sagent new $SASHIMONO_DATA $inetaddr $DOCKER_REGISTRY_PORT $inst_count $cpuMicroSec $ramKB $swapKB $diskKB && rollback
fi
if [[ "$NO_MB" == "" && -f $MB_XRPL_DATA/mb-xrpl.cfg ]]; then

View File

@@ -87,8 +87,8 @@ rm $service_path
# Reload the systemd daemon after removing the service
systemctl daemon-reload
# echo "Removing Sashimono private docker registry..."
# ./registry-uninstall.sh $DOCKER_BIN $DOCKER_REGISTRY_USER
echo "Removing Sashimono private docker registry..."
$SASHIMONO_BIN/docker-registry-uninstall.sh
# Delete binaries except message board and sashimnono uninstall script.
# We keep uninstall script so user can uninstall again if error occured at later steps.

View File

@@ -31,11 +31,13 @@ export SASHIADMIN_GROUP="sashiadmin"
export SASHIUSER_GROUP="sashiuser"
export SASHIUSER_PREFIX="sashi"
export MB_XRPL_USER="sashimbxrpl"
export DOCKER_REGISTRY_USER="sashidockerreg"
export DOCKER_REGISTRY_PORT=4444
export CG_SUFFIX="-cg"
export EVERNODE_REGISTRY_ADDRESS="rDsg8R6MYfEB7Da861ThTRzVUWBa3xJgWL"
# Private docker registry (not used for now)
export DOCKER_REGISTRY_USER="sashidockerreg"
export DOCKER_REGISTRY_PORT=0
# Configuring the sashimono service is the last stage of the installation.
# So if the service exists, Previous sashimono installation has been complete.
[ -f /etc/systemd/system/$SASHIMONO_SERVICE.service ] && sashimono_installed=true || sashimono_installed=false

View File

@@ -33,7 +33,7 @@ namespace conf
* Create config here.
* @return 0 for success. -1 for failure.
*/
int create(std::string_view host_addr, std::string_view registry_addr, const size_t inst_count,
int create(std::string_view host_addr, const uint16_t docker_registry_port, const size_t inst_count,
const size_t cpu_us, const size_t ram_kbytes, const size_t swap_kbytes, const size_t disk_kbytes)
{
if (util::is_file_exists(ctx.config_file))
@@ -69,9 +69,10 @@ namespace conf
cfg.system.max_cpu_us = !cpu_us ? 900000 : cpu_us; // Total CPU allocation out of 1000000 microsec (1 sec).
cfg.system.max_storage_kbytes = !disk_kbytes ? 5242880 : disk_kbytes;
const std::string img_prefix = registry_addr.empty() ? "evernodedev" : std::string(registry_addr);
const std::string img_prefix = "evernodedev";
cfg.docker.images["hp.latest-ubt.20.04"] = img_prefix + "/sashimono:hp.latest-ubt.20.04";
cfg.docker.images["hp.latest-ubt.20.04-njs.16"] = img_prefix + "/sashimono:hp.latest-ubt.20.04-njs.16";
cfg.docker.registry_port = docker_registry_port;
cfg.log.max_file_count = 50;
cfg.log.max_mbytes_per_file = 10;
@@ -269,6 +270,9 @@ namespace conf
for (const auto &elem : docker["images"].object_range())
cfg.docker.images[elem.key()] = elem.value().as<std::string>();
if (docker.contains("registry_port"))
cfg.docker.registry_port = docker["registry_port"].as<uint16_t>();
}
catch (const std::exception &e)
{
@@ -300,6 +304,10 @@ namespace conf
}
}
// If docker registry port is 0, we assume there's no private docker registry.
if (cfg.docker.registry_port > 0)
cfg.docker.registry_address = cfg.hp.host_address + ":" + std::to_string(cfg.docker.registry_port);
return 0;
}
@@ -346,6 +354,7 @@ namespace conf
for (const auto &[key, name] : cfg.docker.images)
images.insert_or_assign(key, name);
docker_config.insert_or_assign("images", images);
docker_config.insert_or_assign("registry_port", cfg.docker.registry_port);
d.insert_or_assign("docker", docker_config);
}
@@ -412,7 +421,7 @@ namespace conf
* Convert string to Log Severity enum type.
* @param severity log severity code.
* @return log severity type.
*/
*/
LOG_SEVERITY get_loglevel_type(std::string_view severity)
{
if (severity == "dbg")

View File

@@ -85,6 +85,8 @@ namespace conf
struct docker_config
{
std::unordered_map<std::string, std::string> images;
uint16_t registry_port = 0; // 0 means bypass private docker registry.
std::string registry_address; // This is dynamically constructed at load time.
};
struct sa_config
@@ -123,7 +125,7 @@ namespace conf
int init();
int create(std::string_view host_addr, std::string_view registry_addr, const size_t inst_count,
int create(std::string_view host_addr, const uint16_t docker_registry_port, const size_t inst_count,
const size_t cpu_us, const size_t ram_kbytes, const size_t swap_kbytes, const size_t disk_kbytes);
void set_dir_paths(std::string exepath, std::string datadir);

View File

@@ -851,7 +851,8 @@ namespace hp
std::to_string(contract_ugid.gid),
std::to_string(instance_ports.peer_port),
std::to_string(instance_ports.user_port),
docker_image};
docker_image,
conf::cfg.docker.registry_address};
std::vector<std::string> output_params;
if (util::execute_bash_file(conf::ctx.user_install_sh, output_params, input_params) == -1)
return -1;

View File

@@ -132,17 +132,20 @@ int main(int argc, char **argv)
// This will create a new config.
const std::string host_addr = (argc >= 4) ? argv[3] : "";
uint16_t docker_registry_port = 0;
size_t inst_count = 0, cpu_us = 0, ram_kbytes = 0, swap_kbytes = 0, disk_kbytes = 0;
if (((argc >= 5) && (util::stoull(argv[4], inst_count) != 0 || inst_count == 0)) ||
((argc >= 6) && (util::stoull(argv[5], cpu_us) != 0 || cpu_us == 0)) ||
((argc >= 7) && (util::stoull(argv[6], ram_kbytes) != 0 || ram_kbytes == 0)) ||
((argc >= 8) && (util::stoull(argv[7], swap_kbytes) != 0 || swap_kbytes == 0)) ||
((argc >= 9) && (util::stoull(argv[8], disk_kbytes) != 0 || disk_kbytes == 0)) ||
conf::create(host_addr, "", inst_count, cpu_us, ram_kbytes, swap_kbytes, disk_kbytes) != 0)
if (((argc >= 5) && util::stoul(argv[4], docker_registry_port) != 0) ||
((argc >= 6) && (util::stoull(argv[5], inst_count) != 0 || inst_count == 0)) ||
((argc >= 7) && (util::stoull(argv[6], cpu_us) != 0 || cpu_us == 0)) ||
((argc >= 8) && (util::stoull(argv[7], ram_kbytes) != 0 || ram_kbytes == 0)) ||
((argc >= 9) && (util::stoull(argv[8], swap_kbytes) != 0 || swap_kbytes == 0)) ||
((argc >= 10) && (util::stoull(argv[9], disk_kbytes) != 0 || disk_kbytes == 0)) ||
conf::create(host_addr, docker_registry_port, inst_count, cpu_us, ram_kbytes, swap_kbytes, disk_kbytes) != 0)
{
std::cerr << "Invalid Sashimono Agent config creation args.\n";
std::cerr << inst_count << ", " << cpu_us << ", " << ram_kbytes << ", " << swap_kbytes << ", " << disk_kbytes << "\n";
std::cerr << docker_registry_port << ", " << inst_count << ", " << cpu_us << ", " << ram_kbytes << ", "
<< swap_kbytes << ", " << disk_kbytes << "\n";
return 1;
}
}
@@ -195,8 +198,11 @@ int main(int argc, char **argv)
salog::init();
// Do a simple version change in the config.
// In the future we could have real upgrade/data migration logic here.
conf::cfg.version = version::AGENT_VERSION;
if (conf::cfg.docker.registry_port == 0)
conf::cfg.docker.registry_port = 4444;
if (conf::write_config(conf::cfg) != 0)
return -1;
}

View File

@@ -39,7 +39,7 @@ namespace util
}
/**
* Check whether given directory exists.
* Check whether given directory exists.
* @param path Directory path.
* @return Returns true if given directory exists otherwise false.
*/
@@ -50,7 +50,7 @@ namespace util
}
/**
* Check whether given file exists.
* Check whether given file exists.
* @param path File path.
* @return Returns true if give file exists otherwise false.
*/
@@ -61,7 +61,7 @@ namespace util
}
/**
* Recursively creates directories and sub-directories if not exist.
* Recursively creates directories and sub-directories if not exist.
* @param path Directory path.
* @return Returns 0 operations succeeded otherwise -1.
*/
@@ -99,12 +99,12 @@ namespace util
}
/**
* Reads the entire file from given file discriptor.
* Reads the entire file from given file discriptor.
* @param fd File descriptor to be read.
* @param buf String buffer to be populated.
* @param offset Begin offset of the file to read.
* @return Returns number of bytes read in a successful read and -1 on error.
*/
*/
int read_from_fd(const int fd, std::string &buf, const off_t offset)
{
struct stat st;
@@ -123,7 +123,7 @@ namespace util
* Provide a safe std::string overload for realpath.
* @param path Path.
* @returns Returns the realpath as string.
*/
*/
const std::string realpath(std::string_view path)
{
std::array<char, PATH_MAX> buffer;
@@ -174,8 +174,8 @@ namespace util
}
/**
* Returns current time in UNIX epoch milliseconds.
*/
* Returns current time in UNIX epoch milliseconds.
*/
uint64_t get_epoch_milliseconds()
{
return std::chrono::duration_cast<std::chrono::duration<std::uint64_t, std::milli>>(
@@ -218,7 +218,7 @@ namespace util
* Split string by given delimeter.
* @param collection Splitted strings params.
* @param delimeter Delimeter to split string.
*/
*/
void split_string(std::vector<std::string> &collection, std::string_view str, std::string_view delimeter)
{
if (str.empty())
@@ -242,11 +242,11 @@ namespace util
}
/**
* Converts given string to a int. A wrapper function for std::stoi.
* Converts given string to a int. A wrapper function for std::stoi.
* @param str String variable.
* @param result Variable to store the answer from the conversion.
* @return Returns 0 in a successful conversion and -1 on error.
*/
*/
int stoi(const std::string &str, int &result)
{
try
@@ -262,11 +262,11 @@ namespace util
}
/**
* Converts given string to a uint16_t. A wrapper function for std::stoul.
* Converts given string to a uint16_t. A wrapper function for std::stoul.
* @param str String variable.
* @param result Variable to store the answer from the conversion.
* @return Returns 0 in a successful conversion and -1 on error.
*/
*/
int stoul(const std::string &str, uint16_t &result)
{
try
@@ -282,11 +282,11 @@ namespace util
}
/**
* Converts given string to a uint_64. A wrapper function for std::stoull.
* Converts given string to a uint_64. A wrapper function for std::stoull.
* @param str String variable.
* @param result Variable to store the answer from the conversion.
* @return Returns 0 in a successful conversion and -1 on error.
*/
*/
int stoull(const std::string &str, uint64_t &result)
{
try
@@ -305,7 +305,7 @@ namespace util
* Construct the user contract directory path when username is given.
* @param username Username of the user.
* @return Contract directory path.
*/
*/
const std::string get_user_contract_dir(const std::string &username, std::string_view container_name)
{
return "/home/" + username + "/" + container_name.data();
@@ -316,7 +316,7 @@ namespace util
* @param username Username of the user.
* @param user_info User info struct to be populated.
* @return -1 of error, 0 on success.
*/
*/
int get_system_user_info(std::string_view username, user_info &user_info)
{
const struct passwd *pwd = getpwnam(username.data());
@@ -339,7 +339,7 @@ namespace util
* @param str String to be modified.
* @param find Substring to be searched.
* @param replace Substring to be replaced.
*/
*/
void find_and_replace(std::string &str, std::string_view find, std::string_view replace)
{
size_t pos = str.find(find);
@@ -418,13 +418,15 @@ namespace util
* @param file_name Name of the bash script.
* @param output_params Final output of the bash script.
* @param input_params Input parameters to the bash script (Optional).
*/
*/
int execute_bash_file(std::string_view file_name, std::vector<std::string> &output_params, const std::vector<std::string_view> &input_params)
{
std::string params = "";
for (auto itr = input_params.begin(); itr != input_params.end(); itr++)
{
params.append(*itr);
// Empty params are appended as '-' to preserve param order.
params.append(itr->empty() ? "-" : *itr);
if (std::next(itr) != input_params.end())
params.append(" ");
}
@@ -466,7 +468,7 @@ namespace util
* @param output Pointer to populate output.
* @param output_len Length of the output.
* @return 0 on success and -1 on error.
*/
*/
int execute_bash_cmd(const char *command, char *output, const int output_len)
{
FILE *fpipe = popen(command, "r");