Hallelujah

This commit is contained in:
Radon Rosborough 2021-06-15 05:11:44 +00:00
parent 4e86dfc567
commit ddb2fa0d4b
12 changed files with 121 additions and 97 deletions

View File

@ -73,32 +73,24 @@ endif
IMAGE_HASH := -e RIJU_IMAGE_HASH="$$(docker inspect riju:$(LANG_TAG) | jq '.[0].Config.Labels["riju.image-hash"]' -r)"
shell: # I=<shell> [L=<lang>] [E=1] [P1|P2=<port>] : Launch Docker image with shell
shell: # I=<shell> [L=<lang>] [E[E]=1] [P1|P2=<port>] : Launch Docker image with shell
@: $${I}
ifneq (,$(filter $(I),admin ci))
@mkdir -p $(HOME)/.aws $(HOME)/.docker $(HOME)/.ssh $(HOME)/.terraform.d
docker run -it --rm --hostname $(I) -v $(VOLUME_MOUNT):/src -v /var/run/docker.sock:/var/run/docker.sock -v $(HOME)/.aws:/var/riju/.aws -v $(HOME)/.docker:/var/riju/.docker -v $(HOME)/.ssh:/var/riju/.ssh -v $(HOME)/.terraform.d:/var/riju/.terraform.d -e AWS_REGION -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e DOCKER_USERNAME -e DOCKER_PASSWORD -e DEPLOY_SSH_PRIVATE_KEY -e DOCKER_REPO -e S3_BUCKET -e DOMAIN -e VOLUME_MOUNT=$(VOLUME_MOUNT) $(SHELL_PORTS) $(SHELL_ENV) $(IMAGE_HASH) --network host riju:$(I) $(BASH_CMD)
docker run -it --rm --hostname $(I) -v $(VOLUME_MOUNT):/src -v /var/run/docker.sock:/var/run/docker.sock -v $(HOME)/.aws:/var/run/riju/.aws -v $(HOME)/.docker:/var/run/riju/.docker -v $(HOME)/.ssh:/var/run/riju/.ssh -v $(HOME)/.terraform.d:/var/run/riju/.terraform.d -e AWS_REGION -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e DOCKER_USERNAME -e DOCKER_PASSWORD -e DEPLOY_SSH_PRIVATE_KEY -e DOCKER_REPO -e S3_BUCKET -e DOMAIN -e VOLUME_MOUNT=$(VOLUME_MOUNT) $(SHELL_PORTS) $(SHELL_ENV) $(IMAGE_HASH) --network host riju:$(I) $(BASH_CMD)
else ifeq ($(I),app)
docker run -it --rm --hostname $(I) $(SHELL_PORTS) $(SHELL_ENV) $(IMAGE_HASH) riju:$(I) $(BASH_CMD)
docker run -it --rm --hostname $(I) -v /var/run/riju:/var/run/riju -v /var/run/docker.sock:/var/run/docker.sock $(SHELL_PORTS) $(SHELL_ENV) $(IMAGE_HASH) riju:$(I) $(BASH_CMD)
else ifneq (,$(filter $(I),base lang))
ifeq ($(I),lang)
@: $${L}
endif
docker run -it --rm --hostname $(LANG_TAG) -v $(VOLUME_MOUNT):/src --label riju-install-target=yes $(SHELL_PORTS) $(SHELL_ENV) $(IMAGE_HASH) riju:$(LANG_TAG) $(BASH_CMD)
docker run -it --rm --hostname $(LANG_TAG) -v $(VOLUME_MOUNT):/src $(SHELL_PORTS) $(SHELL_ENV) $(IMAGE_HASH) riju:$(LANG_TAG) $(BASH_CMD)
else ifeq ($(I),runtime)
docker run -it --rm --hostname $(I) -v $(VOLUME_MOUNT):/src -v /var/run/docker.sock:/var/run/docker.sock $(SHELL_PORTS) $(SHELL_ENV) $(IMAGE_HASH) riju:$(I) $(BASH_CMD)
docker run -it --rm --hostname $(I) -v $(VOLUME_MOUNT):/src -v /var/run/riju:/var/run/riju -v /var/run/docker.sock:/var/run/docker.sock $(SHELL_PORTS) $(SHELL_ENV) $(IMAGE_HASH) riju:$(I) $(BASH_CMD)
else
docker run -it --rm --hostname $(I) -v $(VOLUME_MOUNT):/src $(SHELL_PORTS) $(SHELL_ENV) $(IMAGE_HASH) riju:$(I) $(BASH_CMD)
endif
## This is equivalent to 'make pkg' in a fresh packaging container
## followed by 'make install' in a persistent runtime container.
repkg: script # L=<lang> T=<type> : Build fresh .deb and install into live container
@: $${L} $${T}
$(MAKE_QUIETLY) shell I=packaging CMD="make pkg L=$(L) T=$(T)"
ctr="$$(docker container ls -f label="riju-install-target=yes" -l -q)"; test "$${ctr}" || (echo "no valid container is live"; exit 1); docker exec "$${ctr}" make install L=$(L) T=$(T)
### Build packaging scripts
script: # L=<lang> T=<type> : Generate a packaging script

View File

@ -48,7 +48,6 @@ export class Session {
};
privilegedSession = () => util.privilegedSession(this.context);
privilegedWait = () => util.privilegedWait(this.context);
privilegedExec = (cmdline) =>
util.privilegedExec(this.context, bash(cmdline));
privilegedPty = (cmdline) =>
@ -64,13 +63,6 @@ export class Session {
this.container = {
pty: containerPty,
};
containerPty.on("data", (data) =>
this.send({
event: "serviceLog",
service: "container",
output: data.toString("utf8"),
})
);
containerPty.on("close", (code, signal) =>
this.send({
event: "serviceFailed",
@ -85,7 +77,26 @@ export class Session {
error: `${err}`,
})
);
await this.run(this.privilegedWait(this.context));
let buffer = "";
await new Promise((resolve) => {
containerPty.on("data", (data) => {
buffer += data;
let idx;
while ((idx = buffer.indexOf("\r\n")) !== -1) {
const line = buffer.slice(0, idx);
buffer = buffer.slice(idx + 2);
if (line === "riju: container ready") {
resolve();
} else {
this.send({
event: "serviceLog",
service: "container",
output: line + "\n",
})
}
}
});
});
if (this.config.setup) {
await this.run(this.privilegedExec(this.config.setup));
}

View File

@ -11,7 +11,6 @@ import {
privilegedExec,
privilegedPty,
privilegedSession,
privilegedWait,
quote,
run,
} from "./util.js";
@ -38,7 +37,22 @@ async function main() {
const session = pty.spawn(sessionArgs[0], sessionArgs.slice(1), {
name: "xterm-color",
});
await run(privilegedWait({ uuid }), log);
let buffer = "";
await new Promise((resolve) => {
session.on("data", (data) => {
buffer += data;
let idx;
while ((idx = buffer.indexOf("\r\n")) !== -1) {
const line = buffer.slice(0, idx);
buffer = buffer.slice(idx + 2);
if (line === "riju: container ready") {
resolve();
} else {
console.error(line);
}
}
});
});
const args = privilegedPty(
{ uuid },
bash(

View File

@ -51,10 +51,6 @@ export function privilegedSession({ uuid, lang }) {
return [rijuSystemPrivileged, "session", uuid, lang];
}
export function privilegedWait({ uuid }) {
return [rijuSystemPrivileged, "wait", uuid];
}
export function privilegedExec({ uuid }, args) {
return [rijuSystemPrivileged, "exec", uuid].concat(args);
}

View File

@ -6,5 +6,5 @@ RUN /tmp/install.bash
WORKDIR /src
COPY docker/shared/my_init /usr/local/sbin/
COPY docker/shared/admin-pid1.bash /usr/local/sbin/pid1.bash
ENTRYPOINT ["/usr/local/sbin/my_init", "--quiet", "--", "/usr/local/sbin/pid1.bash"]
ENTRYPOINT ["/usr/local/sbin/my_init", "--quiet", "--skip-runit", "--", "/usr/local/sbin/pid1.bash"]
CMD ["bash"]

View File

@ -24,7 +24,7 @@ COPY langs ./langs/
FROM riju:runtime
ENTRYPOINT ["/usr/local/sbin/my_init", "--quiet", "--"]
ENTRYPOINT ["/usr/local/sbin/my_init", "--quiet", "--skip-runit","--"]
RUN useradd -p '!' -m -l -s /usr/bin/bash riju
COPY --chown=riju:riju --from=build /src ./
RUN chown root:riju system/out/*-privileged && chmod a=,g=rx,u=rwxs system/out/*-privileged

View File

@ -8,5 +8,5 @@ RUN runuser -u riju -- mkdir /home/riju/src
WORKDIR /home/riju/src
COPY docker/shared/my_init /usr/local/sbin/
ENTRYPOINT ["/usr/local/sbin/my_init", "--quiet", "--"]
ENTRYPOINT ["/usr/local/sbin/my_init", "--quiet", "--skip-runit", "--"]
CMD ["bash"]

View File

@ -6,5 +6,5 @@ RUN /tmp/install.bash
WORKDIR /src
COPY docker/shared/my_init /usr/local/sbin/
COPY docker/shared/admin-pid1.bash /usr/local/sbin/pid1.bash
ENTRYPOINT ["/usr/local/sbin/my_init", "--quiet", "--", "/usr/local/sbin/pid1.bash"]
ENTRYPOINT ["/usr/local/sbin/my_init", "--quiet", "--skip-runit", "--", "/usr/local/sbin/pid1.bash"]
CMD ["bash"]

View File

@ -5,5 +5,5 @@ RUN /tmp/install.bash
WORKDIR /src
COPY docker/shared/my_init docker/packaging/pid1.bash /usr/local/sbin/
ENTRYPOINT ["/usr/local/sbin/my_init", "--quiet", "--", "/usr/local/sbin/pid1.bash"]
ENTRYPOINT ["/usr/local/sbin/my_init", "--quiet", "--skip-runit", "--", "/usr/local/sbin/pid1.bash"]
CMD ["bash"]

View File

@ -4,7 +4,7 @@ COPY docker/runtime/install.bash /tmp/
RUN /tmp/install.bash
COPY docker/shared/my_init docker/runtime/pid1.bash /usr/local/sbin/
ENTRYPOINT ["/usr/local/sbin/my_init", "--quiet", "--", "/usr/local/sbin/pid1.bash"]
ENTRYPOINT ["/usr/local/sbin/my_init", "--quiet", "--skip-runit", "--", "/usr/local/sbin/pid1.bash"]
WORKDIR /src
CMD ["bash"]

View File

@ -7,10 +7,10 @@ tee -a /etc/hosts >/dev/null <<< "127.0.0.1 $(hostname)"
groupadd -g "$(stat -c %g "$PWD")" -o -p '!' -r riju
useradd -u "$(stat -c %u "$PWD")" -g "$(stat -c %g "$PWD")" -o -p '!' -m -N -l -s /usr/bin/bash -G sudo riju
runuser -u riju -- ln -sT /var/riju/.aws /home/riju/.aws
runuser -u riju -- ln -sT /var/riju/.docker /home/riju/.docker
runuser -u riju -- ln -sT /var/riju/.ssh /home/riju/.ssh
runuser -u riju -- ln -sT /var/riju/.terraform.d /home/riju/.terraform.d
runuser -u riju -- ln -sT /var/run/riju/.aws /home/riju/.aws
runuser -u riju -- ln -sT /var/run/riju/.docker /home/riju/.docker
runuser -u riju -- ln -sT /var/run/riju/.ssh /home/riju/.ssh
runuser -u riju -- ln -sT /var/run/riju/.terraform.d /home/riju/.terraform.d
runuser -u riju -- touch /home/riju/.sudo_as_admin_successful
runuser -u riju -- tee -a /home/riju/.bashrc >/dev/null <<"EOF"

View File

@ -1,4 +1,5 @@
#define _GNU_SOURCE
#include <fcntl.h>
#include <errno.h>
#include <grp.h>
#include <signal.h>
@ -8,6 +9,7 @@
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
@ -21,7 +23,6 @@ void die_with_usage()
{
die("usage:\n"
" riju-system-privileged session UUID LANG\n"
" riju-system-privileged wait UUID\n"
" riju-system-privileged exec UUID CMDLINE...\n"
" riju-system-privileged pty UUID CMDLINE...");
}
@ -43,72 +44,88 @@ char *parseLang(char *lang) {
return lang;
}
void session(char *uuid, char *lang)
{
char *image, *container, *hostname;
if (asprintf(&image, "riju:lang-%s", lang) < 0)
die("asprintf failed");
if (asprintf(&container, "riju-session-%s", uuid) < 0)
die("asprintf failed");
if (asprintf(&hostname, "HOSTNAME=%s", lang) < 0)
die("asprintf failed");
char *argv[] = {
"docker",
"run",
"--rm", "-it",
"-e", "HOME=/home/riju",
"-e", hostname,
"-e", "LANG=C.UTF-8",
"-e", "LC_ALL=C.UTF-8",
"-e", "LOGNAME=riju",
"-e", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/bin",
"-e", "PWD=/home/riju/src",
"-e", "SHELL=/usr/bin/bash",
"-e", "TERM=xterm-256color",
"-e", "TMPDIR=/tmp",
"-e", "USER=riju",
"-e", "USERNAME=riju",
"--hostname", lang,
"--name", container,
image, "cat", NULL,
};
execvp(argv[0], argv);
die("execvp failed");
}
void wait_alarm(int signum)
{
(void)signum;
die("container did not come up within 1 second");
}
void wait(char *uuid)
void session(char *uuid, char *lang)
{
char *cmdline;
if (asprintf(&cmdline, "docker inspect riju-session-%s >/dev/null 2>&1", uuid) < 0)
char *image, *container, *hostname, *volume, *fifo;
if (asprintf(&image, "riju:lang-%s", lang) < 0)
die("asprintf failed");
struct timespec ts;
if (asprintf(&container, "riju-session-%s", uuid) < 0)
die("asprintf failed");
if (asprintf(&hostname, "HOSTNAME=%s", lang) < 0)
die("asprintf failed");
int rv = mkdir("/var/run/riju/sentinels", 0700);
if (rv < 0 && errno != EEXIST)
die("mkdir failed");
char tmpdir[] = "/var/run/riju/sentinels/XXXXXX";
if (mkdtemp(tmpdir) == NULL)
die("mkdtemp failed");
if (asprintf(&volume, "%s:/var/run/riju/sentinel", tmpdir) < 0)
die("asprintf failed");
if (asprintf(&fifo, "%s/fifo", tmpdir) < 0)
die("asprintf failed");
if (mknod(fifo, 0700 | S_IFIFO, 0) < 0)
die("mknod failed");
pid_t pid = fork();
if (pid < 0)
die("fork failed");
else if (pid == 0) {
char *argv[] = {
"docker",
"run",
"--rm",
"-v", volume,
"-e", "HOME=/home/riju",
"-e", hostname,
"-e", "LANG=C.UTF-8",
"-e", "LC_ALL=C.UTF-8",
"-e", "LOGNAME=riju",
"-e", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/bin",
"-e", "PWD=/home/riju/src",
"-e", "SHELL=/usr/bin/bash",
"-e", "TERM=xterm-256color",
"-e", "TMPDIR=/tmp",
"-e", "USER=riju",
"-e", "USERNAME=riju",
"--user", "root",
"--hostname", lang,
"--name", container,
image, "cat", "/var/run/riju/sentinel/fifo", NULL,
};
execvp(argv[0], argv);
die("execvp failed");
}
struct timespec ts; // 10ms
ts.tv_sec = 0;
ts.tv_nsec = 1000 * 1000 * 10;
signal(SIGALRM, wait_alarm);
alarm(1);
int fd;
while (1) {
FILE *proc = popen(cmdline, "r");
if (proc == NULL)
die("popen failed");
char buf[1024];
while (fgets(buf, 1024, proc) != NULL);
if (ferror(proc))
die("fgets failed");
int status = pclose(proc);
if (status < 0)
die("pclose failed");
if (WEXITSTATUS(status) == 0)
fd = open(fifo, O_WRONLY);
if (fd >= 0)
break;
if (errno != ENXIO)
die("open failed");
int rv = nanosleep(&ts, NULL);
if (rv != 0 && rv != EINTR)
if (rv != 0 && errno != EINTR)
die("nanosleep failed");
}
signal(SIGALRM, SIG_IGN);
if (unlink(fifo) < 0)
die("unlink failed");
if (rmdir(tmpdir) < 0)
die("rmdir failed");
printf("riju: container ready\n"); // magic string
if (waitpid(pid, NULL, 0) <= 0)
die("waitpid failed");
if (close(fd) < 0)
die("close failed");
}
void exec(char *uuid, int argc, char **cmdline, bool pty)
@ -119,6 +136,7 @@ void exec(char *uuid, int argc, char **cmdline, bool pty)
char *argvPrefix[] = {
"docker",
"exec",
"--user", "riju",
pty ? "-it" : "-i",
container,
};
@ -134,8 +152,8 @@ void exec(char *uuid, int argc, char **cmdline, bool pty)
int main(int argc, char **argv)
{
if (setuid(0) != 0)
die("setuid failed");
if (seteuid(0) != 0)
die("seteuid failed");
if (argc < 2)
die_with_usage();
if (!strcmp(argv[1], "session")) {
@ -146,13 +164,6 @@ int main(int argc, char **argv)
session(uuid, lang);
return 0;
}
if (!strcmp(argv[1], "wait")) {
if (argc != 3)
die_with_usage();
char *uuid = parseUUID(argv[2]);
wait(uuid);
return 0;
}
if (!strcmp(argv[1], "exec")) {
if (argc < 4)
die_with_usage();