run-spaceapp 0.1.17 → 0.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/index.mjs +25 -8
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "run-spaceapp",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"spaceappRuntimeVersion": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
|
+
"spaceappRuntimeVersion": "0.1.19",
|
|
5
5
|
"spaceappHostRootRuntimeCompatible": true,
|
|
6
6
|
"description": "Cross-platform Docker launcher for the SpaceApp self-hosted agent workspace",
|
|
7
7
|
"license": "Apache-2.0",
|
|
@@ -52,5 +52,5 @@
|
|
|
52
52
|
"access": "public",
|
|
53
53
|
"provenance": true
|
|
54
54
|
},
|
|
55
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "482d6e8db5b39ab0e3002f016a336e5a28288dc8"
|
|
56
56
|
}
|
package/src/index.mjs
CHANGED
|
@@ -23,6 +23,7 @@ const CONFIG_SCHEMA_VERSION = 3;
|
|
|
23
23
|
const MIN_INSTALL_CPU_COUNT = 4;
|
|
24
24
|
const MIN_INSTALL_MEMORY_BYTES = 7 * 1024 ** 3;
|
|
25
25
|
const MIN_INSTALL_MEMORY_LABEL = "7 GiB usable (8 GB-class system)";
|
|
26
|
+
const CONTAINER_SECRET_MODE = 0o644;
|
|
26
27
|
const MIN_INSTALL_FREE_DISK_BYTES = 15 * 1024 ** 3;
|
|
27
28
|
const PROFILE_RUNTIME_SETTINGS = Object.freeze({
|
|
28
29
|
light: Object.freeze({
|
|
@@ -603,8 +604,9 @@ export async function prepareInstallation(root, {
|
|
|
603
604
|
throw error;
|
|
604
605
|
}
|
|
605
606
|
postgresPassword = randomBytes(32).toString("base64url");
|
|
606
|
-
await atomicWrite(postgresPasswordPath, postgresPassword);
|
|
607
|
+
await atomicWrite(postgresPasswordPath, postgresPassword, CONTAINER_SECRET_MODE);
|
|
607
608
|
}
|
|
609
|
+
await ensureContainerSecretReadable(postgresPasswordPath);
|
|
608
610
|
const databaseUrlPath = join(root, "secrets", "database-url");
|
|
609
611
|
try {
|
|
610
612
|
await stat(databaseUrlPath);
|
|
@@ -615,9 +617,11 @@ export async function prepareInstallation(root, {
|
|
|
615
617
|
const encodedPassword = encodeURIComponent(postgresPassword);
|
|
616
618
|
await atomicWrite(
|
|
617
619
|
databaseUrlPath,
|
|
618
|
-
`postgresql://spaceapp:${encodedPassword}@postgres:5432/spaceapp
|
|
620
|
+
`postgresql://spaceapp:${encodedPassword}@postgres:5432/spaceapp`,
|
|
621
|
+
CONTAINER_SECRET_MODE
|
|
619
622
|
);
|
|
620
623
|
}
|
|
624
|
+
await ensureContainerSecretReadable(databaseUrlPath);
|
|
621
625
|
|
|
622
626
|
const sessionSecretPath = join(root, "secrets", "session-secret");
|
|
623
627
|
try {
|
|
@@ -626,8 +630,9 @@ export async function prepareInstallation(root, {
|
|
|
626
630
|
if (error?.code !== "ENOENT") {
|
|
627
631
|
throw error;
|
|
628
632
|
}
|
|
629
|
-
await atomicWrite(sessionSecretPath, randomBytes(48).toString("base64url"));
|
|
633
|
+
await atomicWrite(sessionSecretPath, randomBytes(48).toString("base64url"), CONTAINER_SECRET_MODE);
|
|
630
634
|
}
|
|
635
|
+
await ensureContainerSecretReadable(sessionSecretPath);
|
|
631
636
|
|
|
632
637
|
const setupTokenPath = join(root, "secrets", "setup-token");
|
|
633
638
|
let setupToken = null;
|
|
@@ -638,8 +643,9 @@ export async function prepareInstallation(root, {
|
|
|
638
643
|
throw error;
|
|
639
644
|
}
|
|
640
645
|
setupToken = randomBytes(32).toString("base64url");
|
|
641
|
-
await atomicWrite(setupTokenPath, setupToken);
|
|
646
|
+
await atomicWrite(setupTokenPath, setupToken, CONTAINER_SECRET_MODE);
|
|
642
647
|
}
|
|
648
|
+
await ensureContainerSecretReadable(setupTokenPath);
|
|
643
649
|
return { config, setupToken };
|
|
644
650
|
}
|
|
645
651
|
|
|
@@ -707,20 +713,31 @@ function formatGibibytes(bytes) {
|
|
|
707
713
|
return Math.floor((bytes / 1024 ** 3) * 10) / 10;
|
|
708
714
|
}
|
|
709
715
|
|
|
710
|
-
async function atomicWrite(target, value) {
|
|
716
|
+
async function atomicWrite(target, value, mode = 0o600) {
|
|
711
717
|
await mkdir(dirname(target), { recursive: true, mode: 0o700 });
|
|
712
718
|
const temporary = `${target}.tmp-${process.pid}-${randomBytes(6).toString("hex")}`;
|
|
713
719
|
try {
|
|
714
|
-
await writeFile(temporary, value, { encoding: "utf8", mode
|
|
715
|
-
await chmod(temporary,
|
|
720
|
+
await writeFile(temporary, value, { encoding: "utf8", mode, flag: "wx" });
|
|
721
|
+
await chmod(temporary, mode);
|
|
716
722
|
await rename(temporary, target);
|
|
717
|
-
await chmod(target,
|
|
723
|
+
await chmod(target, mode);
|
|
718
724
|
} catch (error) {
|
|
719
725
|
await rm(temporary, { force: true }).catch(() => {});
|
|
720
726
|
throw error;
|
|
721
727
|
}
|
|
722
728
|
}
|
|
723
729
|
|
|
730
|
+
async function ensureContainerSecretReadable(path) {
|
|
731
|
+
if (process.platform === "win32") {
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
734
|
+
await chmod(path, CONTAINER_SECRET_MODE).catch((error) => {
|
|
735
|
+
if (error?.code !== "ENOENT") {
|
|
736
|
+
throw error;
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
|
|
724
741
|
function defaultTemplateDir() {
|
|
725
742
|
return resolve(dirname(fileURLToPath(import.meta.url)), "../templates");
|
|
726
743
|
}
|